ADFS OnBehalfOf令牌缺失sub声明问题排查求助
问题:MSAL结合ADFS2019获取的On-Behalf-Of令牌缺失用户声明
场景说明
使用MSAL结合ADFS2019实现Web应用代表已认证用户调用内部API,初始获取的访问令牌包含完整用户标识声明,但调用AcquireTokenOnBehalfOf返回的下游API令牌仅包含应用相关信息,缺失sub、email等用户声明。
初始访问令牌内容(含用户声明)
{ "aud": "https://SRV", "iss": "[***REMOVED***]", "iat": 1687181262, "nbf": 1687181262, "exp": 1687184862, "email": "user1@mydomain.com", "winaccountname": "user1@mydomain.com", "anchor": "sub", "sub": "user1@mydomain.com", "apptype": "Confidential", "appid": "https://SRV", "authmethod": "http://schemas.microsoft.com/ws/2008/06/identity/authenticationmethod/windows", "auth_time": "2023-06-19T12:11:56.653Z", "ver": "1.0", "scp": "email user_impersonation profile openid" }
下游API访问令牌内容(缺失用户声明)
{ "aud": "api://API", "iss": "[***REMOVED***]", "iat": 1687181215, "nbf": 1687181215, "exp": 1687184815, "apptype": "Confidential", "appid": "https://SRV", "auth_time": "2023-06-19T12:11:56.653Z", "authmethod": "http://schemas.microsoft.com/ws/2008/06/identity/authenticationmethod/windows", "ver": "1.0", "scp": "profile user_impersonation openid email" }
代码实现
var token = await HttpContext.GetTokenAsync("access_token"); var resource = _configuration["ADFS:Resource"]; var client = ConfidentialClientApplicationBuilder.Create(_configuration["ADFS:ClientID"]). WithAdfsAuthority(_configuration["ADFS:Instance"]). WithClientSecret(_configuration["ADFS:ClientSecret"]).Build(); var userAssertion = new UserAssertion(token, "urn:ietf:params:oauth:grant-type:jwt-bearer"); var result = await client.AcquireTokenOnBehalfOf(new[] { $"{resource}/openid", $"{resource}/email" , $"{resource}/user_impersonation" }, userAssertion) .WithClaims("sub, upn") .ExecuteAsync(); var httpClient = _httpClientFactory.CreateClient("WebAPI"); httpClient.BaseAddress = new Uri(_configuration["ServiceUrl"]); httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("bearer", result.AccessToken); Weather = await httpClient.GetFromJsonAsync<IEnumerable<WeatherServiceResponse>>("/WeatherForecast"); return;
问题解决要点
- ADFS API应用声明规则配置:ADFS不会自动传递用户声明到下游API,需在ADFS管理控制台中为
api://API对应的应用添加声明规则:- 找到目标API应用程序,进入声明规则页面
- 添加发送LDAP属性作为声明规则,将用户的
sub、email等属性映射到令牌声明;或使用自定义规则确保声明传递
- 修正
WithClaims参数格式:当前传入的逗号分隔字符串不符合ADFS要求,需改为JSON格式的声明请求:
或使用.WithClaims("{\"access_token\":{\"sub\":null,\"email\":null}}")ClaimsRequest类构建规范请求:var claimsRequest = new ClaimsRequest(); claimsRequest.AddClaim("sub", null, "access_token"); claimsRequest.AddClaim("email", null, "access_token"); .WithClaims(claimsRequest) - 验证资源范围配置:确认请求的
{resource}/openid等范围已在ADFS中为API应用正确配置,且允许传递用户声明 - 匹配令牌受众:确保
aud字段api://API与目标API的标识符完全一致,ADFS会根据受众筛选生效的声明规则
内容的提问来源于stack exchange,提问作者mberube.Net
相关产品推荐
相关产品推荐

