c# - 将 id_token 与 ASP.NET Core 3 一起使用
问题描述
在 ASP.NET Core 3 应用程序中,我需要处理id_token
来自access_token
.
id_token
具有构建策略有时需要的成员信息。由于成员信息可能很大,因此access_token
不可能将其作为其中的一部分(令牌超过允许的最大大小)。
客户发送标头,我正在寻找一种方法来提取它并使用其中的声明id_token
。x-id-token
现在我已经配置了 JwtBearer 身份验证,它与Authorization: Bearer access_token
标头无缝协作。
public void ConfigureServices(IServiceCollection services) {
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.Authority = $"https://{Configuration["auth:Domain"]}/";
options.Audience = Configuration["auth:Audience"];
});
...
}
解决方案
如问题中所述,我需要授权流程中的一个步骤来验证id_token
并membership_id
提供自定义标头。我最终以以下形式创建了一个自定义身份验证要求处理程序
internal class MembershipRequirement : AuthorizationHandler<MembershipRequirement>, IAuthorizationRequirement
{
public MembershipRequirement(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, MembershipRequirement requirement)
{
var authFilterCtx = (Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext)context.Resource;
string idToken = authFilterCtx.HttpContext.Request.Headers["x-id-token"];
string membershipId = authFilterCtx.HttpContext.Request.Headers["x-selected-membership-id"];
if (idToken != null && membershipId != null)
{
var identity = ValidateIdToken(idToken).Result;
if (identity != null)
{
var subscriptions = identity.Claims.ToList().FindAll(s => s.Type == "https://example.com/subs").ToList();
var assignments = subscriptions.Select(s => JsonSerializer.Deserialize<Subscription>(s.Value)).ToList();
var membership = assignments.Find(a => a.id == membershipId);
if (membership != null)
{
// assign the id token claims to user identity
context.User.AddIdentity(new ClaimsIdentity(identity.Claims));
context.Succeed(requirement);
}
else { context.Fail(); }
}
else
{
context.Fail();
}
}
return Task.FromResult<object>(null);
}
private async Task<ClaimsPrincipal> ValidateIdToken(string token)
{
try
{
IConfigurationManager<OpenIdConnectConfiguration> configurationManager = new ConfigurationManager<OpenIdConnectConfiguration>($"https://{Configuration["Auth:Domain"]}/.well-known/openid-configuration", new OpenIdConnectConfigurationRetriever());
OpenIdConnectConfiguration openIdConfig = await configurationManager.GetConfigurationAsync(CancellationToken.None);
TokenValidationParameters validationParameters =
new TokenValidationParameters
{
IssuerSigningKeys = openIdConfig.SigningKeys,
ValidateIssuer = false,
ValidateAudience = false
};
var validator = new JwtSecurityTokenHandler();
SecurityToken validatedToken;
var identity = validator.ValidateToken(token, validationParameters, out validatedToken);
return identity;
}
catch (Exception e)
{
Console.Writeline($"Error occurred while validating token: {e.Message}");
return null;
}
}
}
internal class Subscription
{
public string name { get; set; }
public string id { get; set; }
}
然后在该public void ConfigureServices(IServiceCollection services)
方法中添加了一个策略来检查id_token
services.AddAuthorization(options =>
{
options.AddPolicy("RequiredCompanyMembership", policy => policy.Requirements.Add(new MembershipRequirement(Configuration)));
});
对我们来说,此政策适用于所有授权端点。
推荐阅读
- python - 看不到视频截图
- javascript - Promises.all() 在 Edge 和 Safari 中的行为很奇怪
- autodesk-forge - Bim360 Forge 获取更改项目列表
- python - 使用 Django 的 RSS/ATOM 中缺少图像
- python - 在 python 循环中迭代列表时,为什么返回的元素是一个元组?
- azure - Azure 应用服务可以有固定的 MAC 地址吗?
- css - CSS:替代 min()
- vba - 如何更正 Access VBA 中的 MS Access 运行时错误“2498”?
- ag-grid - 删除特定列中单元格的边框底部
- php - mysqld拒绝工作的PHP shell_exec