.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依赖数据保护系统加密/解密刷新令牌的元数据。如果以下任一环节配置不当,重启后会导致无法验证旧的刷新令牌:
- 数据保护密钥仅存储在内存中,重启后丢失
- OpenIddict的RSA签名/加密密钥未持久化,重启后生成新密钥
- 刷新令牌本身仅存储在内存中,重启后丢失
解决方案
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
相关产品推荐
相关产品推荐

