omuronの備忘録

個人的な備忘録

Lambda オーソライザーで Auth0 のトークンを検証する

Developers.IO の Auth0 + API Gateway でM2M認証・認可をやってみた を参考にしつつ、M2M ではなく SPA との認証・認可を試してみました。

Lambda を SAM で作成する

テンプレート生成

全部 1で選択してテンプレート生成。

$ sam init --runtime nodejs10.x --name auth0-sam-sample

デプロイ

あらかじめ、SAM 用の S3 バケットは作っておく。

$ cd auth0-sam-sample
$ sam build
$ sam package --s3-bucket <S3バケット> --output-template-file packaged.yaml
$ sam deploy --template-file packaged.yaml --stack-name <適当なスタック名> --capabilities CAPABILITY_IAM

デプロイしたら、API Gatewayステージ に表示されている URL の呼び出し ドメインをメモしておく。

テンプレート編集

template.yaml を編集する。 生成されたテンプレートと ブログ の差分を確認。 以下の4箇所を変更。

パラメーターの追加

外部引数で渡したいパラメーターを追加する。

Parameters:
  JwksUri:
    Type: String
  Audience:
    Type: String
  TokenIssuer:
    Type: Strin

ServerlessAPI追加

API Gateway に Lambdaオーソライザーの設定を追加。

  ServerlessAPI:
    Type: AWS::Serverless::Api
    Properties:
      StageName: Dev
      Auth:
        DefaultAuthorizer: Auth0Authorizer
        Authorizers:
          Auth0Authorizer:
            FunctionPayloadType: TOKEN
            FunctionArn: !GetAtt Auth0AuthorizerFunction.Arn
            Identity:
              Header: Authorization
              ValidationExpression: ^Bearer [-0-9a-zA-Z\._]*$
              ReauthorizeEvery: 0

Auth0AuthorizerFunction追加

オーソライザーとなる API を追加。これが、Auth0 と通信してトークン検証してくれる。

  Auth0AuthorizerFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: hello-world/
      Handler: auth.lambdaHandler
      Runtime: nodejs10.x
      Environment:
        Variables:
          JWKS_URI: !Ref JwksUri
          AUDIENCE: !Ref Audience
          TOKEN_ISSUER: !Ref TokenIssuer

トークン検証 API 設定追加

トークンの検証をおこなわないと呼び出せない API に、以下を追加する。

            RestApiId: !Ref ServerlessAPI

Output コメントアウト

とりあえず、Output は今は不要なのでコメントアウト

オーソライザー実装

npm install して auth.js 編集する。ソースは GitHub を参照。 公式を参考にするなら ここ

$ cd hello-world/
$ npm i jwks-rsa jsonwebtoken util --save
$ vi auth.js

再デプロイ

クラメソさんブログだと、パラメーターに渡す情報をみつけれませんでした。 公式の GitHub を見ると書いてありました。

TOKEN_ISSUER: The issuer of the token. If you're using Auth0 as the token issuer, this would be: https://your-tenant.auth0.com/ JWKS_URI: This is the URL of the associated JWKS endpoint. If you are using Auth0 as the token issuer, this would be: https://your-tenant.auth0.com/.well-known/jwks.json AUDIENCE: This is the required audience of the token. If you are using Auth0 as the Authorization Server, the audience value is the same thing as your API Identifier for the specific API in your APIs section.

$ cd ..
$ sam build
$ sam package --s3-bucket <S3バケット> --output-template-file packaged.yaml
$ sam deploy --template-file packaged.yaml --stack-name <適当なスタック名> --capabilities CAPABILITY_IAM \
  --parameter-overrides \
  JwksUri=https://<Auth0のドメイン>.auth0.com/.well-known/jwks.json \
  Audience=<メモっているAPI Gatewayのドメイン> \
  TokenIssuer=https://<Auth0のドメイン>.auth0.com/

Auth0 の設定

APIs の追加

Auth0 のダッシュボードから、 APIs - CREATE API で新しい API を作成する。 Identifier に、メモっている API Gatewayドメインを設定する。

SPA の改修

SPA で、トークンを生成している箇所に audience 設定を追加する。 ここもメモっている API Gatewayドメインを設定

  auth0 = await createAuth0Client({
    domain: config.domain,
    client_id: config.clientId,
    audience: "<メモっているAPI Gatewayのドメイン>"
  });

テスト

Lambda の テスト を利用してテスト。 SPA でログインして、デバッガーで token のレスポンスを取得する。レスポンス内にある acccess_token の値をコピーして、テストを作成。

{
  "type": "TOKEN",
  "authorizationToken": "Bearer <access_tokenをコピー>",
  "methodArn": "<hello-world API の ARN>"
}

Lambda の呼出結果が Effect": "Allow", となっていれば成功!

所感

M2M だけじゃなくて、ちゃんと SPA での認証も動くようになりました。フロント側をどうしたらいいかがなかなかわからなかったんだけど、やっぱりこのあたりは JavaScript はじめフロント苦手なところに起因してます。Auth0 側で APIs 作らなくても動きそうなのに、この設定をしないと SPA のサンプルで呼び出しているログインポップアップがちゃんと動かなかった。本当に API 設定が必要かどうかは不明です。