Pubsub 使用错误的密钥签署 JWT 令牌以进行推送

Posted

技术标签:

【中文标题】Pubsub 使用错误的密钥签署 JWT 令牌以进行推送【英文标题】:Pubsub signs the JWT token for push with a wrong key 【发布时间】:2021-02-10 04:13:29 【问题描述】:

我正在为我的后端使用以下堆栈:

    云端点 带有 ESPv2 的 Cloud Run Gateway => 检查 API 密钥并验证 JWT Cloud Run gRPC 服务器实现 当兴趣发生变化时,我会在 pubsub 上发布消息

现在,附加到该 pubsub 主题,我有一个推送订阅,该订阅会触发具有服务帐户和指定受众的 Cloud Run 方法。

设置:

现在我需要配置 Cloud Run 网关以验证 pubsub 为指定服务帐户生成的 JWT。根据此处的文档,这是在api_config.yaml 中完成的:https://cloud.google.com/pubsub/docs/push#jwt_format

发行者是https://accounts.google.com,受众在我在pubsub订阅中指定的那个。

authentication:
  providers:
    - id: gcloud
      jwks_uri: https://www.googleapis.com/robot/v1/metadata/x509/875517523825-compute@developer.gserviceaccount.com
      issuer: https://accounts.google.com
      audiences: project.clounrun.admin
  rules:
    - selector: project.v2.Events.*
      requirements:
        - provider_id: gcloud

可以在此处找到此服务帐户的 jwks: https://www.googleapis.com/robot/v1/metadata/x509/SERVICE-ACCOUNT-ID

就我而言: https://www.googleapis.com/robot/v1/metadata/x509/875517523825-compute@developer.gserviceaccount.com

https://cloud.google.com/endpoints/docs/grpc/service-account-authentication#set_up_authentication_in_the_grpc_api_configuration

我已经为 ESPv2 激活了调试日志,这是我在尝试验证 JWT 时得到的结果:

13:07:37.027 request headers complete (end_stream=false):\n\':authority\', \'project-gateway-v2-dev-cuvfttrlpq-de.a.run.app\'\n\':path\', \'/v2/sessions:event\'\n\':method\', \'POST\'\n\'content-type\', \'application/json\'\n\'authorization\', \'Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6ImQwNWVmMjBjNDUxOTFlZmY2NGIyNWQzODBkNDZmZGU1NWFjMjI5ZDEiLCJ0eXAiOiJKV1QifQ.eyJhdWQiOiJ5aXRub3cuY2xvdW5ydW4uYWRtaW4iLCJhenAiOiIxMDk0NDIwMDAxNjU1ODQ3Nzc4MDciLCJlbWFpbCI6Ijg3NTUxNzUyMzgyNS1jb21wdXRlQGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImV4cCI6MTYwMzgwNzAwMSwiaWF0IjoxNjAzODAzNDAxLCJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJzdWIiOiIxMDk0NDIwMDAxNjU1ODQ3Nzc4MDcifQ.PwLvaBz-_dM3_5VjgzVlaueoRhacUE39FdFuVSfQI2w4V3OD79tIA6t_0cuvE1-kIpNrfDda5RSavVcs4SV4Y5P8AvW5jDtHdCELP3yb8HzVT9nCJlLac-v5ZKuv06syBN9F2Ve7VtZHHZOE2VS4B7uw0Q__1rIVzIllYWBYHkYGUBP2mZ3VhRw9VXARMr-EICanXfETe_MMfoKsX4202L_O4LffPdv16pA5hYtwzKi67gFYuubKI1XNkVQVatQieYQrhkz5jMyNyhVKy8ZY5a2UXagQL7erdsm-uPJo6ujoq0Yxtl8iKMdRv4XfrQSLyFZHCYdO6n2LHJle_FQzCQ\'\n\'content-length\', \'335\'\n\'accept\', \'application/json\'\n\'from\', \'noreply@google.com\'\n\'user-agent\', \'APIs-Google; (+https://developers.google.com/webmasters/APIs-Google.html)\'\n\'x-cloud-trace-context\', \'c3027b54c6aad09d85ce75f6dcaf07d5/8778433264575104852\'\n\'x-forwarded-for\', \'66.249.82.169\'\n\'x-forwarded-proto\', \'https\'\n\'forwarded\', \'for=\"66.249.82.169\";proto=https\'\n\'accept-encoding\', \'gzip,deflate,br\'
13:07:37.027 Called Filter : setDecoderFilterCallbacks
13:07:37.027 matched operation: project.v2.Events.OnSessionEvent
13:07:37.027 Called Filter : decodeHeaders
13:07:37.027 use filter state value project.v2.Events.OnSessionEvent to find verifier.
13:07:37.028 extract authorizationBearer
13:07:37.028 extract x-goog-iap-jwt-assertion
13:07:37.028 gcloud: JWT authentication starts (allow_failed=false), tokens size=1
13:07:37.028 gcloud: startVerify: tokens size 1
13:07:37.028 gcloud: Verifying JWT token of issuer https://accounts.google.com
13:07:37.028 gcloud: JWT token verification completed with: Jwks doesn\'t have key to match kid or alg from Jwt
13:07:37.028 Called Filter : check complete Jwks doesn\'t have key to match kid or alg from Jwt
13:07:37.028 Sending local reply with details jwt_authn_access_denied

