Spring OAuth2刷新令牌-无法将访问令牌转换为JSON [英] Spring oauth2 refresh token - Cannot convert access token to JSON

查看:1737
本文介绍了Spring OAuth2刷新令牌-无法将访问令牌转换为JSON的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在Spring OAuth应用程序中使用刷新令牌,但没有成功.系统将在授予密码时发出刷新令牌:

I'm trying to use a refresh token in a Spring OAuth application without success. The system will issue a refresh token on a password grant:

  {
  "access_token": "xxxxx",
  "token_type": "bearer",
  "refresh_token": "xxxxxx",
  "expires_in": 21599,
  "scope": "read write"
}

但是尝试使用刷新令牌会导致以下错误:

But trying to use the refresh token results in the following error:

curl -u acme -d"grant_type = refresh_token& refresh_token = xxxxxx" http://localhost:9999/uaa/oauth/token

curl -u acme -d "grant_type=refresh_token&refresh_token=xxxxxx" http://localhost:9999/uaa/oauth/token

{
  "error": "invalid_token",
  "error_description": "Cannot convert access token to JSON"
}

我的身份验证服务器配置如下:

My auth server config is as follows:

@Controller
@SessionAttributes("authorizationRequest")
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
@EnableResourceServer
@ImportResource("classpath:/spring/application-context.xml")
@Configuration
public class ApplicationConfiguration extends WebMvcConfigurerAdapter {

