Добавление данных пользователя в полезную нагрузку JWT для весенней безопасности OAUth2

Я использую весеннюю безопасность OAuth2, используя токены JWT в течение некоторого времени, но теперь мне нужно добавить 2 определяемых пользователем значения в токен JWT.

Поэтому, когда я добавил в запрос дополнительный набор параметров /oauth/token?grant_type=client_credentials&user_value=1234567890.

Значение user_value выше было для демонстрационных целей. Я могу проследить его до моего CustomTokenEnhancer (я подключил его, чтобы передать эту информацию полностью). Все параметры запроса видны через аутентификацию OAuth2Authentication, которая передается моему CustomTokenEnhancer.

Теперь я могу добавить эту информацию к дополнительной информации, которую я вижу, возвращаемую мне как часть запроса токена. Смотри ниже.

{
   "access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsicGhpLWFwaSJdLCJzY29wZSI6WyJyZWFkIiwid3JpdGUiXSwib3JnYW5pemF0aW9uIjoicGhpLXVzZXJtZ3RuIiwidXNlcl90b2tlbiI6IjEyMzQ1Njc4OTAiLCJleHAiOjE0ODczNjc2NzEsImF1dGhvcml0aWVzIjpbIlJPTEVfQ0xJRU5UIl0sImp0aSI6IjFlZDMzZTAxLTc1ZGUtNDNjZC1hMzk2LTFkMzk2N2Y1NDQ5OCIsImNsaWVudF9pZCI6InBoaS11c2VyIn0.p628BNaaGljypEcGXZMkstNeTN-221qzzNQQ0npxDLTszWaXkgXqsBnBbKf9XMEtWTeCQkIszC9ne1Ei2X5IWTskhLT9Rko-8K7Jq-mXUc6HJZW-3tGV5rRer8Eyyw1wysW9Jiyp7sPkN-TIx12A70f_LHm6PrRR4ECppHWADs-2DvYA30p8omT1_RTt2WlqC40mopUN2TBPkb1WulVpOUEpcP358Ox8oVP8VQRSkLGZKB_b0KZAK9KGjLg6WNh8RghZaBuYuJQpITe_0XEBs_JfwrHhcK1IGaoYwSS7IGp3Cima9OMljdzayDKRqlfSl3WhaBuFmD1S37p-OVQL0A",
   "token_type":"bearer",
   "expires_in":8967,
   "scope":"read write",
   "user_value":"1234567890",
   "jti":"1ed33e01-75de-43cd-a396-1d3967f54498"
}

Но я не хочу, чтобы эти значения были видны таким образом. Я хочу, чтобы они были добавлены в зашифрованный токен.

Я потратил некоторое время на поиски, и неясно, как я на самом деле добавляю это. Это должно быть возможно, не так ли?


person EvilJinious1    schedule 17.02.2017    source источник


Ответы (3)


Внутри вашего собственного TokenEnhancer вам нужно снова закодировать его:

@Override
public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
    // Generate additional Information [...]


    // Write it to the token
    ((DefaultOAuth2AccessToken)accessToken).setAdditionalInformation(addInfo);

    // Encode Token to JWT
    String encoded = super.encode(accessToken, authentication);

    // Set JWT as value of the token
    ((DefaultOAuth2AccessToken) accessToken).setValue(encoded);

    return accessToken;
}

Вы можете решить эту проблему с помощью методов JwtHelper, но я просто расширил JwtAccessTokenConverter, поэтому я мог просто использовать кодирование и декодирование.

При создании экземпляра вашего усилителя токена вы должны добавить информацию о хранилище ключей:

private CustomTokenEnhancer jwtCustomEnhancer() {
    KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(new ClassPathResource("jwt.jks"), "***".toCharArray());
    CustomTokenEnhancer converter = new CustomTokenEnhancer();
    converter.setKeyPair(keyStoreKeyFactory.getKeyPair("jwt"));

    return converter;
}
person Eknoes    schedule 08.04.2017

Я сделал что-то подобное, передав значение в качестве предоставленных полномочий с помощью службы сведений о пользователе (а не усилителя токена). На стороне клиента я написал экстрактор для извлечения значений из принципала, введенного Spring как тип OAuth2Authentication. Следующий код написан на Scala, но вы можете легко адаптировать его к Java:

/**
  * Mix-in to implicitly extract entity or identity from the principal.
  */
trait AuthorityExtractor {

  def _contextName(implicit principal: OAuth2Authentication) = id(principal, "CONTEXT_")

  def _entityId(implicit principal: OAuth2Authentication) = id(principal, "ENTITY_ID_")

  def _userId(implicit principal: OAuth2Authentication) = id(principal, "USER_ID_")

  def _identityId(implicit principal: OAuth2Authentication) = id(principal, "SELF_ID_")

  private def id(principal: OAuth2Authentication, prefix: String) = {
    import collection.JavaConversions._
    principal
      .getAuthorities
      .filter(_.toString.startsWith(prefix))
      .map(_.toString.substring(prefix.length))
      .headOption.getOrElse("")
  }

}

person Maurício Fernandes de Castro    schedule 22.02.2017

Я расширяю класс JwtAccessTokenConverter следующим образом:

public class FooJwtAccessTokenConverter extends JwtAccessTokenConverter {
  @Override
  public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
     DefaultOAuth2AccessToken fooAccessToken = new DefaultOAuth2AccessToken(accessToken);
     fooAccessToken.getAdditionalInformation().put("foo_property", "foo");
     return super.enhance(scaAccessToken, authentication);
  }

В моем AuthotizationServerConfig я создаю это:

@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
    endpoints
            .tokenStore(tokenStore())
            .accessTokenConverter(accessTokenConverter())
            .authenticationManager(authenticationManager);
}

@Bean
public TokenStore tokenStore() {
    return new JwtTokenStore(accessTokenConverter());
}

@Bean
public JwtAccessTokenConverter accessTokenConverter() {
    ScaJwtAccessTokenConverter accessTokenConverter = new ScaJwtAccessTokenConverter();
    accessTokenConverter.setSigningKey("familia-mgpe"); // Parte da string de validação do token JWT.
    return accessTokenConverter;
}
person Cirilo Lourenço X Junior    schedule 12.09.2017