C# 使用多个JWT承载身份验证
是否可以在ASP.NET Core 2中支持多个JWT令牌发行者? 我想为外部服务提供一个API,我需要使用两个JWT令牌源——Firebase和定制JWT令牌发行者。在ASP.NET core中,我可以为承载身份验证方案设置JWT身份验证,但只能为一个机构设置:C# 使用多个JWT承载身份验证,c#,firebase-authentication,asp.net-core-mvc,jwt,asp.net-core-2.0,C#,Firebase Authentication,Asp.net Core Mvc,Jwt,Asp.net Core 2.0,是否可以在ASP.NET Core 2中支持多个JWT令牌发行者? 我想为外部服务提供一个API,我需要使用两个JWT令牌源——Firebase和定制JWT令牌发行者。在ASP.NET core中,我可以为承载身份验证方案设置JWT身份验证,但只能为一个机构设置: services .AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options =>
services
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Authority = "https://securetoken.google.com/my-firebase-project"
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidIssuer = "my-firebase-project"
ValidateAudience = true,
ValidAudience = "my-firebase-project"
ValidateLifetime = true
};
}
我可以有多个发行人和受众,但我不能设置多个权限。你完全可以实现你想要的:
服务
.AddAuthentication()
.AddJwtBearer(“Firebase”,选项=>
{
选项。权限=”https://securetoken.google.com/my-firebase-project"
options.TokenValidationParameters=新的TokenValidationParameters
{
validateisuer=true,
validisuser=“我的firebase项目”
ValidateAudience=true,
ValidAudience=“我的firebase项目”
ValidateLifetime=true
};
})
.AddJwtBearer(“自定义”,选项=>
{
//自定义配置
//这里有JWT代币
});
服务
.AddAuthorization(选项=>
{
options.DefaultPolicy=新授权PolicyBuilder()
.RequireAuthenticatedUser()文件
.AddAuthenticationSchemes(“Firebase”、“自定义”)
.Build();
});
让我们来看看你的代码和那个代码之间的区别
AddAuthentication
没有参数
如果设置了默认身份验证方案,则在每个请求上,身份验证中间件都将尝试运行与默认身份验证方案关联的身份验证处理程序。因为我们现在有两种可能的身份验证方案,所以运行其中一种没有意义
使用另一个重载的AddJwtBearer
每个添加身份验证的AddXXX
方法都有几个重载:
- 其中使用了与身份验证方法关联的默认身份验证方案(如您所能)
- 除了选项的配置之外,还可以传递身份验证方案的名称,如下所示
[Authorize]
属性将导致请求被拒绝,并发出HTTP 401
由于这不是我们想要的,因为我们希望给身份验证处理程序一个对请求进行身份验证的机会,因此我们通过指示应尝试使用Firebase
和Custom
身份验证方案对请求进行身份验证来更改授权系统的默认策略
这并不能阻止你对某些行为进行更严格的限制;[Authorize]
属性有一个属性,允许您覆盖有效的身份验证方案
如果您有更复杂的场景,可以利用。我发现官方文件很棒
让我们设想一些操作仅对Firebase发行的JWT令牌可用,并且必须具有具有特定值的声明;你可以这样做:
//为了简洁起见,省略了身份验证代码
服务
.AddAuthorization(选项=>
{
options.DefaultPolicy=新授权PolicyBuilder()
.RequireAuthenticatedUser()文件
.AddAuthenticationSchemes(“Firebase”、“自定义”)
.Build();
options.AddPolicy(“FirebaseAdministrators”,新授权PolicyBuilder()
.RequireAuthenticatedUser()文件
.AddAuthenticationSchemes(“Firebase”)
.Requirecall(“角色”、“管理员”)
.Build());
});
然后,您可以在某些操作上使用[Authorize(Policy=“FirebaseAdministrators”)]
最后一点需要注意的是:如果您正在捕获
AuthenticationFailed
事件并使用除第一个AddJwtBearer
策略以外的任何策略,您可能会看到IDX10501:签名验证失败。无法匹配密钥…
这是由于系统依次检查每个AddJwtBearer
,直到找到匹配项为止。这个错误通常可以忽略。这是米卡·德里伊答案的延伸
我们的应用程序有一个自定义授权要求,我们可以从内部源解析该要求。我们使用的是Auth0,但正在使用OpenID切换到Microsoft帐户身份验证。下面是我们的ASP.NETCore2.1启动程序中经过轻微编辑的代码。对于将来的读者来说,在撰写本文时,这一点适用于指定的版本。调用者在传入的请求上使用OpenID的id_令牌作为承载令牌传递。希望它能帮助其他试图进行身份授权转换的人,就像这个问题和答案帮助了我一样
const string Auth0 = nameof(Auth0);
const string MsaOpenId = nameof(MsaOpenId);
string domain = "https://myAuth0App.auth0.com/";
services.AddAuthentication()
.AddJwtBearer(Auth0, options =>
{
options.Authority = domain;
options.Audience = "https://myAuth0Audience.com";
})
.AddJwtBearer(MsaOpenId, options =>
{
options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
{
ValidateAudience = true,
ValidAudience = "00000000-0000-0000-0000-000000000000",
ValidateIssuer = true,
ValidIssuer = "https://login.microsoftonline.com/9188040d-6c67-4c5b-b112-36a304b66dad/v2.0",
ValidateIssuerSigningKey = true,
RequireExpirationTime = true,
ValidateLifetime = true,
RequireSignedTokens = true,
ClockSkew = TimeSpan.FromMinutes(10),
};
options.MetadataAddress = "https://login.microsoftonline.com/9188040d-6c67-4c5b-b112-36a304b66dad/v2.0/.well-known/openid-configuration";
}
);
services.AddAuthorization(options =>
{
options.DefaultPolicy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.AddAuthenticationSchemes( Auth0, MsaOpenId )
.Build();
var approvedPolicyBuilder = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.AddAuthenticationSchemes(Auth0, MsaOpenId)
;
approvedPolicyBuilder.Requirements.Add(new HasApprovedRequirement(domain));
options.AddPolicy("approved", approvedPolicyBuilder.Build());
});
您可以向JWT添加任意数量的属性。因此,没有什么可以阻止您在JWT中记录两个发行人名称。问题在于,如果每个颁发者使用不同的密钥进行签名,您的应用程序将需要知道这两个密钥。这是否需要从firebase或自定义解决方案更改头值?例如,头是
Authorization:Firebase
而不是Authorization:Bearer
?尝试此解决方案时,我遇到错误:“没有为方案‘承载者’注册任何身份验证处理程序。”不,头不需要更改。错误消息表明您引用的是不存在的身份验证方案(承载)。在我们的示例中,两个注册方案是Firebase和Custom,它们是.AddJwtBearer
方法calls.Hi的第一个参数。我只是在寻找这个解决方案。不幸的是,我得到了一个“未指定任何authenticationScheme,并且没有找到DefaultChallengeScheme”异常。options.DefaultPolicy设置为ok。A.