Настройка аутентификации Auth0 в Google App Engine Standard и фреймворках конечных точек облака с Python - PullRequest
0 голосов
/ 02 декабря 2018

Я использую Фреймворки облачных конечных точек с Python в стандартной среде Google Cloud App Engine для предоставления API.

Насколько я могу судить, я должен иметь возможность использовать Pythonдекораторы из оконечных систем Endpoints в сочетании с инструментом командной строки endpointscfg.py для автоматической настройки аутентификации на основе токенов с Auth0;командная строка endpointscfg.py автоматически создает файл openapi.json, который используется для настройки прокси-сервера конечных точек Google.

Вот пример моего декоратора для API, который возвращает вещи обратно:

# # [START echo_api]
@endpoints.api(
    name='echo',
    version=_VERSION,
    api_key_required=True,
    audiences={'auth0': ['https://echo.<my-project>.appspot.com/_ah/api/echo/v1/echo']},
    issuers={'auth0': endpoints.Issuer(
        'https://<my-project>.auth0.com',
        'https://<my-project>.auth0.com/.well-known/jwks.json')}
)
class EchoApi(remote.Service):
    ...

Когда я запускаю инструмент командной строки endpointscfg.py, в моем файле openapi.json что-то выглядит примерно так:

"paths": {
    "/echo/v1/echo": {
      "post": {
        "operationId": "EchoApi_echo",
        "parameters": [
          {
            "in": "body",
            "name": "body",
            "schema": {
              "$ref": "#/definitions/MainEchoRequest"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A successful response",
            "schema": {
              "$ref": "#/definitions/MainEchoResponse"
            }
          }
        },
        "security": [
          {
            "api_key": [],
            "auth0_jwt": []
          }
        ]
      }
    }

"securityDefinitions": {
    "api_key": {
      "in": "query",
      "name": "key",
      "type": "apiKey"
    },
    "auth0_jwt": {
      "authorizationUrl": "https://<my-project>.auth0.com/authorize",
      "flow": "implicit",
      "type": "oauth2",
      "x-google-issuer": "https://<my-project>.auth0.com",
      "x-google-jwks_uri": "https://<my-project>.auth0.com/.well-known/jwks.json",
      "x-google-audiences": "https://echo.<my-project>.appspot.com/_ah/api/echo/v1/echo"
    }
  }

Итак, проблема в том, что эта установканичего не делать и не проверять входящие токены для предотвращения доступа, если токен отсутствует или токен недействителен.

Я смог настроить ручную обработку токена носителя в функции эхо-кода API с помощьюбиблиотека python-jose (извините, если это не очень хорошо сделано, но я просто тестирую и приветствую комментарии):

authorization_header = self.request_state.headers.get('authorization')
    if authorization_header is not None:
        if authorization_header.startswith('Bearer '):
            access_token = authorization_header[7:]
            logging.info(access_token)
        else:
            logging.error("Authorization header did not start with 'Bearer '!")
            raise endpoints.UnauthorizedException(
                    "Authentication failed (improperly formatted authorization header).")
        else:
            logging.error("Authorization header did not start with 'Bearer '!")
            raise endpoints.UnauthorizedException("Authentication failed (bearer token not found).")

r = urlfetch.fetch(_JWKS_URL)
jwks_content = json.loads(r.content)
keys = jwks_content['keys']
public_key = jwk.construct(keys[0])
logging.info(public_key)

message, encoded_signature = str(access_token).rsplit('.', 1)
# decode the signature
decoded_signature = base64url_decode(encoded_signature.encode('utf-8'))
# verify the signature
if not public_key.verify(message.encode("utf8"), decoded_signature):
    logging.warning('Signature verification failed')
    raise endpoints.UnauthorizedException("Authentication failed (invalid signature).")
else:
    logging.info('Signature successfully verified')

claims = jwt.get_unverified_claims(access_token)
# additionally we can verify the token expiration
if time.time() > claims['exp']:
    logging.warning('Token is expired')
    raise endpoints.UnauthorizedException("Authentication failed (token expired).")
# and the Audience  (use claims['client_id'] if verifying an access token)
if claims['aud'] != _APP_CLIENT_ID:
    logging.warning('Token was not issued for this audience')
    raise endpoints.UnauthorizedException("Authentication failed (incorrect audience).")
# now we can use the claims
logging.info(claims)

Этот код работает, но я предположил, что весь смысл в настройке декоратора иКонфигурирование файла openapi.json состояло в том, чтобы разгрузить эти проверки в прокси, чтобы в мой код попали только действительные токены.

Что я делаю не так?

ОБНОВЛЕНИЕ: Возможно, мне нужно проверить endpoints.get_current_user () в моем коде для контроля доступа.Тем не менее, я только что заметил следующее в моих журналах:

Cannot decode and verify the auth token. The backend will not be able to retrieve user info (/base/data/home/apps/e~<my-project>/echo:alpha23.414400469228485401/lib/endpoints_management/control/wsgi.py:643)
Traceback (most recent call last):
  File "/base/data/home/apps/e~<my-project>/echo:alpha23.414400469228485401/lib/endpoints_management/control/wsgi.py", line 640, in __call__
    service_name)
  File "/base/data/home/apps/e~<my-project>/echo:alpha23.414400469228485401/lib/endpoints_management/auth/tokens.py", line 75, in authenticate
    error)
UnauthenticatedException: (u'Cannot decode the auth token', UnauthenticatedException(u'Cannot find the `jwks_uri` for issuer https://<my-project>.auth0.com/: either the issuer is unknown or the OpenID discovery failed',))

Тем не менее, я думаю, что все настроено нормально.Любая идея, почему 'jwks_uri' не может быть найден, несмотря на тот факт, что путь в файле openapi.json правильный?

1 Ответ

0 голосов
/ 04 декабря 2018

Я текущий сопровождающий этих фреймворков.Вам нужно проверить endpoints.get_current_user(), чтобы контролировать доступ, да.Я работаю над возможностью сделать это намного проще.

Что касается исключения UnauthenticatedException, вы можете его проигнорировать.Это происходит из «структуры управления», которая пытается проверить токены аутентификации, даже если она не участвует в защите oauth Frameworks (только защита API-ключа).

...