首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >当后端在Docker容器中运行时,Keycloak令牌验证失败

当后端在Docker容器中运行时,Keycloak令牌验证失败
EN

Stack Overflow用户
提问于 2022-01-13 13:52:25
回答 2查看 2.9K关注 0票数 5

我正处于构建我的web应用程序的早期阶段。我打算使用Keycloak作为身份提供程序来保护后端的安全。在我的本地机器上,我同时将Keycloak和后端作为码头容器运行,但是在不同的网络上,因为最终在生产中,我希望让身份验证服务器分别运行在后端e.g account.example.comapi.example.com中。

在本地,可以通过基本URL http://localhost:8080/auth访问我的密钥披风容器,通过http://test.localhost:8000/访问后端。

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

因此,后端上的每个REST端点都将验证传递给授权头的令牌,然后调用Keycloak服务器在处理请求之前验证令牌。

我目前遇到的问题是令牌验证在响应中失败。

代码语言:javascript
运行
复制
{"error":"invalid_token","error_description":"Token verification failed"}'

显然,经过调查,这是因为我从后端API容器中调用Keycloak服务器。如果我在后端对接器容器中使用curl生成令牌,那么我接收到的令牌将被很好地验证,但是在容器之外生成的令牌不会被验证。

我正在使用python-keycloak作为密钥披风REST的包装器。

代码语言:javascript
运行
复制
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,
        )

如何解决这个问题并让令牌验证在本地机器上工作?

EN

Stack Overflow用户

回答已采纳

发布于 2022-01-14 08:54:59

令牌无效,因为令牌中的颁发者(iss)与后端服务所期望的颁发者不匹配。

后端(或后端中的适配器/框架)将使用OIDC发现协议来确定预期的发行者。为此,它将调用https://keycloak-container-name/auth/realms/<your-realm>/.well-known/openid-configuration。这将返回如下的元数据:

代码语言:javascript
运行
复制
{
  "issuer":"https://keycloak-container-name/auth/realms/<your-realm>",
  ...
}

Keycloak将根据请求确定发行者的主机部分(在本例中为keycloak-container-name)。因此,如果后端从码头网络中通过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发现端点来验证这一点。你会得到这样的回应:

代码语言:javascript
运行
复制
{
  "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发出请求来检查这一点。它现在将返回像这样的元数据:

代码语言:javascript
运行
复制
{
  "issuer":"http://localhost:8080/auth/realms/<your-realm>",
  ...
}

如果您不想单独为每个领域配置这一点,则可以在整个默认主机名提供程序服务器范围内进行配置。

票数 8
EN
查看全部 2 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70697745

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档