2017-03-09 3 views
2

Je souhaite créer un serveur d'autorisation à l'aide de Spring Oauth, qui peut émettre ses propres jetons JWT. Le serveur d'autorisation doit déléguer l'authentification à Google. J'ai suivi ce tutoriel qui fait presque tout ce que je veux: https://spring.io/guides/tutorials/spring-boot-oauth2/Emettre des jetons JWT à partir du serveur d'autorisation OAuth2 de Spring lors de l'authentification avec Google

J'ai été en mesure d'ajouter Google en tant que fournisseur d'authentification, mais je suis aux prises avec la partie JWT.

Voilà ma configuration de serveur d'autorisation:

@SpringBootApplication 
@EnableOAuth2Client 
@EnableAuthorizationServer 
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER) 
public class MsAuthorizationGmailApplication extends WebSecurityConfigurerAdapter { 

    @Autowired 
    OAuth2ClientContext oauth2ClientContext; 

    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
     http.antMatcher("/**").authorizeRequests().antMatchers("/", "/login**", "/webjars/**").permitAll().anyRequest() 
      .authenticated().and().exceptionHandling() 
      .authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/login/gmail")).and().logout() 
      .logoutSuccessUrl("/").permitAll().and().csrf() 
      .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()).and() 
      .addFilterBefore(ssoFilter(), BasicAuthenticationFilter.class); 
    } 

    @Bean 
    @ConfigurationProperties("gmail") 
    public ClientResources gmail() { 
     return new ClientResources(); 
    } 

    private Filter ssoFilter() { 
     CompositeFilter filter = new CompositeFilter(); 
     List<Filter> filters = new ArrayList<>(); 
     filters.add(ssoFilter(gmail(), "/login/gmail")); 
     filter.setFilters(filters); 
     return filter; 
    } 

    private Filter ssoFilter(ClientResources client, String path) { 
     OAuth2ClientAuthenticationProcessingFilter filter = new  OAuth2ClientAuthenticationProcessingFilter(
      path); 
     OAuth2RestTemplate template = new OAuth2RestTemplate(client.getClient(), oauth2ClientContext); 
     filter.setRestTemplate(template); 
     filter.setTokenServices(JwtConfig.tokenServices()); 
     return filter; 
    } 

    public static void main(String[] args) { 
     SpringApplication.run(MsAuthorizationGmailApplication.class, args); 
    } 

} 

Dans la configuration JWT Je ne cherche pas à faire quoi que ce soit de fantaisie, juste essayer de le faire passer pour le moment:

public final class JwtConfig { 

    private static final String KEY = "123"; 

    private JwtConfig() { 
    } 

    private static JwtAccessTokenConverter accessTokenConverter() { 
     JwtAccessTokenConverter converter = new JwtAccessTokenConverter(); 
     converter.setSigningKey(KEY); 
     return converter; 
    } 

    private static TokenStore tokenStore() { 
     return new JwtTokenStore(accessTokenConverter()); 
    } 

    public static DefaultTokenServices tokenServices() { 
     DefaultTokenServices defaultTokenServices = new DefaultTokenServices(); 
     defaultTokenServices.setTokenStore(tokenStore()); 
     defaultTokenServices.setSupportRefreshToken(true); 
     return defaultTokenServices; 
    } 
} 

Je reçois la exception suivante:

