Java-клиент для обновления токена keycloak

Представить,

Ниже приведены 2 клиента (2 микрослужбы) в keyclock.

  • отдых-сервис-1
  • отдых-сервис-2

Ниже представлена ​​роль в rest-service-2

  • сервис-2-пользователь

Для выполнения вызова между службами, т. е.: rest-service-1 вызывает rest-service-2

«rest-service-1» настроен со следующими значениями в Keycloak

Access Type: confidential
Service Account Enabled: Yes

Кроме того, в разделе «Роли учетной записи службы» для rest-service-1 добавляется/сопоставляется следующая роль.

Role for client rest-service-2: service-2-user

После настройки 2 клиентов и учетной записи службы для вызова клиента в keyclock. Я создал проект Spring boot 2.0.3 и использовал следующий код для получения токена.

@Bean
public AuthzClient authzClient(KeycloakSpringBootProperties kcProperties) {
  //org.keycloak.authorization.client.Configuration
  Configuration configuration =
      new Configuration(kcProperties.getAuthServerUrl(), 
                        kcProperties.getRealm(), 
                        kcProperties.getResource(),
                        kcProperties.getCredentials(), null);

  return AuthzClient.create(configuration);
}

Вот как я получаю токен доступа

@Autowired
private AuthzClient authzClient;

public AccessTokenResponse token() {
  return authzClient.obtainAccessToken();
}

Полученный токен:

{
  "access_token": ${access-token},
  "expires_in": 300,
  "refresh_expires_in": 1800,
  "refresh_token": ${refresh-token},
  "token_type": "bearer",
  "id_token": null,
  "not-before-policy": 0,
  "session_state": "6f284b2f-5bb6-4018-8acd-b83923ebb7d7",
  "scope": "profile email"
}

Примечание. Я заменил токены, чтобы сделать его коротким.

ВОПРОС:

Как использовать токен обновления, указанный выше, и получить новый токен доступа. Поддерживает ли AuthzClient это? Если да, то как мне это сделать?

Нужно ли мне создавать новый экземпляр TokenCallable и получать токен? Если да, то как создать экземпляр TokenCallable?

Является ли TokenCallable потокобезопасным?


person Arun Chandrasekaran    schedule 28.06.2018    source источник


Ответы (1)


Вы не можете сделать это явно с помощью класса AuthzClient. Однако вы можете использовать какой-нибудь низкоуровневый API из пакета org.keycloak.authorization.client.util, то есть класс Http. Например:

public AccessTokenResponse refreshToken(String refreshToken) {
    String url = kcProperties.getAuthServerUrl() + "/realms/" + kcProperties.getRealm() + "/protocol/openid-connect/token";
    String clientId = kcProperties.getResource();
    String secret = (String) kcProperties.getCredentials().get("secret");
    Http http = new Http(kcConfig, (params, headers) -> {});

    return http.<AccessTokenResponse>post(url)
            .authentication()
                .client()
            .form()
                .param("grant_type", "refresh_token")
                .param("refresh_token", refreshToken)
                .param("client_id", clientId)
                .param("client_secret", secret)
            .response()
                .json(AccessTokenResponse.class)
            .execute();
}

@Bean
public org.keycloak.authorization.client.Configuration kcConfig() {
    return new org.keycloak.authorization.client.Configuration(
            kcProperties.getAuthServerUrl(),
            kcProperties.getRealm(),
            kcProperties.getResource(),
            kcProperties.getCredentials(),
            null
    );
}

Это решение является полностью потокобезопасным (подробности см. в разделе CloseableHttpClient).

person maslick    schedule 08.02.2019
comment
Привет, это выглядит очень полезным. Один вопрос; выпустив этот запрос на обновление токена, будет ли исходный access_token заменен новым, созданным здесь в качестве побочного эффекта?, или этот код будет генерировать только новый access_token (но замену старого access_token по-прежнему необходимо будет выполнять вручную, поскольку 2-й шаг)? Спасибо! - person tony _008; 10.10.2019
comment
Я попробовал это сам и получил новый токен. Но как заставить приложение использовать только что сгенерированный токен? тк - person tony _008; 11.10.2019
comment
@tony_008 tony_008 Я обновил ответ: вы можете внедрить kcConfig в свой компонент. - person maslick; 11.10.2019
comment
спасибо, что нашли время @maslick. Я могу сгенерировать токен. Проблема, с которой я столкнулся, заключается в том, что я не могу переопределить access_token (и refresh_token), запрошенный пружинным соединителем безопасности в отношении сервера аутентификации keycloack. Я могу сгенерировать токен, но не могу указать своему приложению использовать новый токен, приложение продолжает использовать старый. Вы правильно использовали адаптер Spring-boot + безопасность Spring? Любые отзывы о том, как я могу сказать приложению начать использовать этот вновь созданный токен вместо старого? - person tony _008; 11.10.2019
comment
Я думаю, вы неправильно поняли мою мысль. AuthzClient — это клиент REST для Keycloak. Мой ответ объясняет, как можно получить новый токен с сервера Keycloak через REST, используя токен обновления. - person maslick; 12.10.2019
comment
Привет @maslick thx, так что, чтобы быть на 100% уверенным, вы имеете в виду, что опубликованное вами решение касается, в частности, получения нового токена через REST с использованием токена обновления, но не связано с тем, как использовать этот новый токен в весеннем проекте безопасности. Правильно? - person tony _008; 14.10.2019
comment
@tony_008, если вы используете keycloak-spring-boot-starter, то как только вы обновите токен с помощью AuthzClient, как я описал выше, адаптер Keycloak узнает об обновлении токена. - person maslick; 14.10.2019
comment
Хорошо, я понял, это именно то, что мне нужно. И все же последний вопрос. Разве вы не упомянули в своем ответе на исходный вопрос: вы не можете сделать это явно с помощью AuthzClient lib. Таким образом, ваш код, похоже, не использует AuthzClient. Это правильно или я что-то пропустил? И спасибо за потраченное время, я ценю это. - person tony _008; 15.10.2019
comment
Ты прав! AuthzClient имеет высокоуровневый API, который нельзя использовать для получения токена доступа путем предоставления токена обновления (такого метода нет). Однако пакет org.keycloak.authorization.client имеет некоторый низкоуровневый API, представленный в классе Http (который я использовал в ответе выше). Обычно вы не обновляете токен явно на бэкэнде, но, конечно, у вас может быть прецедент для этого. Вместо этого токен обычно обновляется во внешнем интерфейсе (например, адаптер javascript keycloak). Я обновил ответ (извините за путаницу). ХТН - person maslick; 16.10.2019