请求OAuth2访问令牌时能否添加自定义Claims?
问题
在请求OAuth2 Access Token时,是否可以为其添加自定义Claims?默认情况下授权服务器会添加自身的Claims,但我希望在请求令牌时额外指定自定义Claims。这是否可行?
我正尝试使用nimbusds库实现此功能,以下是我的代码:
/** * Obtains an OAuth2 access token using the client credentials grant. * * @param clientId the client ID to authenticate with the token endpoint * @param clientSecret the client secret to authenticate with the token endpoint * @return the access token value as a string */ public String getToken(String clientId, String clientSecret) throws URISyntaxException, ParseException, IOException { // Construct the client credentials grant AuthorizationGrant clientGrant = new ClientCredentialsGrant(); // The credentials to authenticate the client at the token endpoint ClientID clientID = new ClientID(clientId); Secret clientSECRET= new Secret(clientSecret); ClientAuthentication clientAuth = new ClientSecretBasic(clientID, clientSECRET); // The request scope for the token (may be optional) // Scope scope = new Scope("core"); // The token endpoint URI tokenEndpoint = new URI("http://localhost:5444/oauth2/token"); // URI tokenEndpoint = new URI("http://localhost:8081/realms/master/protocol/openid-connect/token"); // Make the token request TokenRequest request = new TokenRequest(tokenEndpoint, clientAuth, clientGrant, null, null, Map.of("custom", List.of("custom"))); TokenResponse response = TokenResponse.parse(request.toHTTPRequest().send()); if (! response.indicatesSuccess()) { // We got an error response... TokenErrorResponse errorResponse = response.toErrorResponse(); log.info("errorResponse: {}", errorResponse.toString()); } AccessTokenResponse successResponse = response.toSuccessResponse(); // Get the access token AccessToken accessToken = successResponse.getTokens().getAccessToken(); log.info("accessToken: {}", accessToken.toJSONString()); return accessToken.getValue(); }
我在这行代码中尝试添加自定义值,但获取到的令牌中并未包含请求的自定义Claims:
TokenRequest request = new TokenRequest(tokenEndpoint, clientAuth, clientGrant, null, null, Map.of("custom", List.of("custom")));
解决思路
核心结论:自定义Claims的添加必须得到授权服务器的支持,客户端仅发送参数无法直接生效,需要从请求方式、服务器配置两方面调整:
1. 修正TokenRequest的参数传递方式
OAuth2规范中,客户端传递自定义Claims通常需要通过claims参数(JSON格式)指定,而非直接传入自定义键值对。修改代码示例:
// 构造指定access_token自定义Claims的JSON结构 String claimsJson = "{\"access_token\":{\"custom\":\"custom_value\"}}"; // 将claims作为请求参数传入TokenRequest TokenRequest request = new TokenRequest( tokenEndpoint, clientAuth, clientGrant, null, null, Map.of("claims", List.of(claimsJson)) );
2. 配置授权服务器接收并处理自定义Claims
不同授权服务器的配置逻辑不同,举几个常见场景:
- Spring Authorization Server:自定义
OAuth2TokenCustomizer,从token请求的参数中提取自定义值,添加到生成的令牌Claims集合中 - Keycloak:创建自定义Protocol Mapper,或者在客户端配置中启用允许传递自定义Claims,并将目标Claims添加到客户端作用域
- 自定义授权服务器:在令牌生成逻辑中,显式读取请求中的自定义参数,写入JWT的Claims
3. 验证请求参数的实际发送状态
用抓包工具(如Charles、Wireshark)检查发送到令牌端点的POST请求,确认自定义参数是否被正确包含在表单数据中。如果参数未发送成功,需排查NimbusDS库是否正确将扩展参数转换为表单字段。
4. 正确解析令牌中的自定义Claims
确保解析access token时直接读取目标Claims,例如:
// 从AccessToken中直接提取自定义Claim String customValue = accessToken.getClaim("custom").toString();
内容的提问来源于stack exchange,提问作者Jordi
相关产品推荐
相关产品推荐

