Программный доступ к имени пользователя и паролю с помощью KeyCloak с использованием внешнего брокера IDP
Я использую функцию Identity Brokering и внешний IDP. Итак, пользователь входит во внешний интерфейс IDP, затем клиент-брокер KeyCloak получает токен JWT от внешнего IDP, а KeyCloak предоставляет JWT, с помощью которого мы получаем доступ к ресурсам. Я настроил функцию " Поставщик идентификаторов по умолчанию", чтобы при входе пользователю отображался внешний экран входа в систему IDP. Это означает, что пользователи и их пароли хранятся на внешнем IDP.
Проблема возникает, когда мне нужно войти в систему, используя "Предоставление прямого доступа" (предоставление пароля владельца ресурса) программно в тестах. Поскольку пароль не хранится в KeyCloak, я всегда получаю 401 несанкционированную ошибку от KeyCloak при входе в систему. Когда я попытался изменить пароль пользователя, он начал работать, поэтому проблема в том, что пароль пользователя не предоставляется на KeyCloak, а использование "Direct Access Grant" KeyCloak не вызывает внешний IDP при программном входе в систему.
Я использую следующий код для получения токена доступа, но получаю ошибку 401 каждый раз, когда передаю действительное имя пользователя / пароль.
org.keycloak.authorization.client.util.HttpResponseException: Unexpected response from server: 401 / Unauthorized
Для этого клиента разрешено предоставление прямого доступа.
public static String login(final Configuration configuration) {
final AuthzClient authzClient = AuthzClient.create(configuration);
final AccessTokenResponse accessTokenResponse = authzClient.obtainAccessToken(USERNAME, PASSWORD);
return accessTokenResponse.getToken();
}
Есть ли способ это исправить? Например, чтобы позвонить брокеру идентификации по "Прямому доступу", чтобы KeyCloak предоставил нам его действительный токен?
1 ответ
Проблема заключалась в том, что KeyCloak не имеет информации о паролях от первоначального провайдера идентификации. У них есть функция обмена токенами, которая должна использоваться для программного обмена токенами.
Для достижения этой цели необходимо использовать внешний токен для обмена внутренними токенами.
Вот пример кода в Python, который делает это (просто поместите правильные значения в заполнители):
def login():
idp_access_token = idp_login()
return keycloak_token_exchange(idp_access_token)
def idp_login():
login_data = {
"client_id": <IDP-CLIENT-ID>,
"client_secret": <IDP-CLIENT-SECRET>,
"grant_type": <IDP-PASSWORD-GRANT-TYPE>,
"username": <USERNAME>,
"password": <PASSWORD>,
"scope": "openid",
"realm": "Username-Password-Authentication"
}
login_headers = {
"Content-Type": "application/json"
}
token_response = requests.post(<IDP-URL>, headers=login_headers, data=json.dumps(login_data))
return parse_response(token_response)['access_token']
def keycloak_token_exchange(idp_access_token):
token_exchange_url = <KEYCLOAK-SERVER-URL> + '/realms/master/protocol/openid-connect/token'
data = {
'grant_type': 'urn:ietf:params:oauth:grant-type:token-exchange',
'subject_token': idp_access_token,
'subject_issuer': <IDP-PROVIDER-ALIAS>,
'subject_token_type': 'urn:ietf:params:oauth:token-type:access_token',
'audience': <KEYCLOAK-CLIENT-ID>
}
response = requests.post(token_exchange_url, data=data,
auth=(<KEYCLOAK-CLIENT-ID>, <KEYCLOAK-CLIENT-SECRET>))
logger.info(response)
return parse_response(response)['access_token']
Этот пример был очень полезен для меня, я только хочу добавить дополнительную информацию о KEYCLOAK-CLIENT, используемом для обмена токенами (для меня authorization_client). Я использую KEYCLOAK в качестве брокера для IDP ADFS.
- Сначала вам нужно включить функцию обмена токенами, добавив 2 параметра в вашу командную строку запуска keycloak (в зависимости от того, как вы это делаете) -Dkeycloak.profile=preview -Dkeycloak.profile.feature.token_exchange=enabled IDP (для меня ADFS) Вкладка Разрешения с разрешением на обмен токенами будут доступны.
- Добавьте политику к разрешению провайдера "обмен токенами", к клиенту KEYCLOAK-CLIENT
- Добавьте эту предыдущую политику в разрешение клиента "обмен токенами"
С POSTMAN вы можете проверить процесс аутентификации:
Внешний IDP ADFS для входа в систему Имя пользователя / пароль Обмен токенами