Итак, я создаю 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())
}
}