wjm*_*m03 5 jwt asp.net-core openiddict
我正在尝试实现一个基于 OpenIddict 的身份服务器。我们的用例是一个大型 JavaScript 应用程序,需要对多个后端 API 进行用户身份验证。JavaScript 应用程序使用密码流从专用 OpenIddict 服务器获取令牌。然后,前端调用的各种 API 会验证令牌。
我已经使用 ASP.NET Identity 和 EF 实现了服务器,并且可以成功检索有效令牌。我们的 API 在 AWS Lambda 中运行,因此我们不能(或不想)使用标准.AddDataProtection方法。我们使用存储在 S3 中的自签名证书来生成令牌并验证它们。
那么问题是,当我将 access_token 发送到后端 API 时,它们无法验证令牌并提供访问权限。我知道令牌是有效的,因为我可以使用JwtSecurityTokenHandler自签名证书在 Linqpad 中手动解密它们。
这是我的服务器配置:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddIdentity<ApplicationUser, IdentityRole>(options =>
{
options.ClaimsIdentity.UserNameClaimType = Claims.Name;
options.ClaimsIdentity.UserIdClaimType = Claims.Subject;
options.ClaimsIdentity.RoleClaimType = Claims.Role;
})
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
services.AddOpenIddict()
.AddCore(options =>
{
options.UseEntityFrameworkCore().UseDbContext<ApplicationDbContext>();
})
.AddServer(options =>
{
options.SetTokenEndpointUris("/connect/token");
options.AllowPasswordFlow();
options.AcceptAnonymousClients();
options.AddEncryptionCertificate(MyCustomCertificate);
options.AddSigningCertificate(MyOtherCustomCertificate);
options.UseAspNetCore().EnableTokenEndpointPassthrough();
});
services.AddDbContext<ApplicationDbContext>(options =>
{
options.UseSqlServer(connectionString);
options.UseOpenIddict();
});
}
Run Code Online (Sandbox Code Playgroud)
我在 API 中尝试了两种不同的配置,但都不起作用。选项 1(首选),使用内置 OpenIddict 令牌验证:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddOpenIddict().AddValidation(
options =>
{
options.SetTokenValidationParameters(config =>
{
config.ValidateAudience = false; //just to make sure it's not a typo causing the problem
config.ValidateIssuer = false; //just to make sure it's not a typo causing the problem
config.TokenDecryptionKey = new X509SecurityKey(MyCustomCertificate);
config.IssuerSigningKey = new X509SecurityKey(MyOtherCustomCertificate);
});
options.UseAspNetCore();
});
}
Run Code Online (Sandbox Code Playgroud)
{"error":"invalid_token","error_description":"The specified token is not valid."}即使我可以手动解密和验证令牌,这总是会导致。我尝试将默认日志级别设置为“Trace”,但日志中没有显示任何其他内容可以解释问题所在。
选项 2,使用内置 .NET 令牌验证:
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Authority = "https://openiddictserver";
options.Audience = "clientid";
options.RequireHttpsMetadata = false;
options.IncludeErrorDetails = true;
options.TokenValidationParameters = new TokenValidationParameters()
{
NameClaimType = OpenIdConnectConstants.Claims.Subject,
RoleClaimType = OpenIdConnectConstants.Claims.Role,
ValidateAudience = false, //just to make sure it's not a typo problem
ValidateIssuer = false, //just to make sure it's not a typo problem
TokenDecryptionKey = new X509SecurityKey(MyCustomCertificate),
IssuerSigningKey = new X509SecurityKey(MyOtherCustomCertificate)
};
});
Run Code Online (Sandbox Code Playgroud)
选项 2 只会导致 401 错误,没有任何有用的信息。
更多背景信息:
id_token我可以很好地验证签名。只有在尝试使用加密时access_token我才会遇到麻烦app.UseAuthentication()在正确的位置调用并且[Authorize(AuthenticationScheme="something")]属性是正确的。OpenIddict.AspNetCore专用 openiddict nuget feed 中的软件包版本 3.0.0。我相当确定这只是由于无法access_token在 API 中以正确的方式解密。
您看到的行为是由 OpenIddict 验证处理程序的 alpha 位限制引起的,该处理程序检查是否TokenValidationParameters.IssuerSigningKeys为 null,而不是TokenValidationParameters.IssuerSigningKey。
要解决这个问题,您可以使用:
config.IssuerSigningKeys = new[] { new X509SecurityKey(MyOtherCustomCertificate) };
Run Code Online (Sandbox Code Playgroud)
或者,您可以使用 discovery 来允许它从授权服务器下载签名密钥:
services.AddOpenIddict()
.AddValidation(options =>
{
options.SetIssuer(new Uri("https://localhost:44365/"));
options.AddEncryptionCertificate(AuthenticationExtensionMethods.TokenEncryptionCertificate());
options.UseAspNetCore();
options.UseSystemNetHttp();
});
Run Code Online (Sandbox Code Playgroud)
值得注意的是,该options.SetTokenValidationParameters()方法很快就会被删除(作为内省支持添加的一部分)。注册静态 OIDC 配置的新语法将类似于:
services.AddOpenIddict()
.AddValidation(options =>
{
options.SetConfiguration(new OpenIdConnectConfiguration
{
Issuer = "https://localhost:44365/",
SigningKeys = { new X509SecurityKey(AuthenticationExtensionMethods.TokenSigningCertificate()) }
});
options.AddEncryptionCertificate(AuthenticationExtensionMethods.TokenEncryptionCertificate());
});
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9235 次 |
| 最近记录: |