仅在 JWT 令牌中而不是在 OAuth2 令牌中添加附加信息

Posted

技术标签:

【中文标题】仅在 JWT 令牌中而不是在 OAuth2 令牌中添加附加信息【英文标题】:Add additionnal information only in the JWT token and not in the OAuth2 token 【发布时间】:2017-11-21 12:33:56 【问题描述】:

在我的 Spring 启动应用程序中,我正在尝试配置 Oauth2 和 JWT,它工作正常,但我想隐藏 oauth2 令牌中的附加信息,因为它们是纯文本的,并且相同的信息在 JWT 令牌中重复。

这是我的 Oauth2ServerConfig :

    @Configuration
    public class OAuth2ServerConfiguration 

        @Configuration
        @EnableAuthorizationServer
        protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter 

            private final AuthenticationManager authenticationManager;

            private final OAuth2ApprovalRepository oAuth2ApprovalRepository;

            private final OAuth2CodeRepository oAuth2CodeRepository;

            private final OAuth2ClientDetailsRepository oAuth2ClientDetailsRepository;


            public AuthorizationServerConfiguration(@Qualifier("authenticationManagerBean") AuthenticationManager authenticationManager) 
                this.authenticationManager = authenticationManager;
            

            @Bean
            public ApprovalStore approvalStore() 
                return new MyDBApprovalStore(oAuth2ApprovalRepository);
            

            @Bean
            protected AuthorizationCodeServices authorizationCodeServices() 
                return new MyDBAuthorizationCodeServices(oAuth2CodeRepository);
            


            @Override
            public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception 
                TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
                tokenEnhancerChain.setTokenEnhancers(Arrays.asList(tokenEnhancer(), accessTokenConverter()));

                endpoints.authorizationCodeServices(authorizationCodeServices())
                    .approvalStore(approvalStore())
                    .tokenStore(tokenStore())
                    .tokenEnhancer(tokenEnhancerChain)
                    .authenticationManager(authenticationManager);
            


            @Bean
            public TokenEnhancer tokenEnhancer() 
                return new CustomTokenEnhancer();
            


            @Bean
            public TokenStore tokenStore() 
                return new JwtTokenStore(accessTokenConverter());
            


            @Bean
            public JwtAccessTokenConverter accessTokenConverter() 
                JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
                converter.setSigningKey("123");
                return converter;
            


            @Override
            public void configure(ClientDetailsServiceConfigurer clients) throws Exception 
                clients.withClientDetails(new MyClientDetailsService(oAuth2ClientDetailsRepository));
            
        

    

还有我的自定义信息添加:

    public class CustomTokenEnhancer implements TokenEnhancer 

        @Override
        public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) 
            Map<String, Object> additionalInfo = new HashMap<>();
            additionalInfo.put("organizationId", "123");
    ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);
            return accessToken;
        
    

这是我验证 WS 调用的响应示例:


"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJvcmdhbml6YXRpb25JZCI6IjEyMyIsImF1ZCI6WyJyZXNfYmh1YiJdLCJ1c2VyX25hbWUiOiJhZG1pbiIsInNjb3BlIjpbInJlYWQiLCJ3cml0ZSJdLCJleHAiOjE0OTc4NjkyNDMsImF1dGhvcml0aWVzIjpbIlJPTEVfQURNSU4iLCJST0xFX1VTRVIiXSwianRpIjoiOGNhYTZjN2YtNTU0Yy00OTZmLTkwYTUtZTA4MjAyM2I3ZTFlIiwiY2xpZW50X2lkIjoiYmh1YmFwcCJ9.B58c2_tmfuV_L1py8ZzOPuTK3OZAhVFviL9W1gxRoec",
"token_type": "bearer",
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJvcmdhbml6YXRpb25JZCI6IjEyMyIsImF1ZCI6WyJyZXNfYmh1YiJdLCJ1c2VyX25hbWUiOiJhZG1pbiIsInNjb3BlIjpbInJlYWQiLCJ3cml0ZSJdLCJhdGkiOiI4Y2FhNmM3Zi01NTRjLTQ5NmYtOTBhNS1lMDgyMDIzYjdlMWUiLCJleHAiOjE0OTc4Njk0NDMsImF1dGhvcml0aWVzIjpbIlJPTEVfQURNSU4iLCJST0xFX1VTRVIiXSwianRpIjoiMGJjNWJhYzctMWI3Ny00OGFiLWI1N2MtNDM4ZjMyN2JmNGM2IiwiY2xpZW50X2lkIjoiYmh1YmFwcCJ9.DkQoCEX47PmmxOEj0n9kb2L5Yu6DqFgmUh7HBSTO_z4",
"expires_in": 1799,
"scope": "read write",
"organizationId": "123",
"jti": "8caa6c7f-554c-496f-90a5-e082023b7e1e"

我不想将此令牌的 organizationId 暴露给外部世界,并希望将此信息编码为 JWT 令牌 (access_token)。

如何用 Spring Boot、OAuth2、JWT 实现?

【问题讨论】:

【参考方案1】:

如果连接是通过 HTTPS(应该是这样),那么信息将不会暴露给外部世界(只是请求它的客户端)。

无论如何,您拥有的访问令牌只是一个 JWS(未加密),因此如果您将其放入其中,信息不会被隐藏(它只是 Base64 编码的)。

【讨论】:

问题是我们正在添加更多信息并且响应不断增长,因为附加信息被重复,即在令牌中以及在响应中......有什么办法可以将其从响应?问题是,浏览器中的恶意代码可能会修改这些附加信息(例如,在上述情况下,organizationId 为 444),而编码令牌中的 organizationId 仍为 123,并且开发人员为了方便而使用暴露的数据而不是值在令牌中以从后端服务获取一些详细信息【参考方案2】:

我在这里找到了解决方案:

Spring OAuth 2 + JWT Inlcuding additional info JUST in access token

我也改变了配置方法...

@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception 
  TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
  tokenEnhancerChain.setTokenEnhancers(Arrays.asList(tokenEnhancer())); 
  endpoints
    .tokenStore(tokenStore())
    .tokenEnhancer(tokenEnhancerChain)
    .reuseRefreshTokens(false)
    .userDetailsService(userDetailsService)
    .authenticationManager(authenticationManager);

【讨论】:

以上是关于仅在 JWT 令牌中而不是在 OAuth2 令牌中添加附加信息的主要内容,如果未能解决你的问题,请参考以下文章

JWT 不记名令牌流

OAuth2.0-JWT令牌

如何以管理员用户身份撤销用户的访问令牌和刷新令牌?在 Oauth2 中使用 JWT

Spring Webflux SecurityValidate OAuth2 JWT 令牌

为啥我的领域通知令牌仅在我的活动设备上触发,而不是在所有具有开放领域的设备上触发?

带有预取 JWT 令牌的 OAuth2RestTemplate