Программный доступ к имени пользователя и паролю с помощью 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.

  1. Сначала вам нужно включить функцию обмена токенами, добавив 2 параметра в вашу командную строку запуска keycloak (в зависимости от того, как вы это делаете) -Dkeycloak.profile=preview -Dkeycloak.profile.feature.token_exchange=enabled IDP (для меня ADFS) Вкладка Разрешения с разрешением на обмен токенами будут доступны.
  2. Добавьте политику к разрешению провайдера "обмен токенами", к клиенту KEYCLOAK-CLIENT
  3. Добавьте эту предыдущую политику в разрешение клиента "обмен токенами"

С POSTMAN вы можете проверить процесс аутентификации:

Внешний IDP ADFS для входа в систему Имя пользователя / пароль Обмен токенами

Другие вопросы по тегам