我正處于構建 Web 應用程式的早期階段。我打算使用 Keycloak 作為身份提供者來保護后端。在我的本地機器上,我將 Keycloak 和我的后端作為 docker 容器運行,但在不同的網路上,因為最終在生產中,我希望運行 Keycloak 的身份驗證服務器與后端分開運行,例如account.example.com分別api.example.com運行
在本地,我的 Keycloak 容器可以通過基本 URLhttp://localhost:8080/auth和后端訪問http://test.localhost:8000/
我在 Keycloak 領域創建了一個訪問型別為機密的客戶端。我正在使用授權代碼授予型別生成令牌。
因此,后端的每個 REST API 端點都會驗證傳遞給授權標頭的令牌,然后在處理請求之前呼叫 Keycloak 服務器來驗證令牌。
我目前遇到的問題是令牌驗證失敗并回應
{"error":"invalid_token","error_description":"Token verification failed"}'
經過調查,顯然是因為我從后端 API 容器呼叫 Keycloak 服務器。如果我在后端 docker 容器中使用 curl 生成令牌,則我收到的令牌正在驗證良好,但在容器外部生成的令牌不是。
我python-keycloak用作 Keycloak REST API 的包裝器
from keycloak import KeycloakOpenID
self._keycloak = KeycloakOpenID(
server_url='http://host.docker.internal:8080/auth/',
realm_name='myrealm',
client_id='myclient',
client_secret_key='mysecret,
)
if "HTTP_AUTHORIZATION" not in request.META:
return JsonResponse(
{"detail": NotAuthenticated.default_detail},
status=NotAuthenticated.status_code,
)
auth_header = request.META.get("HTTP_AUTHORIZATION").split()
token = auth_header[1] if len(auth_header) == 2 else auth_header[0]
try:
self.keycloak.userinfo(token)
except KeycloakInvalidTokenError as e:
# print(e)
return JsonResponse(
{"detail": AuthenticationFailed.default_detail},
status=AuthenticationFailed.status_code,
)
如何解決此問題并在我的本地計算機上進行令牌驗證
uj5u.com熱心網友回復:
問題在于issuer令牌。郵遞員的令牌頒發者是http://localhost:8080/...,但后端配置為僅接受頒發者http://host.docker.internal:8080/...。最佳實踐是在任何地方都使用相同protocol:domain[:port]的 IdP(在您的情況下為 Keycloak)https://keycloak.domain.com,否則您將遇到此類問題。
uj5u.com熱心網友回復:
您的令牌無效,因為令牌中的頒發者 ( iss) 與您的后端服務預期的頒發者不匹配。
您的后端(或后端中的配接器/框架)將使用 OIDC 發現協議來確定預期的頒發者。為此,它將呼叫https://keycloak-container-name/auth/realms/<your-realm>/.well-known/openid-configuration. 這將回傳如下元資料:
{
"issuer":"https://keycloak-container-name/auth/realms/<your-realm>",
...
}
Keycloak 將根據請求確定頒發者的主機部分(keycloak-container-name在這種情況下)。因此,如果您的后端從 docker 網路中查詢發現端點,keycloak-container-name則主機部分將是your-container-name. 您的后端會期望發行人https://keycloak-container-name/auth/realms/<your-realm>在這種情況下。
現在,如果您想從前端查詢令牌,您的前端會將請求發送到http://localhost:8080/auth/.... 由于發行者將根據請求確定,因此該令牌中的發行者將https://localhost:8080/auth/realms/<your-realm>在這種情況下。這與預期的發行者不匹配https://keycloak-container-name/auth/realms/<your-realm>,因此令牌將被視為無效而被拒絕。
您還可以通過呼叫 OIDC 發現端點來驗證這一點http://localhost:8080/auth/realms/<your-realm>/.well-known/openid-configuration。你會得到這樣的回應:
{
"issuer":"http://localhost:8080/auth/realms/<your-realm>",
...
}
要解決此問題,您可以將Frontend URL領域中的 設定為http://localhost:8080/auth. 使用此設定,發行者將不再在請求中確定,而是將被固定http://localhost:8080/auth/realms/<your-realm>。您可以通過向https://keycloak-container-name/auth/realms/<your-realm>/.well-known/openid-configuration. 這將回傳像這樣的元資料:
{
"issuer":"http://localhost:8080/auth/realms/<your-realm>",
...
}
如果您不想為每個領域單獨配置它,您可以改為在服務器范圍內配置默認主機名提供程式。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/410986.html
標籤:
上一篇:無法從Web瀏覽器訪問EC2上的dockerwebapp
下一篇:GAE標準中的grpc