如您所见,jwks 不包含 JWT 孩子。这是真的。

这个JWT的头是这样的:


  "alg": "RS256",
  "kid": "d05ef20c45191eff64b25d380d46fde55ac229d1",
  "typ": "JWT"

有效载荷是这样的:


  "aud": "project.clounrun.admin",
  "azp": "109442000165584777807",
  "email": "875517523825-compute@developer.gserviceaccount.com",
  "email_verified": true,
  "exp": 1603807001,
  "iat": 1603803401,
  "iss": "https://accounts.google.com",
  "sub": "109442000165584777807"

这表明 pubsub 确实使用了该服务帐户,但 jwks 响应中似乎缺少该特定孩子。


  "4366ae10d4a79728de14f6f89a628b4fe640140f": "-----BEGIN CERTIFICATE-----\nMIIC+jCCAeKgAwIBAgIIapShdpj8y6QwDQYJKoZIhvcNAQEFBQAwIDEeMBwGA1UE\nAxMVMTA5NDQyMDAwMTY1NTg0Nzc3ODA3MB4XDTIwMDQzMDIyNDE0N1oXDTMwMDQy\nODIyNDE0N1owIDEeMBwGA1UEAxMVMTA5NDQyMDAwMTY1NTg0Nzc3ODA3MIIBIjAN\nBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArvpvYFbpJiXk4cEOo2xXzIFjLZEq\nIe1753Oe00IXmq5u/Glf6H0TdShqSn/mHd283UOeDGyjcz/AZO3iKyGv+GndSfiq\ny9TbXfeinCUoVtLUU500P32Ciej/t8Hf4UZYl6XlBVSMZK5ZVCqdWHs9vfPH8k6w\nSJm456BwjL3xty5AjuBooTSHec92SGe2DYSpMJL9NHGELdSnNRoxEaXpEUBV93vr\nTKfbBKa/1WaumVvIn54rAIMkaFq7dJRFr98U2yfHFvUhMtqAwX7HkdvgM74sjfV0\nduVfVz3T/m/oG/7lCllpI4LhVHpxxuNhimFo5quXjShJLPNEjFbESndMaQIDAQAB\nozgwNjAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIHgDAWBgNVHSUBAf8EDDAK\nBggrBgEFBQcDAjANBgkqhkiG9w0BAQUFAAOCAQEAZqBZCbFswKBxa4S+fvC6qb5c\nF/29sxM4WijC4e+/Ti+e6tcRrf3LyOF0jIpHbHWcwjTiYXX+D+UUmMrgh0ZVLCOR\nTDj29JSIUEhzYsGmBzBBcPLfMO2zl6c0aMdUkO+3vXQoTHUNjcs8UoN6BlPo3oIG\n2BjOXhEmuuUA3BQVDsMIM5g4G5r28WaprV7GaTa4fsyCh9oRquTtqL34CZLxiLXv\ncqK+oRMFU4tsLKvZjcfTeKp3fbXDpo7R1R7/+SyxAJTQOe1uPeAc5qhlVK6Ky/Zy\nTv3SUzAifJ3BDz1eNKYTqQNWiXi3QnX6qwebHgHKcJ01qnbCqMqbv6HicpULdQ==\n-----END CERTIFICATE-----\n",
  "e0b3368c1646eb88d93b9d0b2d65e2d6fbae27b7": "-----BEGIN CERTIFICATE-----\nMIIDNDCCAhygAwIBAgIIQ2si/YIYDg0wDQYJKoZIhvcNAQEFBQAwPTE7MDkGA1UE\nAxMyODc1NTE3NTIzODI1LWNvbXB1dGUuZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3Vu\ndC5jb20wHhcNMjAwOTMwMTM1NjM5WhcNMjIxMDEzMjAxNTU3WjA9MTswOQYDVQQD\nEzI4NzU1MTc1MjM4MjUtY29tcHV0ZS5kZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50\nLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALejPchRlDY8EE5D\nvD1CuPyGsbCoXHDnJpaA4P23CLNUmooBydxxzfV611vTUTBCFjq5Pcg3fpGusoMt\nyF9TqQVq4bGZxrXv+yxVs24uFdHAB7mY9JUE8GKN5i7IMP3egDcns4LmNWsB0iKN\niK1gK5q7gZIISjo3igLrup1G6wM02qym2VS6raKn/12WY+pa/PiZrO79eAkYPyqr\n73AvLdcLsik9U7lNDfxiev3/IE+tP0B68Uo5Ff+Wai+RDnNmDX3Fy50hv8vfniRe\nB/b57Kn6SMtMz4IMD4BeNQpOXdZe780cubuwS1oPLcRLHCXTqEzsGVIMLoMxrxF9\nhRK743kCAwEAAaM4MDYwDAYDVR0TAQH/BAIwADAOBgNVHQ8BAf8EBAMCB4AwFgYD\nVR0lAQH/BAwwCgYIKwYBBQUHAwIwDQYJKoZIhvcNAQEFBQADggEBAKF+dNSK+GFN\ndKFBs5PZufLUMlyaIXYysDnZgCk9oWMBiBpa6WDg00SllAz5z9koVYFr3ySQq6mK\nddkJLUXVt+NkR6Jh4k4OYshBV4v6q/BOXEjpP6/+jNV9qD5vVuq+w1eReouCl8eO\ng/rfUAivAPpU1srXSmhs6Uw2E4jDf8ArJWLsPfHjoqWLJEICGBG0i1nlJBRpGNWj\nyBfN1cEp64pYynpnVY9kuIEKdBCue8QEXVhsKURHGcOfCWP9+vVerhlyDatL1tQW\n5RAjvzS8NGLe8QnMdy+63TwP4qKGkWSEPTxP0fpQpxuLbqKHHsSeA7WL6nS6zSwx\nRXHDLiUfU0A=\n-----END CERTIFICATE-----\n",
  "c0191d2d00f89eb1905886a04335a79a124885e1": "-----BEGIN CERTIFICATE-----\nMIIDNDCCAhygAwIBAgIIaTwbvrNhTkYwDQYJKoZIhvcNAQEFBQAwPTE7MDkGA1UE\nAxMyODc1NTE3NTIzODI1LWNvbXB1dGUuZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3Vu\ndC5jb20wHhcNMjAxMDI4MDA0NDEwWhcNMjAxMTEzMTI1OTEwWjA9MTswOQYDVQQD\nEzI4NzU1MTc1MjM4MjUtY29tcHV0ZS5kZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50\nLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKJZDpcJAHyot7z9\n0EAOOEC6+dwlkxduThH5FQXlaCUoHRAoCtTHrxeITSsZg55cXGXKzTTf1Nv+UE9E\nTY5nhU70nEK77B5FbxwzX9Q/OkOhP3NQnl0U0O6nedfCJvOtCMdopHnrRa+ZIWhG\nPoW2RKQTv7gr4bGFJnQshcYDtrahH6Xv/RfyyTnI9AUzCX6eVO3g7odLSdcv+qnV\niqsZLCqz2lflKky+Rti/1f8LGXySTs+r7bdvqCdpbIm6f79WqQ720hmx+4JaIuS3\nYmYztK5J6JwsDLqULyyMvZs9vVA6cK1+580Vb76pkF9MHqTZdZ2gPP1qoKCO0ezI\nK3lYfGECAwEAAaM4MDYwDAYDVR0TAQH/BAIwADAOBgNVHQ8BAf8EBAMCB4AwFgYD\nVR0lAQH/BAwwCgYIKwYBBQUHAwIwDQYJKoZIhvcNAQEFBQADggEBAHB+6GiylFKU\nq9nyzrvlTRe0tph7kT6D8WhlnxGDgnDOn9xAB360xh+KPczq7+8DJczSb5145No/\nefrCUpvgkraVe/eTsu8EAjDjk/XPOeV4117EU+PRVV5nitYiVGJ0Z+3V3kHCnqLT\ntTxQlKDRpJ02GjhQRkW03fhLEFr7eu79fiwfjfaFSoAAIrNxBi3mtrhcidu43zD1\n/VXAReH26S129UoYz7fPlsnULX/oUyZPidaKIZ2Fl5N2QTgXnd1PnU3HgesU4HWs\nYJeiq6Z1pFxTw9192VD3MgDSDVQAeHXs+wTQsUHftMcNl7nPWl9YfiPjzD4sNWL3\n8whVkhIN8r4=\n-----END CERTIFICATE-----\n"