org.springframework.security.authentication.BadCredentialsException: Could not obtain user details from token 
at org.springframework.security.oauth2.client.filter.OAuth2ClientAuthenticationProcessingFilter.attemptAuthentication(OAuth2ClientAuthenticationProcessingFilter.java:122) ~[spring-security-oauth2-2.0.12.RELEASE.jar:na] 
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:212) ~[spring-security-web-4.2.1.RELEASE.jar:4.2.1.RELEASE] 
at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:112) [spring-web-4.3.6.RELEASE.jar:4.3.6.RELEASE] 
at org.springframework.web.filter.CompositeFilter.doFilter(CompositeFilter.java:73) [spring-web-4.3.6.RELEASE.jar:4.3.6.RELEASE] 
.... 
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.11.jar:8.5.11] 
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_121] 
Caused by: org.springframework.security.oauth2.common.exceptions.InvalidTokenException: Cannot convert access token to JSON 
at org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter.decode(JwtAccessTokenConverter.java:287) ~[spring-security-oauth2-2.0.12.RELEASE.jar:na] 
at org.springframework.security.oauth2.provider.token.store.JwtTokenStore.convertAccessToken(JwtTokenStore.java:88) ~[spring-security-oauth2-2.0.12.RELEASE.jar:na] 
at org.springframework.security.oauth2.provider.token.store.JwtTokenStore.readAccessToken(JwtTokenStore.java:80) ~[spring-security-oauth2-2.0.12.RELEASE.jar:na] 
at org.springframework.security.oauth2.provider.token.DefaultTokenServices.loadAuthentication(DefaultTokenServices.java:229) ~[spring-security-oauth2-2.0.12.RELEASE.jar:na] 
at org.springframework.security.oauth2.client.filter.OAuth2ClientAuthenticationProcessingFilter.attemptAuthentication(OAuth2ClientAuthenticationProcessingFilter.java:112) ~[spring-security-oauth2-2.0.12.RELEASE.jar:na] 
... 62 common frames omitted 
Caused by: java.lang.IllegalArgumentException: JWT must have 3 tokens 
at org.springframework.security.jwt.JwtHelper.decode(JwtHelper.java:49) ~[spring-security-jwt-1.0.0.RELEASE.jar:na] 
at org.springframework.security.jwt.JwtHelper.decodeAndVerify(JwtHelper.java:74) ~[spring-security-jwt-1.0.0.RELEASE.jar:na] 
at org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter.decode(JwtAccessTokenConverter.java:277) ~[spring-security-oauth2-2.0.12.RELEASE.jar:na] 
... 66 common frames omitted 

Comment je comprends cela: Cela ressemble à cela lorsque Google émet un jeton d'accès, le serveur d'autorisation (étant un client de Google OAuth) tente de décoder le jeton d'accès en JWT et déclenche une exception car le jeton de Google n'est pas un JWT valide (c'est juste un jeton d'accès).

Je voudrais créer un JWT contenant le jeton d'accès (qui sera utilisé pour accéder aux API Google) et quelques informations supplémentaires sur l'utilisateur. Je voudrais également pouvoir actualiser le jeton JWT lorsque le jeton d'accès expire. Y'a-t-il une quelconque façon de réussir cela?

Répondre

0

Je ne suis pas sûr de GMail mais pour votre propre serveur d'autorisation, vous pouvez ajouter un rehausseur de jeton JwtAccessTokenConverter qui convertira votre jeton en JWT.

Pour l'échantillon, pls se oauth2-spring-boot-mongo-jwt-sample

En général, la charge utile jeton normale est inférieure de type

{ 
    "access_token": "bc9c021f-b5ae-43af-9746-737b533f9bc5", 
    "token_type": "bearer", 
    "refresh_token": "fee7a2a1-eff9-4757-8dd3-5392ee225bea", 
    "expires_in": 43199, 
    "scope": "read-foo" } 

alors que, JWT ressemble à ceci

{ 
    "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsiZm9vIl0sInVzZXJfbmFtZSI6InVzZXIiLCJzY29wZSI6WyJyZWFkLWZvbyJdLCJleHAiOjE1MTQ3ODMwNTIsImF1dGhvcml0aWVzIjpbIlJPTEVfVVNFUiJdLCJqdGkiOiJlMjM4MDg1YS0xZjFjLTQ5ZWQtODNiMC1iN2Q1MjI5OWUwZjYiLCJjbGllbnRfaWQiOiJ3ZWItY2xpZW50In0.-OSw1Vr4o1dnAQL3n7QFGG6UOXr4itc0Kp8dugyT4zU", 
    "token_type": "bearer", 
    "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsiZm9vIl0sInVzZXJfbmFtZSI6InVzZXIiLCJzY29wZSI6WyJyZWFkLWZvbyJdLCJhdGkiOiJlMjM4MDg1YS0xZjFjLTQ5ZWQtODNiMC1iN2Q1MjI5OWUwZjYiLCJleHAiOjE1MTczMzE4NTIsImF1dGhvcml0aWVzIjpbIlJPTEVfVVNFUiJdLCJqdGkiOiIzYTA2OTZmMy1mYzg1LTQ2YTEtYjVlMC01NmQ2OGVmYTJhMmUiLCJjbGllbnRfaWQiOiJ3ZWItY2xpZW50In0.jSBriPfM-rSgHHLyifIuBHwrwCkyb5I2u2AKa8kQUUU", 
    "expires_in": 43199, 
    "scope": "read-foo", 
    "jti": "e238085a-1f1c-49ed-83b0-b7d52299e0f6" 
}