授权代码流后,Spring OAuth2 服务器没有响应刷新令牌

Posted

技术标签:

【中文标题】授权代码流后,Spring OAuth2 服务器没有响应刷新令牌【英文标题】:Spring OAuth2 Server is not responding with refresh token after authorization code flow 【发布时间】:2021-07-01 04:00:24 【问题描述】:

我已经设置了一个 OAuth2 身份验证服务器,其主要目的是使用授权代码流。据我所知,流程正在运行,因为我能够在流程结束时获得有效的 access_token,但问题是我没有获得 request_token 响应字段。我不确定我是否打算做一些与我所做的不同的事情,但我相信我要做的就是在authorizedGrantTypes 参数中添加“request_token”(我已经完成了)。下面我将最相关的设置代码。

AuthorizationServerConfigurerAdapter

@Import(AuthorizationServerEndpointsConfiguration.class)
@Configuration
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter 

    PasswordEncoder passwordEncoder;
    AuthenticationManager authenticationManager;
    KeyPair keyPair;
    RedisConnectionFactory redisConnectionFactory;

    public AuthorizationServerConfig(AuthenticationManager authenticationManager, KeyPair keyPair, RedisConnectionFactory redisConnectionFactory,
                                     PasswordEncoder passwordEncoder) 
        this.keyPair = keyPair;
        this.redisConnectionFactory = redisConnectionFactory;
        this.authenticationManager = authenticationManager;
        this.passwordEncoder = passwordEncoder;
    

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception 
        clients
                .inMemory()
                    .withClient("web")
                    .secret(passwordEncoder.encode("noonewilleverguess"))
                    .scopes("resource:read", "resource:write")
                    .authorizedGrantTypes("authorization_code", "refresh_token")
                    .redirectUris("http://localhost:8080/login-two");
    

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception 
        endpoints
                .authenticationManager(authenticationManager)
                .tokenStore(tokenStore(redisConnectionFactory))
                .accessTokenConverter(accessTokenConverter());
    

    @Bean
    public TokenStore tokenStore(RedisConnectionFactory redisConnectionFactory) 
        return new RedisTokenStore(redisConnectionFactory);
    

    @Bean
    public JwtAccessTokenConverter accessTokenConverter() 
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        converter.setKeyPair(this.keyPair);
        return converter;
    

AuthorizationServerSecurityConfiguration

@Configuration
public class JwtSetEndpointConfiguration extends AuthorizationServerSecurityConfiguration 

    @Override
    protected void configure(HttpSecurity http) throws Exception 
        super.configure(http);

        http
                .requestMatchers()
                    .mvcMatchers("/.well-known/jwks.json")
                    .and()
                .authorizeRequests()
                    .mvcMatchers("/.well-known/jwks.json").permitAll();
    



WebSecurityConfigurerAdapter

@EnableWebSecurity
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter 

    @Bean
    @Override
    protected UserDetailsService userDetailsService() 
        return new UserDetailsServiceImpl();
    

    @Bean
    public KeyPair keyPairBean() throws NoSuchAlgorithmException 
        //TODO:drt - probs change
        KeyPairGenerator gen = KeyPairGenerator.getInstance("RSA");
        gen.initialize(2048);
        return gen.generateKeyPair();
    

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception 
        return super.authenticationManagerBean();
    

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception 
        auth.userDetailsService(userDetailsService()).passwordEncoder(passwordEncoder());
    

    @Bean
    PasswordEncoder passwordEncoder() 
        return PasswordEncoderFactories.createDelegatingPasswordEncoder();
    

授权码流响应

我首先发送一个 GET 请求到:

http://localhost:8080/oauth/authorize?response_type=code&client_id=web&state=8781487s1

重定向示例:http://localhost:8080/login-two?code=N-U9XJ&state=8781487s1

然后我使用基本身份验证向 http://localhost:8080/oauth/token 发送 POST 请求

这是我收到的示例响应,没有 refresh_token 字段:


    "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2MTc2MjY1NzQsInVzZXJfbmFtZSI6ImFkbWluIiwiYXV0aG9yaXRpZXMiOlsiUk9MRV9VU0VSIl0sImp0aSI6ImRENUplcWI3QlhHTkd0WkI1QVU4akhNbGR1YyIsImNsaWVudF9pZCI6IndlYiIsInNjb3BlIjpbInJlc291cmNlOndyaXRlIiwicmVzb3VyY2U6cmVhZCJdfQ.D5XKotYYAZkKtZNWdD-wirtoi3prU3CCmibIiQF5kodbXeK5ETdZ5k8CgSBLd7Aq-XEdhYXUEbtzzI0vf1vHf_MyhPFy_owldm_JJf2-2z9jNoU2BSnGMp6TCM00pCSMwbk57paLRZouryHEhTdvixVDmez2e1KmMVmXP6NypARB3Sp5SD2sZ2JN7FBQdkQ0OMVChjAQMTy1M3mDiT5dpT7iD7JxKRFTmD7qKYSF_gbQi6mEF3oH4j40TGI_CpyP3kKdDh4kiEfNeFd84YNHGYZACsYHfjoJrtJV1ECoeLph5CpmSpzt0lhOlzy8Q98OsPR8SdRt5Ou9N-BFmftZDw",
    "token_type": "bearer",
    "expires_in": 13462,
    "scope": "resource:write resource:read",
    "jti": "dD5Jeqb7BXGNGtZB5AU8jHMlduc"

希望你们中的一个可以提供帮助,因为在尝试了一些事情并在网上查找之后,我不知道我做错了什么。请帮忙,

【问题讨论】:

【参考方案1】:

所以我设法解决了这个问题,所以它现在在授权流程之后返回一个刷新令牌。我所要做的就是添加 DefaultTokenServices bean 并确保将 setSupportRefreshToken 设置为 true。

@Bean
    @Primary
    public DefaultTokenServices tokenServices() 
        DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
        defaultTokenServices.setTokenStore(tokenStore());
        defaultTokenServices.setSupportRefreshToken(true);
        return defaultTokenServices;
    

【讨论】:

以上是关于授权代码流后,Spring OAuth2 服务器没有响应刷新令牌的主要内容,如果未能解决你的问题,请参考以下文章

Spring Security Oauth2 : Possible CSRF detected

Spring Security---Oauth2详解

妹子始终没搞懂OAuth2.0,今天整合Spring Cloud Security 一次说明白!

Spring OAuth2 授权:访问被拒绝

调用spring oauth2授权服务器时Spring Cloud Gateway卡住

Spring OAuth2 资源和授权服务器