API Gateway + Auth0 で API に認可機能を追加する

4 min read読了の目安(約3900字

サーバーレスな API に認可機能を追加して、利用者を制限できるようにする方法を説明します。
認証・認可にはAuth0を利用し、Serverless Framework で API Gateway のオーソライザーに Auth0 を設定します。
今回は認可周りの説明になるので、サーバーレスな API 自体の作成方法は、こちらの記事を参考にしてください。

前提

以下の前提で説明を進めます。

  • Serverless Framework インストール済み
    • バージョン 2.29.0、AWS のアカウント設定済み、Lambda で使用する言語は Python 3.8
  • Auth0 のアカウント作成済み
  • API Gateway のデプロイ済み

Auth0 の設定時に API Gateway の URL を入力するため、事前に API Gateway のデプロイは済ませておいてください。また、API Gateway は削除して再作成すると URL が変わるので、本番環境の場合はカスタムドメインの利用なども検討してください。

Auth0 側の設定

Auth0 の管理画面でApplications > APIs > CREATE APIから API を新規作成します。

Auth0 New API

  • Name:好きな API 名を入力(今回はSample APIとしました)
  • Identifier:API Gateway の URL を入力(あとで使います)
  • Signing Algorithm:RS256

API を新規作成すると、Applications > Applicationsに M2M(Machine to Machine)認証のテスト用アプリケーションが追加されているはずです。
今回の場合だと「Sample API (Test Application)」という名前で作成され、Settings に、Client ID や Client Secret が記載されています。

ここまでくれば、Auth0 のマニュアルを参考にアクセストークンを取得できるようになります。
以下を実行することで、アクセストークンが取得できます。

$ curl --request POST \
  --url 'https://YOUR_DOMAIN/oauth/token' \
  --header 'content-type: application/x-www-form-urlencoded' \
  --data grant_type=client_credentials \
  --data client_id=YOUR_CLIENT_ID \
  --data client_secret=YOUR_CLIENT_SECRET \
  --data audience=YOUR_API_IDENTIFIER

上記リクエストの各パラメータに設定する値を説明します。

  • YOUR_DOMAIN:テスト用アプリケーションの Domain
  • YOUR_CLIENT_ID:テスト用アプリケーションの Client ID
  • YOUR_CLIENT_SECRET:テスト用アプリケーションの Client Secret
  • YOUR_API_IDENTIFIER:API Gateway の URL(Auth0 の API 作成時に設定した Identifier)

リクエストを実行すると、以下のような JSON が返ってきます。

{ "access_token": "<token>", "expires_in": 86400, "token_type": "Bearer" }

アクセストークンの取得まで確認できれば、Auth0 側の設定は完了です。

API Gateway の設定

次に API Gateway の HTTP API で Auth0 を認可に使用できるように設定していきます。
Serverless Framework の serverless.yml の provider にオーソライザーの設定を追加します。

serverless.yml
provider:
  # 他の設定は省略
  httpApi:
    authorizers:
      auth0Authorizer:
        identitySource: $request.header.Authorization
        issuerUrl: https://[YOUR-TENANT-NAME].jp.auth0.com/
        audience: https://[YOUR-APIGATEWAY-ID].execute-api.ap-northeast-1.amazonaws.com/

追加した設定値の意味は以下の通りです。

  • identitySource
    • アクセストークンが設定される場所
    • $request.header.Authorization は Authorization ヘッダーにアクセストークンをセットするという意味
  • issuerUrl
    • Auth0 の URL
    • [YOUR-TENANT-NAME].jp.auth0.comがテスト用アプリケーションの Domain
    • 末尾にスラッシュ(/)を入れ忘れると動作しなくなるので注意(地味にハマったので…)
  • autience
    • Auth0 で設定した Identifier
    • 冒頭に設定した API Gateway の URL

これを Lambda のイベントに追加します。

serverless.yml
functions:
  hello:
    handler: handler.hello
    events:
      - httpApi:
          path: /hello
          method: get
          authorizer: # 追加分
            name: auth0Authorizer # 追加分

provider に追加したauth0Authorizerを、authorizer.name に追加するだけで API に認可機能を付与できます。

これをデプロイします。

$ sls deploy

認可の検証

実際に認可が動作するかを確認します。
まずは、Authorization ヘッダーなしで実行します。

$ curl -XGET 'https://[YOUR-APIGATEWAY-ID].execute-api.ap-northeast-1.amazonaws.com/hello'
{"message":"Unauthorized"}

レスポンスが Unauthorized となったので、認可が正しく動作していることが確認できます。
次に、Authorization ヘッダー付きでリクエストします。<access_token>には Auth0 から取得した access_token を入れてください。

$ curl -XGET -H 'Authorization: Bearer <access_token>' 'https://[YOUR-APIGATEWAY-ID].execute-api.ap-northeast-1.amazonaws.com/hello'
{"message": "Go Serverless v1.0! Your function executed successfully!", "input": null}

Authorization のトークンで認可が通り、正常にレスポンスが返ってきました。
Auth0 と組み合わせることで API Gateway の HTTP API に認可処理を割と簡単に追加できますので、必要に応じて試してみてください。

おまけ

今回使用したコードは以下の Github リポジトリにアップしているので、全体のコードを確認したい方はそちらを見てください(v4.0 のタグが今回のコードです)。

https://github.com/ombran/serverless-sample/tree/v4.0