簡體   English   中英

使用外部 IDP 代理通過 KeyCloak 編程用戶名/密碼訪問

[英]Programatic username/password access with KeyCloak using external IDP brokering

我正在使用身份代理功能和外部 IDP。 因此,用戶登錄到外部 IDP UI,然后 KeyCloak 代理客戶端從外部 IDP 接收 JWT 令牌,KeyCloak 提供 JWT 用於我們訪問資源。 我已經設置了Default Identitiy Provider功能,因此在用戶登錄時會向用戶顯示外部 IDP 登錄屏幕。 這意味着用戶及其密碼存儲在外部 IDP 上。

當我需要在測試中以編程方式使用“直接訪問授權”(資源所有者密碼授權)登錄時,就會出現問題。 由於密碼未存儲在 KeyCloak 上,我總是在登錄時從 KeyCloak 收到 401 Unauthorized 錯誤。 當我嘗試更改用戶密碼時,它開始工作,所以問題是 KeyCloak 上沒有提供用戶密碼,並且使用“直接訪問授權”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 向我們提供它的有效令牌?

問題是 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. 首先,您需要啟用令牌交換功能,在您的 keycloak 啟動命令行中添加 2 個參數(取決於您的操作方式) -Dkeycloak.profile=preview -Dkeycloak.profile.feature.token_exchange=enabled IDP(對於我來說是ADFS ) tab 具有令牌交換權限的權限將可用。
  2. 向客戶端 KEYCLOAK-CLIENT 添加一個策略到“token-exchange”提供者權限
  3. 將此先前的策略添加到“令牌交換”客戶端權限

使用 POSTMAN,您可以測試身份驗證流程:

外部 IDP ADFS 登錄用戶名/密碼令牌交換

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM