Azure AD Claims未纳入IdentityServer4签发令牌的技术问题咨询
解决IdentityServer4未包含Azure AD Claims到签发令牌的问题
这绝对不是默认设计如此——你完全可以把Azure AD里的租户ID、角色等Claims带到IdentityServer4(IS4)签发的令牌里,只是需要额外的配置来完成Claims的映射和传递。下面是一步步的解决方法:
1. 确保从Azure AD获取到目标Claims
首先,在IS4配置Azure AD作为外部身份提供者时,要开启从UserInfo端点拉取Claims的功能,同时请求正确的Scope来获取你需要的信息:
services.AddAuthentication() .AddOpenIdConnect("AzureAD", "Azure AD", options => { options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme; options.Authority = "https://login.microsoftonline.com/{你的租户ID}/v2.0"; options.ClientId = "{你的Azure AD应用Client ID}"; options.ClientSecret = "{你的Azure AD应用Client Secret}"; options.ResponseType = "code"; // 关键:开启从UserInfo端点获取额外Claims options.GetClaimsFromUserInfoEndpoint = true; // 请求包含所需信息的Scope options.Scope.Add("openid"); options.Scope.Add("profile"); options.Scope.Add("email"); options.Scope.Add("roles"); // 如果需要用户角色,必须添加这个Scope // 映射Azure AD的原生Claims到更友好的名称(可选但推荐) options.ClaimActions.MapUniqueJsonKey("tenant_id", "tid"); // 租户ID对应Azure AD的tid Claim options.ClaimActions.MapJsonKey(ClaimTypes.Role, "roles"); // 把roles映射成标准的Role Claim // 在创建登录票据时手动提取并添加需要的Claims options.Events.OnCreatingTicket = context => { // 提取并添加租户ID var tenantId = context.Principal.FindFirstValue("tid"); if (!string.IsNullOrEmpty(tenantId)) { context.Identity.AddClaim(new Claim("tenant_id", tenantId)); } // 处理多角色场景,确保所有Azure AD返回的角色都被添加 var azureRoles = context.Principal.FindAll("roles"); foreach (var role in azureRoles) { context.Identity.AddClaim(new Claim(ClaimTypes.Role, role.Value)); } return Task.CompletedTask; }; });
同时要确保你的Azure AD应用注册已经配置了正确的权限:如果需要读取用户角色,要在应用权限里添加Directory.Read.All(针对目录角色)或者确保你已经在应用里定义了应用角色并分配给了用户。
2. 配置IS4将目标Claims包含到签发的令牌中
光获取到Claims还不够,你需要告诉IS4哪些Claims需要包含到发给API或客户端的令牌里。可以通过配置ApiResource或者Client来实现:
针对ApiResource的配置
services.AddIdentityServer() .AddInMemoryApiResources(new List<ApiResource> { new ApiResource("你的API资源名称") { // 列出需要包含在访问令牌里的Claims UserClaims = { "tenant_id", ClaimTypes.Role, "email", "name" } } }) // 其他IS4配置(比如客户端、身份资源等)...
针对Client的配置(如果是客户端凭证流或需要ID令牌包含Claims)
如果是需要ID令牌包含这些Claims,要在Client配置里添加AllowedScopes和Claims:
new Client { ClientId = "你的客户端ID", // 其他客户端配置... AllowedScopes = { "openid", "profile", "你的API资源名称" }, // 指定要包含在ID令牌里的Claims Claims = { new ClientClaim("tenant_id", "tenant_id") } }
3. 自定义ProfileService(可选但必要时)
如果默认的ProfileService没有正确传递Claims,你可以自定义一个ProfileService来确保所有需要的Claims都被包含到令牌中:
public class CustomProfileService : IProfileService { public async Task GetProfileDataAsync(ProfileDataRequestContext context) { // 获取当前用户的所有Claims var userClaims = context.Subject.Claims.ToList(); // 可以在这里过滤或添加额外的Claims // 比如确保tenant_id和role都存在 context.IssuedClaims = userClaims; } public async Task IsActiveAsync(IsActiveContext context) { // 简单标记用户为活跃状态,根据你的业务逻辑调整 context.IsActive = true; } }
然后把这个自定义服务注册到DI容器中:
services.AddTransient<IProfileService, CustomProfileService>();
最后验证
完成配置后,重新启动IS4和你的应用,登录后解析IS4签发的令牌,应该就能看到来自Azure AD的租户ID、角色等Claims了。如果还是看不到,可以检查:
- Azure AD是否真的返回了这些Claims(可以用调试工具查看回调时的Claims集合)
- IS4的ApiResource/Client配置是否正确包含了这些Claims名称
- 自定义ProfileService是否正确返回了Claims
内容的提问来源于stack exchange,提问作者Sean
相关产品推荐
相关产品推荐

