0

我当前的用例是:我有一个前端应用程序,用户通过 Keycloak 登录。我想在这个前端(https://www.eclipse.org/ditto/http-api-doc.html)中实现 Ditto HTTP API 的某些部分。

例如,我想为授权创建策略( https://www.eclipse.org/ditto/basic-policy.html )。我在文档中读到可以使用符合 OpenID Connect 的提供程序,其形式为:(https://www.eclipse.org/ditto/basic-policy.html#who-can-be-addressed)。

页面底部有基本的身份验证示例,在这种情况下似乎使用用户名。

{
    "policyId": "my.namespace:policy-a",
    "entries": {
      "owner": {
        "subjects": {
          "nginx:ditto": {
            "type": "nginx basic auth user"
          }
        },
        
    ...
}

我的问题是:如果我想使用 Keycloak,子声明到底是什么?它也是我要授予权限的用户的用户名吗?以及如何在我想指定之后将其发送到 Ditto 的策略的前端中获取此信息?


更新 1

我尝试在 Ditto 中启用 keycloak 身份验证,如下所示,如下所述:https ://www.eclipse.org/ditto/installation-operating.html#openid-connect

因为我使用 Docker Compose 运行 Ditto,所以我在第 136 行的 ditto/deployment/docker/docker-compose.yml 中添加了以下行作为环境变量:- Dditto.gateway.authentication.oauth.openid-connect-issuers.keycloak=http://localhost:8090/auth/realms/twin 此 URL 与我的令牌的颁发者声明中的相同'我从 keycloak 接收。

现在,如果我尝试使用 Postman 向 {{basePath}}/things 发出例如发布请求,我会收到以下错误:

<html>

<head>
    <title>401 Authorization Required</title>
</head>

<body bgcolor="white">
    <center>
        <h1>401 Authorization Required</h1>
    </center>
    <hr>
    <center>nginx/1.13.12</center>
</body>

</html>

我在 Postman 中选择了 Bearer Token 作为 Auth 并粘贴了一个新的令牌。具有默认同上用户的基本身份验证仍在工作。

在此处输入图像描述

我之前是否必须在同上指定新主题/我的用户?


更新 2

我设法通过在 nginx.conf 中注释掉“auth_basic”和“auth_basic_user_file”来关闭 nginx 中的基本身份验证!

它现在似乎被转发到同上,因为现在我收到 Postman 的以下错误:

{ 
   "status": 401, 
   "error": "gateway:jwt.issuer.notsupported", 
   "message": "The JWT issuer 'localhost:8090/auth/realms/twin' is not supported.", 
   "description": "Check if your JWT is correct." 
}

更新 3

我在 gateway.conf 中的配置现在看起来像这样:

oauth {
        protocol = "http"
        openid-connect-issuers = {
          keycloak = "localhost:8090/auth/realms/twin"
        }
      }

我还尝试在 docker-compose.yml 中添加这两行:

- Dditto.gateway.authentication.oauth.protocol=http
- Dditto.gateway.authentication.oauth.openid-connect-issuers.keycloak=localhost:8090/auth/realms/twin

不幸的是,我仍然没有运气,与上述相同的错误:/似乎用户之前在 keycloak 上遇到过类似的问题(https://gitter.im/eclipse/ditto?at=5de3ff186a85195b9edcb1a6),但遗憾的是他没有提到解决方案。

编辑:事实证明,我以错误的方式指定了这些变量,正确的解决方案是将它们作为command: java ... 更多信息的一部分添加到此处


更新 4

我尝试在本地构建 Ditto 而不是使用最新的 docker 映像,我想我现在可能更进一步,看起来我的 oauth 配置正在工作。我现在得到:

{
    "status": 503,
    "error": "gateway:publickey.provider.unavailable",
    "message": "The public key provider is not available.",
    "description": "If after retry it is still unavailable, please contact the service team."
}

日志中的错误消息是:

gateway_1        | 2020-11-05 15:33:18,669 WARN  [] o.e.d.s.g.s.a.j.DittoPublicKeyProvider  - Got Exception from discovery endpoint <http://localhost:8090/auth/realms/twin/.well-known/openid-configuration>.
gateway_1        | akka.stream.StreamTcpException: Tcp command [Connect(localhost:8090,None,List(),Some(10 seconds),true)] failed because of java.net.ConnectException: Connection refused
gateway_1        | Caused by: java.net.ConnectException: Connection refused
...
gateway_1        | java.util.concurrent.CompletionException: org.eclipse.ditto.services.gateway.security.authentication.jwt.PublicKeyProviderUnavailableException [message='The public key provider is not available.', errorCode=gateway:publickey.provider.unavailable, statusCode=SERVICE_UNAVAILABLE, description='If after retry it is still unavailable, please contact the service team.', href=null, dittoHeaders=ImmutableDittoHeaders [{}]]
...
gateway_1        | Caused by: org.eclipse.ditto.services.gateway.security.authentication.jwt.PublicKeyProviderUnavailableException [message='The public key provider is not available.', errorCode=gateway:publickey.provider.unavailable, statusCode=SERVICE_UNAVAILABLE, description='If after retry it is still unavailable, please contact the service team.', href=null, dittoHeaders=ImmutableDittoHeaders [{}]]
...
gateway_1        | Caused by: akka.stream.StreamTcpException: Tcp command [Connect(localhost:8090,None,List(),Some(10 seconds),true)] failed because of java.net.ConnectException: Connection refused
gateway_1        | Caused by: java.net.ConnectException: Connection refused

我的 keyloak 肯定在运行,我可以获得代币。如果我正在打开http://localhost:8090/auth/realms/twin/.well-known/openid-configuration第一条错误消息中的内容,我可以从 keycloak 配置中看到我的 openid 配置。编辑:似乎我的网关容器无法到达我的 keycloak 容器,将尝试解决这个问题。


最后更新

来自网关 docker 容器的无法访问的 keycloak docker 容器是问题所在。我现在正在使用 traefik:

  1. Keycloak 容器具有以下别名:keycloak.localhost
  2. 网关中的 Oauth 配置如下所示:
oauth {
        protocol = "http"
        openid-connect-issuers = {
          keycloak = "keycloak.localhost/auth/realms/twin"
        }
      }
  1. 现在网关可以通过别名找到 keycloak 容器,我仍然可以使用本地主机中的 keycloak admin ui:http://keycloak.localhost:8090/auth/admin/

附加信息:Traefic 博客

4

1 回答 1

2

如果我想使用 Keycloak,子声明到底是什么?

Keycloak 为您提供 JWT。

JWT 是一个加密的 JSON,其中包含多个称为“声明”的字段。您可以通过访问https://jwt.io并将您的令牌粘贴到那里来检查您的令牌的外观。其中一个字段称为sub. 这是子声明

要在 eclipse ditto 中启用 keycloak 身份验证,您需要将颁发者添加到 ditto 配置中。

一个例子可以在这里找到。该地址必须与您的 JWT 令牌的颁发者声明中的 URL 匹配。

ditto.gateway.authentication {
    oauth {
      protocol = "http"
      openid-connect-issuers = {
        some-name = "localhost:8090/auth/realms/twin"
      }
    }
}

它也是我要授予权限的用户的用户名吗?

在 Eclipse 中,实际上并没有“用户名”的概念。Eclipse 同上身份验证基于授权主题。对于您提供的基本身份验证示例,在同上生成的授权主题是nginx:ditto.

对于 JWT 身份验证,授权主题是作为您配置的 open id 连接颁发者的名称(在我的情况下some-name)和 sub 声明的值的组合生成的。授权主题可能如下所示:some-name:8d078113-3ee5-4dbf-8db1-eb1a6cf0fe81.

以及如何在我想指定之后将其发送到 Ditto 的策略的前端中获取此信息?

我不确定我是否正确理解了这个问题。如果您的意思是如何对 eclipse 同上的前端 HTTP 请求进行身份验证,则需要通过将 JWT 添加到 HTTP 请求的授权标头中来提供 JWT 到 eclipse 同上,格式如下:

authorization: Bearer yourJWT

如果您的意思是如何知道 JWT 的子声明,则需要将JWT 解析为 JSON 对象,然后从有效负载部分中读取子声明。

于 2020-11-02T05:24:36.453 回答