在使用Google进行身份验证时,从Spring OAuth2授权服务器发出JWT令牌

在使用Google进行身份验证时,从Spring OAuth2授权服务器发出JWT令牌,jwt,google-oauth,spring-oauth2,Jwt,Google Oauth,Spring Oauth2,我想使用SpringOAuth创建一个授权服务器,它能够发布自己的JWT令牌。授权服务器必须将身份验证委托给Google。我一直在遵循本教程,它几乎完成了我想要的一切: 我能够将Google添加为身份验证提供商,但我正在努力解决JWT部分的问题 以下是我的授权服务器配置: @SpringBootApplication @EnableOAuth2Client @EnableAuthorizationServer @Order(SecurityProperties.ACCESS_OVERRIDE_

我想使用SpringOAuth创建一个授权服务器,它能够发布自己的JWT令牌。授权服务器必须将身份验证委托给Google。我一直在遵循本教程,它几乎完成了我想要的一切:

我能够将Google添加为身份验证提供商,但我正在努力解决JWT部分的问题

以下是我的授权服务器配置:

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

}
我得到以下例外情况:

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
我的理解是:当Google发布访问令牌时,授权服务器(作为Google OAuth的客户端)试图将访问令牌解码为JWT,并抛出异常,因为Google的令牌不是有效的JWT(它只是一个访问令牌)


我想创建一个JWT,其中包含访问令牌(将用于访问GoogleAPI)和一些关于用户的附加信息。我还希望能够在访问令牌过期时刷新JWT令牌。有什么办法可以做到这一点吗?

我不确定GMail,但对于您自己的授权服务器,您可以添加一个令牌增强器
JwtAccessTokenConverter
,它将您的令牌转换为JWT

有关样品,请参考

通常,正常令牌有效负载为以下类型

{
    "access_token": "bc9c021f-b5ae-43af-9746-737b533f9bc5",
    "token_type": "bearer",
    "refresh_token": "fee7a2a1-eff9-4757-8dd3-5392ee225bea",
    "expires_in": 43199,
    "scope": "read-foo" }
然而,JWT看起来像这样

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