2016-09-29 3 views
3

Ich versuche, ein Aktualisierungstoken in einer Spring-OAuth-Anwendung ohne Erfolg zu verwenden. Das System wird ein Aktualisierungs-Token auf einem Passwort Erteilung erteilen:Spring oauth2 Aktualisierungstoken - Kann Access-Token nicht in JSON konvertieren

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

aber versuchen, die Aktualisierungs-Token Ergebnisse in den folgenden Fehlern zu verwenden:

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" 
} 

Mein auth Server-Konfiguration ist wie folgt:

@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)); 
     } 
    } 
} 

Hat jemand irgendwelche Ideen, warum der Authentifizierungsserver kein neues Token ausgibt, wenn er ein gültiges Aktualisierungs-Token erhält?

Antwort

0

So scheint es das Problem war ein ungültiges refresh_token Format. Aufgrund meiner Konfiguration war das, was der Authentifizierungsserver erwartete, eine gültige JWT, während ich ihm ein einfaches Bearer-Token zusandte. Daher kann die Fehlermeldung 'Token nicht in JSON konvertieren'.

Übrigens fand ich dieses Dokument hilfreich für das Verständnis, wie alle Teile des Frühlings OAuth zusammen passen, was mich zu herauszufinden geführt, was hier los war:

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

+3

Es würde hav Es hat definitiv geholfen, wenn Sie Ihre Lösung gepostet haben, anstatt nur einen bestimmten Link zu geben. – KyelJmD

+0

Danke für Ihre Antwort. Du hast meinen Tag Bruder gerettet. – Asif

+0

@TimS Können Sie bitte hinzufügen, was wir tun müssen, um dieses Problem zu lösen. Ich konnte es nicht herausfinden. – Ibrahim

3

dieses Problem hatte. Ich schickte den "Bearer xxxxxx ..." und der TokenEnhancer erwartete nur "xxxxx ..." ohne das "Bearer" Präfix

1

Ich hatte das gleiche Problem. Nach einigem Debugging stellte sich heraus, dass meine Signatur nicht übereinstimmte.

In meinem Fall habe ich die Schlüssel etwas anders eingerichtet, und es gibt einen Fehler, bei dem der Schlüssel zum Signieren und Überprüfen fehlschlägt.

https://github.com/spring-projects/spring-security-oauth/issues/1144

+0

Dieser Zeiger ist sehr hilfreich – Debopam

0

hat auch gleiches Problem mit Frühlings-Boot 1.5.4

Es ist wirklich tatsächlich, dass jwtAccessTokenConverter.setVerifierKey(publicKey); nicht wirklich Verifizierer gesetzt (im Debug-Wert null ist), die in verwendet wird -

JwtAccessTokenConverter 
...protected Map<String, Object> decode(String token) { 
     try { 
      Jwt jwt = JwtHelper.decodeAndVerify(token, verifier); 

als Abhilfe geholfen:

private JwtAccessTokenConverter jwtAccessTokenConverter() { 
     JwtAccessTokenConverter jwtAccessTokenConverter = new CustomTokenEnhancer(); 
     jwtAccessTokenConverter.setSigningKey(jwtSigningKey); 
     jwtAccessTokenConverter.setVerifier(new RsaVerifier(jwtPublicKey)); 
     log.info("Set JWT signing key to: {}", jwtAccessTokenConverter.getKey()); 

     return jwtAccessTokenConverter; 
    } 
Verwandte Themen