    @RequestMapping("/user")
    @ResponseBody
    public Principal user(Principal user) {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        System.out.println(auth.toString());
        return user;
    }

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/login").setViewName("login");
        registry.addViewController("/oauth/confirm_access").setViewName("authorize");
    }

    @Configuration
    @Order(-20)
    protected static class LoginConfig extends WebSecurityConfigurerAdapter {

        @Autowired
        private AuthenticationManager authenticationManager;

        @Override
        protected void configure(HttpSecurity http) throws Exception {

            http.csrf().disable();

            // @formatter:off
            http
                .formLogin().loginPage("/login").permitAll()
            .and()
                .requestMatchers().antMatchers("/login", "/oauth/authorize", "/oauth/confirm_access")
            .and()
                .authorizeRequests().anyRequest().authenticated();
            // @formatter:on

        }

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

    @Configuration
    public static class JwtConfiguration {

        @Bean
        public JwtAccessTokenConverter jwtAccessTokenConverter() {
            JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
            KeyPair keyPair = new KeyStoreKeyFactory(new ClassPathResource("keystore.jks"), "foobar".toCharArray())
                    .getKeyPair("test");
            converter.setKeyPair(keyPair);
            return converter;
        }

        @Bean
        public JwtTokenStore jwtTokenStore() {
            return new JwtTokenStore(jwtAccessTokenConverter());
        }
    }

    @Configuration
    @EnableAuthorizationServer
    protected static class OAuth2AuthorizationConfig extends AuthorizationServerConfigurerAdapter implements
            EnvironmentAware {

        private static final String ENV_OAUTH = "authentication.oauth.";
        private static final String PROP_CLIENTID = "clientid";
        private static final String PROP_SECRET = "secret";
        private static final String PROP_TOKEN_VALIDITY_SECONDS = "tokenValidityInSeconds";

        private RelaxedPropertyResolver propertyResolver;

        @Autowired
        private AuthenticationManager authenticationManager;

        @Autowired
        private JwtAccessTokenConverter jwtAccessTokenConverter;

        @Autowired
        private JwtTokenStore jwtTokenStore;

        @Autowired
        @Qualifier("myUserDetailsService")
        private UserDetailsService userDetailsService;

        @Autowired
        private DataSource dataSource;

        @Override
        public void setEnvironment(Environment environment) {
            this.propertyResolver = new RelaxedPropertyResolver(environment, ENV_OAUTH);
        }

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

        @Bean
        @Primary
        public DefaultTokenServices tokenServices() {
            DefaultTokenServices tokenServices = new DefaultTokenServices();
            tokenServices.setSupportRefreshToken(true);
            tokenServices.setTokenStore(jwtTokenStore);
            tokenServices.setAuthenticationManager(authenticationManager);
            tokenServices.setTokenEnhancer(tokenEnhancer());
            return tokenServices;
        }

        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
            TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
            // The order is important here - the custom enhancer must come before the jwtAccessTokenConverter.
            tokenEnhancerChain.setTokenEnhancers(Arrays.asList(tokenEnhancer(), jwtAccessTokenConverter));
            endpoints
                    .authenticationManager(authenticationManager)
                    .tokenEnhancer(tokenEnhancerChain)
                    .tokenStore(jwtTokenStore)
                    .userDetailsService(userDetailsService);
        }

        @Override
        public void configure(AuthorizationServerSecurityConfigurer oauthServer)
                throws Exception {
            oauthServer.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()");
        }

        @Override
        public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
            clients.jdbc(dataSource);
                    /*.withClient(propertyResolver.getProperty(PROP_CLIENTID))
                    .scopes("read", "write")
                    .autoApprove(true)
                    .authorities(ClientAuthoritiesConstants.CLIENT)
                    .authorizedGrantTypes("authorization_code", "refresh_token", "password")
                    .secret(propertyResolver.getProperty(PROP_SECRET))
                    .accessTokenValiditySeconds(propertyResolver.getProperty(PROP_TOKEN_VALIDITY_SECONDS, Integer
                    .class, 1800));*/
        }
    }

    /**
     * Configures the global LDAP authentication
     */
    @Configuration
    protected static class AuthenticationConfiguration extends GlobalAuthenticationConfigurerAdapter implements EnvironmentAware {

        private static final String ENV_LDAP = "authentication.ldap.";
        private static final String PROP_SEARCH_BASE = "userSearchBase";
        private static final String PROP_SEARCH_FILTER = "userSearchFilter";
        private static final String PROP_GROUP_SEARCH_FILTER = "groupSearchFilter";
        private static final String PROP_LDAP_URL = "url";
        private static final String PROP_LDAP_USER = "userDn";
        private static final String PROP_LDAP_PASS = "password";

        private RelaxedPropertyResolver propertyResolver;

        /**
         * Maps the LDAP user to the Principle that we'll be using in the app
         */
        public UserDetailsContextMapper userDetailsContextMapper() {
            return new UserDetailsContextMapper() {
                @Override
                public UserDetails mapUserFromContext(DirContextOperations ctx, String username,
                                                      Collection<? extends GrantedAuthority> authorities) {
                    // Get the common name of the user
                    String commonName = ctx.getStringAttribute("cn");
                    // Get the users email address
                    String email = ctx.getStringAttribute("mail");
                    // Get the domino user UNID
                    String uId = ctx.getStringAttribute("uid");
                    return new CustomUserDetails(email, "", commonName, authorities);
                }

                @Override
                public void mapUserToContext(UserDetails user, DirContextAdapter ctx) {
                    throw new IllegalStateException("Only retrieving data from LDAP is currently supported");
                }

            };
        }

        @Override
        public void setEnvironment(Environment environment) {
            this.propertyResolver = new RelaxedPropertyResolver(environment, ENV_LDAP);
        }

        @Override
        public void init(AuthenticationManagerBuilder auth) throws Exception {
            auth
                    .ldapAuthentication()
                    .userSearchBase(propertyResolver.getProperty(PROP_SEARCH_BASE))
                    .groupSearchBase(propertyResolver.getProperty(PROP_SEARCH_BASE))
                    .userSearchFilter(propertyResolver.getProperty(PROP_SEARCH_FILTER))
                    .groupSearchFilter(propertyResolver.getProperty(PROP_GROUP_SEARCH_FILTER))
                    .userDetailsContextMapper(userDetailsContextMapper())
                    .contextSource()
                    .url(propertyResolver.getProperty(PROP_LDAP_URL))
                    .managerDn(propertyResolver.getProperty(PROP_LDAP_USER))
                    .managerPassword(propertyResolver.getProperty(PROP_LDAP_PASS));
        }
    }
}

任何人都知道为什么在给定有效的刷新令牌后,身份验证服务器不发行新令牌吗?

Anyone have any ideas why the auth server isn't issuing a new token when given a valid refresh token?

推荐答案

因此,问题似乎是无效的refresh_token格式.由于我的配置,身份验证服务器期望的是有效的JWT,而我正在向其发送普通承载令牌.因此,错误消息无法将令牌转换为JSON".

So it looks like the issue was an invalid refresh_token format. Due to my config, what the auth server was expecting was a valid JWT, whereas I was sending it a plain bearer token. Hence the error message 'cannot convert token to JSON'.

偶然地,我发现该文档对于了解Spring OAuth的所有部分如何组合在一起很有用,这使我得以弄清这里发生的事情:

Incidentally, I found this document useful in understanding how all the parts of Spring OAuth fit together, which led me to figuring out what was going on here:

https://github.com/spring-projects/spring-security-oauth/blob/master/docs/oauth2.md

这篇关于Spring OAuth2刷新令牌-无法将访问令牌转换为JSON的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