后端运行在Docker容器中时,密钥伪装令牌验证失败 [英] Keycloak token verification fails when the backend is running in a Docker container
本文介绍了后端运行在Docker容器中时,密钥伪装令牌验证失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我正处于构建Web应用程序的早期阶段。我打算使用Keyloak作为身份提供者来保护后端。在我的本地机器上,我同时运行Keyshaak和我的后端作为docker容器,但在不同的网络上,因为最终在生产中,我希望运行Keyshaak的身份验证服务器与后端分开运行,例如分别account.example.com
和api.example.com
在本地,可以通过基本URLhttp://localhost:8080/auth
访问我的Keyloak容器,通过http://test.localhost:8000/
访问后台
因此,后端上的每个REST API终结点都将验证传递给授权头的令牌,然后在处理请求之前调用Keyloak服务器来验证令牌。
我目前遇到的问题是令牌验证失败,响应为
{"error":"invalid_token","error_description":"Token verification failed"}'
经过调查,很明显,这是因为我正在从后端API容器调用Keyloak服务器。如果我在后端docker容器内使用cURL生成令牌,则我收到的令牌可以通过验证,但在容器外部生成的令牌则不能。
我正在使用python-keycloak
作为Keyloak 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,
)
如何解决此问题并在本地计算机上进行令牌验证
推荐答案
您的令牌无效,因为令牌中的颁发者(iss
)与您的后端服务期望的颁发者不匹配。
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>
不匹配,因此该令牌将被拒绝为无效。
您还可以通过http://localhost:8080/auth/realms/<your-realm>/.well-known/openid-configuration
调用OIDC发现端点来验证这一点。您将得到如下响应:
{
"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>",
...
}
如果您不想分别为每个领域配置此设置,则可以改为在服务器范围内配置default hostname provider。
这篇关于后端运行在Docker容器中时,密钥伪装令牌验证失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文