ASP.NET Core 6中如何通过OpenIdConnect将Access Token声明添加到ClaimsPrincipal
解决ASP.NET Core 6中OpenIdConnect无法获取Access Token声明的问题
默认情况下,Microsoft.AspNetCore.Authentication.OpenIdConnect中间件仅从id_token提取声明构建ClaimsPrincipal,不会自动包含access_token中的内容。要将access_token的声明添加到主体中,可按以下步骤操作:
1. 基础配置确保获取Access Token
先在认证服务配置中开启SaveTokens以保存access_token到认证票据,同时配置正确的授权码流参数:
builder.Services.AddAuthentication(options => { options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme; }) .AddCookie() .AddOpenIdConnect(options => { options.Authority = "https://your-keycloak-domain/auth/realms/your-realm"; options.ClientId = "your-client-id"; options.ClientSecret = "your-client-secret"; options.ResponseType = OpenIdConnectResponseType.Code; options.SaveTokens = true; // 必须开启,才能后续读取access_token options.GetClaimsFromUserInfoEndpoint = true; // 可选,若需从UserInfo端点拉取额外信息 });
2. 在令牌验证事件中解析并添加声明
通过OnTokenValidated事件,在令牌验证完成后解析access_token,将其声明添加到ClaimsPrincipal:
options.Events = new OpenIdConnectEvents { OnTokenValidated = context => { // 从认证属性中读取access_token if (context.Properties.TryGetTokenValue("access_token", out var accessToken)) { var tokenHandler = new JwtSecurityTokenHandler(); if (tokenHandler.CanReadToken(accessToken)) { var jwtToken = tokenHandler.ReadJwtToken(accessToken); // 遍历access_token的声明,添加到主体中 foreach (var claim in jwtToken.Claims) { // 可选:跳过已存在的声明,避免重复 if (!context.Principal.HasClaim(c => c.Type == claim.Type && c.Value == claim.Value)) { context.Principal.AddClaim(claim); } } } } return Task.CompletedTask; } };
注:
context.Properties.TryGetTokenValue是.NET 6+的扩展方法,比直接读取字典更简洁可靠。
3. 额外注意事项
- 确认Keycloak客户端配置中,
access_token已包含你需要的自定义声明:可在Keycloak的客户端范围或用户属性映射中配置。 - 若Keycloak签发的
access_token是加密的,需额外配置解密密钥(默认情况下Keycloak签发的是未加密JWT,无需此操作)。 - 如果不需要保留重复声明,可根据声明类型或值进行过滤,避免
ClaimsPrincipal中出现重复项。
内容的提问来源于stack exchange,提问作者Inx51
相关产品推荐
相关产品推荐

