У меня есть мультитенантное приложение (адаптер keyboak для Springboot + защита от Spring), защищенное keycloak. Учитывая мультитенатную природу проекта, я написал многоклиентный коннектор, который прекрасно работает.
На официальном документе Keaycloak рекомендуется (для мультитенантных приложений) моделировать каждый теннант как новую область, но для меня этолучше работает, когда несколько клиентов находятся в одной и той же области. Это обусловлено следующими преимуществами:
- Области клиента, группы и другие конфигурации могут быть общими
- Пользователям не нужно дублировать данные в N различных сферах
- Вход в систему единого входа прекрасно работает в одних и тех же клиентах области (с использованием служб переноса + CORS)
Итак, все работает отлично, за исключением 1 вещи, моего начального единого входа для доступа (который затем используется всеми службами только переноса)с помощью CORS) довольно большой (он показывает все ресурсы - tennants - и их роли в каждом ресурсе / tennant).
Я бы хотел ограничить размер access_token с помощью использования"scopes", чтобы ограничить роли access_token теми, которые значат для tennat, где я вошел в то время. Для этого я вручную запускаю запрос к серверу авторизации (за пределами стандартной функциональности, предоставляемой springboot / spring security) с целью ручной перезаписи того, есть ли токен доступа в моем приложении, с новым, сгенерированным моим дополнительнымrequest.
Мой «новый» запрос токена выглядит примерно так:
SimpleKeycloakAccount currentUserAccount = (SimpleKeycloakAccount) auth.getDetails();
String authServerUrl = currentUserAccount.getKeycloakSecurityContext().getDeployment().getAuthServerBaseUrl();
String realm = currentUserAccount.getKeycloakSecurityContext().getDeployment().getRealm();
String resource = currentUserAccount.getKeycloakSecurityContext().getDeployment().getResourceName();
String refreshToken = currentUserAccount.getKeycloakSecurityContext().getRefreshToken();
String token = currentUserAccount.getKeycloakSecurityContext().getTokenString();
Http http = new Http( new Configuration(authServerUrl, realm, resource,
currentUserAccount.getKeycloakSecurityContext().getDeployment().getResourceCredentials()
, null),
(params, headers) -> {});
String url = authServerUrl + "/realms/" + realm + "/protocol/openid-connect/token";
AccessTokenResponse response = http.<AccessTokenResponse>post(url)
.authentication()
.client()
.form()
.param("grant_type", "refresh_token")
.param("refresh_token", refreshToken)
.param("client_id", resource)
.param("client_secret", "SOME_SECRET")
.param("scope", "SOME_SCOPE_TO_RESTRICT_ROLES")
.response()
.json(AccessTokenResponse.class)
.execute();
// :) - response.getToken() and response.getRefreshToken(), contain new successfully generated tokens
Мой вопрос состоит в том, как заставить мое приложение изменить / сбросить стандартный токен доступа и refresh_tokenполученные обычными средствами, с этими "созданными на заказ" токенами? или это вообще возможно?
Спасибо за любой отзыв!
Дополнительная информация
Чтобы прояснить подробнее, давайте проанализируем поведение типичного проекта безопасности Springboot / Spring, интегрированного с keycloack:
- Вы защищаете свои конечные точки с помощью «ролей» через конфигурации (либо в application.properties, либо в SecurityContext)
- Вы знаете, что это приложение Spring взаимодействует в обратном каналес сервером авторизации keycloak вот так вы становитесь access_token (но все это черный ящик для разработчика, вы только знаете, что был создан принципал, контекст безопасности, учетные данные и т. д. - все происходит за кулисами)
Учитывая эти 2 пункта выше, представьте, что вы используете библиотеку Http для запроса нового токена к конечной точке токена сервера аутентификации, как в приведенном выше коде (да, отфильтрованные по областям и тому подобное). Таким образом, теперь ситуация такова, что, хотя вы создали действительный acces_token (и refresh_token);поскольку они были созданы «вручную» путем отправки запроса к конечной точке токена, этот новый токен не был «включен» в приложение, поскольку не было создано никакого нового принципала, не был создан новый контекст безопасности и т. д. Другими словамиДля приложения Springboot этот новый токен не существует.
Что я пытаюсь сделать, это сказать sprinboot / spring security: «Эй, приятель, я знаю, что ты сам не генерировал этот токен, но, пожалуйста, прими его и веди себя так, как если бы ты его создал».
Надеюсь, это прояснит смысл моего вопроса.