Spring Boot JWT токены неверной подписи при использовании рефреста токена - PullRequest
0 голосов
/ 15 октября 2019

Итак, я создаю OAuth-сервер.

Я в состоянии подключиться к своему серверу авторизации, но подпись кажется недействительной.

Вменяя его в https://jwt.io/, получается недействительная подпись. Что еще хуже, когда я пытаюсь использовать токен обновления, я получаю InvalidTokenException, не могу преобразовать токен доступа в JSON.

Это тайно исходит от JwtAccessTokenConverter.java

protected Map<String, Object> decode(String token) {
        try {
            Jwt jwt = JwtHelper.decodeAndVerify(token, verifier);
            String claimsStr = jwt.getClaims();
            Map<String, Object> claims = objectMapper.parseMap(claimsStr);
            if (claims.containsKey(EXP) && claims.get(EXP) instanceof Integer) {
                Integer intValue = (Integer) claims.get(EXP);
                claims.put(EXP, new Long(intValue));
            }
            this.getJwtClaimsSetVerifier().verify(claims);
            return claims;
        }
        catch (Exception e) {
            throw new InvalidTokenException("Cannot convert access token to JSON", e);
        }
    }

реальное исключение - вычисленноеподпись не соответствует данной. Так что по какой-то причине подпись на самом деле не подписывает все. У меня есть пользовательский токен-энхансер, который помещает пару дополнительных значений. Я подозреваю, что это не подписывается, не то чтобы я знаю почему.

Ниже мой сервер авторизации

@Configuration
@EnableAuthorizationServer
@EnableConfigurationProperties(SecurityProperties::class)
class AuthorizationServerConfiguration(private val dataSource: DataSource, private val passwordEncoder: PasswordEncoder,
                                       private val authenticationManager: AuthenticationManager, private val securityProperties: SecurityProperties,
                                       private val userDetailsService: UserDetailsService) : AuthorizationServerConfigurerAdapter() {

    private var jwtAccessTokenConverter: JwtAccessTokenConverter? = null
    private var tokenStore: TokenStore? = null

    @Bean
    fun tokenEnhancer(): CustomTokenEnhancer {
        return CustomTokenEnhancer()
    }

    @Bean
    fun loggingExceptionTranslator(): DefaultWebResponseExceptionTranslator {
        return object : DefaultWebResponseExceptionTranslator() {
            @Throws(Exception::class)
            override fun translate(e: Exception): ResponseEntity<OAuth2Exception> {
                // This is the line that prints the stack trace to the log. You can customise this to format the trace etc if you like
                e.printStackTrace()

                // Carry on handling the exception
                val responseEntity = super.translate(e)
                val headers = HttpHeaders()
                headers.setAll(responseEntity.headers.toSingleValueMap())
                val excBody = responseEntity.body
                return ResponseEntity(excBody, headers, responseEntity.statusCode)
            }
        }
    }

    @Bean
    fun tokenStore(): TokenStore {
        if (tokenStore == null) {
            tokenStore = JwtTokenStore(tokenEnhancer())
        }
        return tokenStore as TokenStore
    }

    @Bean
    fun tokenServices(tokenStore: TokenStore,
                      clientDetailsService: ClientDetailsService): DefaultTokenServices {
        val tokenServices = DefaultTokenServices()
        tokenServices.setSupportRefreshToken(true)
        tokenServices.setTokenStore(tokenStore)
        tokenServices.setAuthenticationManager(this.authenticationManager)
        tokenServices.setAccessTokenValiditySeconds(securityProperties.tokenTimeToLive)
        return tokenServices
    }

    @Bean
    fun jwtAccessTokenConverter(): JwtAccessTokenConverter {
        if (jwtAccessTokenConverter != null) {
            return jwtAccessTokenConverter as JwtAccessTokenConverter
        }

        val jwtProperties = securityProperties.jwt
        val keyPair = jwtProperties?.let { keyStoreKeyFactory(it) }?.let { keyPair(jwtProperties, it) }
        jwtAccessTokenConverter = CustomTokenEnhancer()
        jwtAccessTokenConverter!!.setKeyPair(keyPair!!)
        jwtAccessTokenConverter!!.afterPropertiesSet()
        return jwtAccessTokenConverter as JwtAccessTokenConverter
    }

    @Throws(Exception::class)
    override fun configure(clients: ClientDetailsServiceConfigurer) {
        clients.jdbc(this.dataSource)
    }

    override fun configure(endpoints: AuthorizationServerEndpointsConfigurer) {
        endpoints.authenticationManager(this.authenticationManager)
                .accessTokenConverter(jwtAccessTokenConverter())
                .userDetailsService(this.userDetailsService)
                .tokenStore(tokenStore())
    }

    override fun configure(oauthServer: AuthorizationServerSecurityConfigurer) {
        oauthServer.passwordEncoder(this.passwordEncoder).tokenKeyAccess("permitAll()")
                .checkTokenAccess("isAuthenticated()")
    }

    private fun keyPair(jwtProperties: SecurityProperties.JwtProperties?, keyStoreKeyFactory: KeyStoreKeyFactory): KeyPair {
        return keyStoreKeyFactory.getKeyPair(jwtProperties?.keyPairAlias, jwtProperties?.keyPairPassword?.toCharArray())
    }

    private fun keyStoreKeyFactory(jwtProperties: SecurityProperties.JwtProperties): KeyStoreKeyFactory {
        return KeyStoreKeyFactory(jwtProperties.keyStore, jwtProperties.keyStorePassword?.toCharArray())
    }
}

1 Ответ

0 голосов
/ 15 октября 2019

Мне нужно было использовать компонент в следующей строке

@Bean
fun tokenStore(): TokenStore {
    return JwtTokenStore(jwtAccessTokenConverter())
}
...