You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 9迁移后OpenIddict刷新令牌重启后验证失败求助

.NET 9迁移后OpenIddict 6.0刷新令牌重启后验证失败(invalid_grant)

问题场景

  • 已完成从ASP.NET Core 8到.NET 9的迁移,Azure Entra ID认证流程运行正常
  • 本地离线部署场景使用基于OpenIddict 6.0构建的嵌入式OIDC服务,令牌采用RSA密钥加密
  • .NET 8环境下所有功能正常,升级到.NET 9后,服务器重启后刷新令牌验证失败,返回错误:

OpenIddict.Server.OpenIddictServerDispatcher: Information: The response was successfully returned as a JSON document: {
"error": "invalid_grant",
"error_description": "The specified refresh token is invalid.",
"error_uri": "https://documentation.openiddict.com/errors/ID2003"
}

核心原因

.NET 9对**数据保护(Data Protection)**的默认配置进行了调整,而OpenIddict依赖数据保护系统加密/解密刷新令牌的元数据。如果以下任一环节配置不当,重启后会导致无法验证旧的刷新令牌:

  1. 数据保护密钥仅存储在内存中,重启后丢失
  2. OpenIddict的RSA签名/加密密钥未持久化,重启后生成新密钥
  3. 刷新令牌本身仅存储在内存中,重启后丢失

解决方案

1. 配置数据保护密钥持久化

.NET 9开发环境默认使用内存存储数据保护密钥,重启后会丢失,需显式配置持久化存储:

builder.Services.AddDataProtection()
    .PersistKeysToFileSystem(new DirectoryInfo(@"C:\YourApp\DataProtectionKeys"))
    .SetApplicationName("YourUniqueAppName");

生产环境建议使用分布式存储(如Redis、Azure Blob Storage)替代本地文件系统,确保多实例部署时密钥一致。

2. 持久化OpenIddict的RSA密钥

避免启动时动态生成临时RSA密钥,改用持久化的证书或PEM格式密钥:

// 使用PFX证书(推荐生产环境)
builder.Services.AddOpenIddict()
    .AddServer(options =>
    {
        var cert = new X509Certificate2(@"C:\YourApp\Certificates\AuthCert.pfx", "YourCertPassword");
        options.AddSigningCertificate(cert);
        options.AddEncryptionCertificate(cert);
    });

// 或使用PEM格式密钥文件
builder.Services.AddOpenIddict()
    .AddServer(options =>
    {
        options.AddSigningKey(RSA.Create().ImportFromPem(File.ReadAllText(@"C:\YourApp\Keys\SigningKey.pem")));
        options.AddEncryptionKey(RSA.Create().ImportFromPem(File.ReadAllText(@"C:\YourApp\Keys\EncryptionKey.pem")));
    });

3. 配置刷新令牌持久化存储

如果使用默认内存存储刷新令牌,重启后会丢失,需改用EF Core等持久化存储:

builder.Services.AddOpenIddict()
    .AddServer(options =>
    {
        options.UseEntityFrameworkCore()
               .UseDbContext<YourAppDbContext>()
               .EnableTokenStorage();
    });

4. 迁移.NET 8的Data Protection密钥(可选)

如果需要兼容迁移前生成的刷新令牌,可导出.NET 8的Data Protection密钥并导入到.NET 9环境:

  • .NET 8项目中导出密钥:
var provider = builder.Services.BuildServiceProvider().GetRequiredService<IDataProtectionProvider>();
var keys = provider.GetKeys();
File.WriteAllText(@"C:\YourApp\Keys\DataProtectionKeys.xml", keys.ToXml());
  • .NET 9项目中导入密钥:
builder.Services.AddDataProtection()
    .PersistKeysToFileSystem(new DirectoryInfo(@"C:\YourApp\DataProtectionKeys"))
    .SetApplicationName("YourUniqueAppName")
    .ImportKeysFromXml(File.ReadAllText(@"C:\YourApp\Keys\DataProtectionKeys.xml"));

内容的提问来源于stack exchange,提问作者Niek Jannink

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 08:55:14