IdentityServer4集成ADFS 2016外部身份提供者未返回角色的问题咨询
解决IdentityServer4集成ADFS 2016时的角色获取与JWT令牌问题
我来帮你梳理下这个问题的解决思路,分两个核心部分来处理:获取角色声明,以及提取ADFS返回的JWT令牌。
一、解决角色声明缺失的问题
你能成功认证但看不到角色,大概率是ADFS声明规则配置或代码里的声明映射逻辑没匹配上,按以下步骤排查:
1. 先确认ADFS端的角色声明配置
ADFS默认不会自动把Active Directory的安全组/角色传递给依赖方,你需要在ADFS的依赖方信任里添加声明规则:
- 打开ADFS管理控制台,找到你的IdentityServer4对应的依赖方信任
- 进入「编辑声明规则」,添加一条「发送LDAP属性作为声明」的规则
- 选择AD作为属性存储,将
tokenGroups - Unqualified Names(或你需要的角色属性)映射到输出声明类型http://schemas.microsoft.com/ws/2008/06/identity/claims/role
- 选择AD作为属性存储,将
- 保存规则后,ADFS才会在认证成功后返回角色声明
2. 调整OpenIdConnect的声明映射逻辑
ADFS返回的角色声明类型是完整的URI,不是简单的role字符串,你需要修改代码里的ClaimAction来正确映射:
// 替换原来的ClaimAction options.ClaimActions.MapUniqueJsonKey("role", "http://schemas.microsoft.com/ws/2008/06/identity/claims/role"); // 或者你可以先打印所有声明,确认实际的Type再调整 options.ClaimActions.MapAllExcept("iss", "nbf", "exp", "aud", "nonce", "iat", "c_hash");
3. 在Callback中调试查看所有声明
在ExternalController.Callback()里添加调试代码,确认ADFS返回的所有声明:
public async Task<IActionResult> Callback() { var result = await HttpContext.AuthenticateAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme); if (result?.Succeeded != true) { throw new Exception("External authentication error"); } // 打印所有声明,找到角色对应的Type foreach (var claim in result.Principal.Claims) { Console.WriteLine($"Claim Type: {claim.Type}, Value: {claim.Value}"); } }
二、获取ADFS返回的JWT令牌
要拿到ADFS的id_token和access_token,只需在OpenIdConnect配置里添加一行代码,然后在Callback中提取:
1. 开启令牌保存功能
在你的AddOpenIdConnect配置里添加SaveTokens = true,默认这个值是false,不会把令牌存入AuthenticationProperties:
services.AddAuthentication() .AddOpenIdConnect("adfs", "ADFS", options => { // 其他原有配置... options.SaveTokens = true; // 新增这一行 // 其他原有配置... });
2. 在Callback中提取令牌
现在可以从认证结果的Properties里拿到JWT令牌了:
public async Task<IActionResult> Callback() { var result = await HttpContext.AuthenticateAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme); if (result?.Succeeded != true) { throw new Exception("External authentication error"); } // 提取ADFS返回的令牌 var authProps = result.Properties; var idToken = authProps.GetTokenValue("id_token"); var accessToken = authProps.GetTokenValue("access_token"); var refreshToken = authProps.GetTokenValue("refresh_token"); // 可以解析id_token查看角色,比如用JwtSecurityTokenHandler var handler = new JwtSecurityTokenHandler(); var decodedIdToken = handler.ReadJwtToken(idToken); var rolesFromToken = decodedIdToken.Claims.Where(c => c.Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/role"); }
内容的提问来源于stack exchange,提问作者JoeyD
相关产品推荐
相关产品推荐

