我如何使用 gRPC 为 google 云 运行 设置 jwcrypto 令牌发行者?

How would I setup a jwcrypto token issuer for google cloud run with gRPC?

我正在尝试为 Google 云端点创建自定义身份验证方法。这个想法是我可以配置我的 ESPv2 容器(基于 Envoy 的可扩展服务代理),它托管在 Google 云 运行 上,从自定义发行者那里获取 JWT,也托管在云 [=36] 上=].

按照指南 Endpoints guide for gRPC,我认为 yaml 文件的 jwks_uri: 部分应该指向一个 URL,它暴露了 public 键(我认为你可以通过将 JWK 放入 json 文件并将所述 JSON 文件托管在 google 云存储上,将其公开到 public 互联网来实现。

让我难过的部分是发行者,我已经完成了 RFC7519,它指出发行者是一个字符串或 URI 值。我不太熟悉 ESPv2 容器使用的 Envoy 的具体实现,但我最好的猜测是 yaml 文件中的 issuer: 选项只是用于匹配从服务器发出的域或字符串创建令牌时。

我可能是错的,所以非常感谢您提供有关这方面的指导。

亲切的问候,

卑鄙B

issuer 应该是您发送到 ESPv2 的 JWT 令牌中的 "iss" 字段。

作者的解决方案


在与 Google 云端点团队以及 ESPv2 的一些贡献者合作后,我们弄明白了这一点(并发现了一些要指出给将来想要这样做的人的一些事情) .

解决原始问题


事实上,正如 Wayne Zhang 所指出的,发行者可以是任何字符串值,只要它与 JWT 负载中的“iss”声明匹配即可。

例如

authentication:
providers:
- id: some-fancy-id
  issuer: fart # <-- Don't wrapping ANY these in double-quotes 
  jwks_uri: https://storage.googleapis.com/your-public-bucket/jwk-public-key.json
  audiences: some-specific-name

然后在你的(解码的)JWT

// Header
{
  "alg": "RS256",
  "kid": "custom-id-system-you-specify",
  "typ": "JWT"
}
// Payload
{
  "aud": [
      "some-specific-name"
  ],
  "exp": 1590139950, <-- MUST be INTEGER value
  "iat": 1590136350, <-- ^^
  "iss": "fart",
  "sub": "Here is some sulphur dioxide"
}

Error/Bug #1 - “iat”和“exp”应该是整数而不是字符串


正如您已经从上面解码的 JWT 中看到的那样,“exp”和“iat”声明必须是整数值(这可以在 RFC7519 4.1.4 和 4.1.6 节中清楚地看到).

这似乎是一个简单的错误,但正如 ESPv2 贡献者和我发现的那样,错误消息在帮助开发人员找出问题所在方面并不是特别有用。

例如,如果您将“iat”和“exp”声明写成字符串而不是整数,ESPv2 容器会通知开发者他的 JWT 不是正确的 Base64URL 格式,就是无效 JSON。在不知情的情况下,您可能会认为您错误地使用了该库。

为了将来解决这个问题,对错误消息进行了一些更改,您可以看到提出的问题及其结论 here

错误 #2 - 密钥错误,JSON 格式


在宣布这场消耗战的胜利之前,我 运行 又犯了一个错误,这个错误和之前的一样模糊。

当尝试调用需要身份验证的方法时,我遇到了以下问题

grpc._channel._InactiveRpcError: <_InactiveRpcError of RPC that terminated with:
    status = StatusCode.UNAUTHENTICATED
    details = "Jwks remote fetch is failed"
    debug_error_string = "{"created":"@1590054504.221608572","description":"Error received from peer ipv4:216.239.36.53:443","file":"src/core/lib/surface/call.cc","file_line":1056,"grpc_message":"Jwks remote fetch is failed","grpc_status":16}"
>

您可能认为这意味着 ESPv2 无法检索您的密钥。 原因是三个相关问题。

  1. ESPv2 只支持 X509 和 RSA 密钥对,所以不要重蹈我的覆辙,使用 EC 生成的密钥对。

  2. jwcrypto 默认情况下不会将“alg”和“kid”声明添加到您的密钥文件中,请确保添加了这些声明,否则 jwcrypto 将不知道在签署任何 JWT 时使用什么算法已生成。

  3. 最后的错误是JSON文件的格式。当您调用导出密钥的方法时,您会得到以下信息:

    {
      "e":"XXXX",
      "kty":"RSA",
      "n":"crazyRandomNumbersAndLetters",
      "alg": "RS256",                       <-- NOT ADDED BY DEFAULT
      "kid": "custom-id-system-you-specify" <-- ^^
    }
    

在 JSON 文件中简单地为此提供 URL 是不正确的。正确格式如下:

    {
      "keys": [
        {
          "e":"XXXX",
          "kty":"RSA",
          "n":"crazyRandomNumbersAndLetters",
          "alg": "RS256",                       <-- NOT ADDED BY DEFAULT
          "kid": "custom-id-system-you-specify" <-- ^^
        }
      ]
    }

如果你做到了这一切,应该会一帆风顺。

我很抱歉有点跑题了,但我希望其他人不必像我一样经历那么多困难才能实现这一目标:)

我非常感谢 ESPv2 的开发人员,感谢他们的快速回复和对问题的洞察力。干得好!

祝编码顺利!

  • 卑鄙小B.