我们有:

4366ae10d4a79728de14f6f89a628b4fe640140f e0b3368c1646eb88d93b9d0b2d65e2d6fbae27b7 c0191d2d00f89eb1905886a04335a79a124885e1

但是没有

d05ef20c45191eff64b25d380d46fde55ac229d1

如果 pubsub 使用不同的密钥,我在哪里可以找到 jwks?

更新: 我验证了我所有的服务帐户 JWKS 链接,但没有一个包含那个孩子。所以这很奇怪。

【问题讨论】:

【参考方案1】:

您正在使用 Google 签名密钥(Google 正在为您签名)。

这意味着您需要从 Google 发布的公钥中查找 KID。

你会在这里找到公共证书小子:https://www.googleapis.com/oauth2/v1/certs

对于一些附加的上下文,每个服务帐户都有一种“隐藏”密钥。Google 管理和控制此密钥。当您向 Google 请求身份令牌时,JWT 使用此特殊密钥进行签名。这就是您需要的原因在 Google 的公共证书列表而不是您的服务帐户的证书列表中查找它。

【讨论】:

以上是关于Pubsub 使用错误的密钥签署 JWT 令牌以进行推送的主要内容,如果未能解决你的问题,请参考以下文章

如果没有它可以解密,那么签署jwt有啥意义

我需要为每个用户单独管理 jwt 密钥吗?

使用 x509 证书签署 JWT 令牌时遇到问题

Azure KeyVault - 签署 JWT 令牌

签署令牌如何工作? (无效签名错误)

JWT令牌加密和http get中的传输