后端运行在Docker容器中时,密钥伪装令牌验证失败 [英] Keycloak token verification fails when the backend is running in a Docker container

查看:17
本文介绍了后端运行在Docker容器中时,密钥伪装令牌验证失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正处于构建Web应用程序的早期阶段。我打算使用Keyloak作为身份提供者来保护后端。在我的本地机器上,我同时运行Keyshaak和我的后端作为docker容器,但在不同的网络上,因为最终在生产中,我希望运行Keyshaak的身份验证服务器与后端分开运行,例如分别account.example.comapi.example.com

在本地,可以通过基本URLhttp://localhost:8080/auth访问我的Keyloak容器,通过http://test.localhost:8000/访问后台

我已经在Keyshaak领域中创建了一个访问类型为机密的客户端。我正在使用授权码授权类型生成令牌。

因此,后端上的每个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)与您的后端服务期望的颁发者不匹配。

您的后端(或后端中的适配器/框架)将使用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>不匹配,因此该令牌将被拒绝为无效。

您还可以通过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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