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 設定が必要かどうかは不明です。