Spring Boot从Azure请求令牌时自定义声明未设置如何解决
核心问题说明
你当前的用法完全搞错了ClaimsRequest的作用,Azure AD不支持在请求令牌时动态传入自定义声明让它直接写到令牌里,所有要出现在令牌里的声明都必须先在Azure AD端提前配置,ClaimsRequest只是用来告知Azure AD你需要返回哪些已经配置好的可选声明,不是用来新增声明的。
1. 先在Azure AD完成自定义声明配置
你用的是客户端凭据流(服务到服务无用户参与的授权模式),要加自定义声明先去Azure Portal操作:
- 进入你的Azure AD应用注册管理页,左侧导航选择「令牌配置」
- 点击「添加可选声明」,选择要附加声明的令牌类型(访问令牌/ID令牌)
- 如果是用内置属性作为声明,直接在列表勾选对应属性即可;如果是完全自定义的声明,选择「添加自定义声明」,自行定义声明名称和取值来源
- 客户端凭据流默认只返回应用维度的声明,如果你需要用户维度的声明,要切换到带用户上下文的授权流(比如授权码流、密码流),或者为你的应用服务主体配置声明映射策略关联自定义属性
2. 修正代码中ClaimsRequest的错误用法
你现在的代码把序列化后的整个对象当成声明名传入,完全不符合API要求,requestClaimInAccessToken/requestClaimInIdToken方法的第一个参数是你在Azure AD中配置好的声明名称的字符串,你之前自定义的MyClaims类完全不需要,直接用原生的ClaimsRequest即可:
public String getTokenFromAzure() { String token = null; ConfidentialClientApplication application = getApplication(); if (application == null) { log.error("application is not instantiated"); return null; } // 构造声明请求,只需要指定你配置好的声明名即可 ClaimsRequest claimsRequest = new ClaimsRequest(); // 要求在访问令牌中返回已配置的employeeid声明 claimsRequest.requestClaimInAccessToken("employeeid", null); // 要求在访问令牌中返回已配置的dummy声明 claimsRequest.requestClaimInAccessToken("dummy", null); // 要求在ID令牌中返回已配置的声明(如果需要的话) claimsRequest.requestClaimInIdToken("employeeid", null); ClientCredentialParameters parameters = ClientCredentialParameters.builder(Collections.singleton(clientId + "/.default")) .claims(claimsRequest) .build(); IAuthenticationResult auth = application.acquireToken(parameters).join(); if (auth == null) { log.info("auth still == null"); return null; } log.info("idToken: " + auth.idToken()); log.info("accessToken: " + auth.accessToken()); token = isEmpty(auth.idToken()) ? auth.accessToken() : auth.idToken(); return token; }
3. 排查常见不生效问题
如果配置完还是拿不到自定义声明,检查以下几点:
- 确认你在Azure AD配置声明时选择的令牌类型和你代码里取的令牌类型一致,比如你配置的是ID令牌的声明,访问令牌里自然不会出现
- 确认声明的取值来源有值,比如你配置声明取用户的
employeeId属性,但对应账号的这个属性为空的话,声明默认不会返回 - 客户端凭据流下不要配置用户维度的声明,这个模式没有用户上下文,不会返回用户相关属性
内容的提问来源于stack exchange,提问作者f.trajkovski
相关产品推荐
相关产品推荐

