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