本文介紹了通過使用外部IDP代理的KeyCloak進行程序化用戶名/密碼訪問的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!
問題描述
我正在使用Identity Brokering功能和外部IdP。因此,用戶登錄到外部IdP用戶界面,然后KeyCloak Broker客戶端從外部IdP接收JWT令牌,KeyCloak提供JWT供我們訪問資源。我已經設置了Default Identitiy Provider功能,以便在登錄時向用戶顯示外部IDP登錄屏幕。這意味著用戶及其密碼存儲在外部IdP上。
當我需要在測試中以編程方式使用”Direct Access Grant”(資源所有者密碼授予)登錄時,會出現這個問題。由于密碼沒有存儲在KeyCloak上,登錄時我總是從KeyCloak收到401未經授權的錯誤。當我試圖更改用戶密碼時,它開始起作用了,所以問題是用戶密碼沒有在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();
}
有沒有辦法解決這個問題?例如,在”Direct Access Grant”上調用Identity Broker,以便KeyCloak向我們提供其有效令牌?
推薦答案
問題在于KeyCloak沒有來自初始身份提供者的有關密碼的信息。它們具有token exchange feature,應用于編程令牌交換。
External Token to Interanal Token Exchange應使用它。
下面是一個用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']
這篇關于通過使用外部IDP代理的KeyCloak進行程序化用戶名/密碼訪問的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,