Google 云端点 - Auth0 - "id_token verification failed: Invalid token signature"

Google Cloud Endpoints - Auth0 - "id_token verification failed: Invalid token signature"

我正在尝试使用 Google Cloud Endpoints 设置 Auth0。

我遵循了

的指示

我想使用我已经从 Auth0 iOS SDK 创建的 Auth0 认证用户从我的 iOS 应用调用“http://10.50.10.31:8080/_ah/api/echo/v1/test/”。

let url = URL(string: "http://10.50.10.31:8080/_ah/api/echo/v1/test/")!
var request = URLRequest(url: url)
request.addValue("Bearer \(session.token.idToken)", forHTTPHeaderField: "Authorization")
let task = URLSession.shared.dataTask(with: request) { data, response, error in
   print(data)
   print(response)
}
task.resume()

Swift 代码工作正常。 session.idToken 来自 Auth0 iOS 框架。

文件app.yaml

runtime: python27
api_version: 1
threadsafe: true

env_variables:
  # The following values are to be replaced by information from the output of
  # 'gcloud service-management deploy swagger.json' command.
  ENDPOINTS_SERVICE_NAME: echo-api.endpoints.duskmotion-2016.cloud.goog
  ENDPOINTS_SERVICE_VERSION: 2017-02-16r0

builtins:
- appstats: on
- admin_redirect: on
- deferred: on
- remote_api: on

libraries:
- name: jinja2
  version: "2.6"
- name: markupsafe
  version: "0.15"
- name: pycrypto
  version: "2.6.1"
- name: enum
  version: "0.9.23"
- name: protorpc
  version: "1.0"
- name: pytz
  version: "2016.4"
- name: six
  version: "1.9.0"
- name: ssl
  version: "2.7.11"
- name: werkzeug
  version: "0.11.10"

inbound_services:
- warmup

handlers:
- url: /favicon.ico
  static_files: application/static/img/favicon.ico
  upload: application/static/img/favicon.ico

- url: /robots.txt
  static_files: application/static/robots.txt
  upload: application/static/robots.txt

- url: /gae_mini_profiler/static
  static_dir: lib/gae_mini_profiler/static

- url: /gae_mini_profiler/.*
  script: lib.gae_mini_profiler.main.application

- url: /static
  static_dir: application/static

- url: /admin/logout
  script: run.application.app
  secure: always
  login: required

- url: /admin/.*
  script: run.application.app
  secure: always
  login: admin
  auth_fail_action: redirect

- url: /_ah/warmup
  script: run.application.app
  secure: always

- url: /_ah/.*
  script: run.application.urls.api

- url: .*
  script: run.application.app
  secure: always

skip_files:
- ^(.*/)?#.*#$
- ^(.*/)?.*~$
- ^(.*/)?.*\.py[co]$
- ^(.*/)?.*/RCS/.*$
- ^(.*/)?.*\(dev\).tmpl
- ^(.*/)?\..*$
- ^(.*/)?setuptools/script \(dev\).tmpl$

文件main.py

import endpoints
from protorpc import message_types
from protorpc import messages
from protorpc import remote

auth0_issuer = endpoints.Issuer(
    issuer='https://duskmotion.auth0.com/',
    jwks_uri='https://duskmotion.auth0.com/.well-known/jwks.json')

class EchoRequest(messages.Message):
    content = messages.StringField(1)


class EchoResponse(messages.Message):
    """A proto Message that contains a simple string field."""
    content = messages.StringField(1)


ECHO_RESOURCE = endpoints.ResourceContainer(
    EchoRequest,
    n=messages.IntegerField(2, default=1))


@endpoints.api(name='echo', version='v1', issuers={"auth0-jwk" : auth0_issuer})
class EchoApi(remote.Service):
    @endpoints.method(
        # This method takes a ResourceContainer defined above.
        message_types.VoidMessage,
        # This method returns an Echo message.
        EchoResponse,
        path='test',
        http_method='GET',
        name='echo_test_get')
    def echo_test_get(self, request):

        # auth = request.headers.get('Authorization', None)
        import logging
        logging.info(request)

        user = endpoints.get_current_user()
        content = "Nothing"
        if user:
            content = "It is working"
        import logging
        logging.info(content)
        if not user:
            raise endpoints.UnauthorizedException
        return EchoResponse(content=content)

api = endpoints.api_server([EchoApi])

生成 API 文件后,我手动添加了 "Security" "x-security" 和 "securityDefinitions".

文件 echov1openapi.json 看起来像

{
  "basePath": "/_ah/api",
  "consumes": [
    "application/json"
  ],
  "definitions": {
    "ApplicationUrlsEchoResponse": {
      "properties": {
        "content": {
          "type": "string"
        }
      },
      "type": "object"
    }
  },
  "host": "echo-api.endpoints.duskmotion-2016.cloud.goog",
  "info": {
    "title": "echo",
    "version": "v1"
  },
  "paths": {
    "/echo/v1/test": {
      "get": {
        "operationId": "EchoApi_echoTestGet",
        "parameters": [],
        "responses": {
          "200": {
            "description": "A successful response",
            "schema": {
              "$ref": "#/definitions/ApplicationUrlsEchoResponse"
            }
          }
        },
        "security": [
          {
            "auth0_jwk": []
          }
        ]
      }
    }
  },
  "produces": [
    "application/json"
  ],
  "schemes": [
    "http"
  ],
  "x-security": [{
                "auth0_jwk": {
                  "audiences": [
                          "xxxxxxxxxxxxxxxxxx"
                      ]
               }
       }],
  "securityDefinitions": {
              "auth0_jwk": {
                  "authorizationUrl": "https://duskmotion.auth0.com/authorize",
                  "flow": "implicit",
                  "type": "oauth2",
                  "x-issuer": "https://duskmotion.auth0.com/",
                  "x-jwks_uri": "https://duskmotion.auth0.com/.well-known/jwks.json"
             }
       },
  "swagger": "2.0"
}

当我 运行 在本地 Google App Engine 开发服务器上时,我得到

DEBUG    2017-02-16 23:55:25,551 users_id_token.py:198] Checking for id_token.
DEBUG    2017-02-16 23:55:25,551 users_id_token.py:485] Loading certs from https://www.googleapis.com/service_accounts/v1/metadata/raw/federated-signon@system.gserviceaccount.com
DEBUG    2017-02-16 23:55:25,568 users_id_token.py:269] id_token verification failed: Invalid token signature
DEBUG    2017-02-16 23:55:25,569 users_id_token.py:209] Checking for oauth token.
DEBUG    2017-02-16 23:55:25,569 users_id_token.py:340] Fetching token info from https://www.googleapis.com/oauth2/v1/tokeninfo
ERROR    2017-02-16 23:55:25,840 users_id_token.py:349] Token info endpoint returned status 400: Invalid Value

调试线2和5来自我自己。

  1. 为什么调用 *.googleapis.com 端点而不是我的 *.auth0.com?
  2. 我在 .py 文件中的设置中缺少什么才能使其正常工作?

这是开发服务器上 Endpoints Frameworks 的一个已知问题,已在项目问题跟踪器中报告:3rd-party auth does not work with dev-server #55

另请参阅相关 Google Groups thread 以了解正在进行的讨论。