概要
- Cognito+Lambda@Edgeをつかって、CF配信に認証をつけたい
cognito-at-edge
を使用する- ものすごいハマってしまったので、将来の自分の為に残す
とても参考にさせていただきました
CF作成
配信はCF+S3で実施する。
S3作成
- S3バケットを作成(リージョンは東京で作った)
CF作成
- CF作成し、オリジンをS3指定する
- OriginAccessControlで制御する
- S3バケットにアクセス制御を記載する
{ "Version": "2008-10-17", "Id": "PolicyForCloudFrontPrivateContent", "Statement": [ { "Sid": "AllowCloudFrontServicePrincipal", "Effect": "Allow", "Principal": { "Service": "cloudfront.amazonaws.com" }, "Action": "s3:GetObject", "Resource": "arn:aws:s3:::gamecontainer-ot-content/*", "Condition": { "StringEquals": { "AWS:SourceArn": "arn:aws:cloudfront::012345678901:distribution/XXXXXXXXXX" } } } ] }
これでS3➡CFのアクセスができるようになる。
CFのディストリビューション名でアクセスをして確認してみると良い
Lambda@Edgeを作成
こちらのライブラリをそのまま使う
npm init npm install cognito-at-edge npm install dotenv
一応dotenvと組み合わせたけど、これは本質ではない。本来ならSecretManager使うとか、環境変数に入れるとかするべきかも。
require('dotenv').config(); const { Authenticator } = require('cognito-at-edge'); const authenticator = new Authenticator({ // Replace these parameter values with those of your own environment region: process.env.REGION, // user pool region userPoolId: process.env.USERPOOLID, // user pool ID userPoolAppId: process.env.USERPOOLAPPID, // user pool app client ID userPoolDomain: process.env.USERPOOLDOMAIN, // user pool domain }); exports.handler = async (request) => authenticator.handle(request);
Cognito作成
Cognitoは今回はメールアドレスとパスワードの認証で作成。
これは任意でOKのはず。最初はお試しでメールパスワードの認証がわかりやすい。
アプリクライアントの確認
デフォルトでアプリクライアントが作成されているはず
これのWebと名前書いたやつを使おう。(どっちでもいけるのか?)
アプリクライアントの設定
ここが本番。
以下を設定する
- コールバックURL
- 先ほど作ったCFのディストリビューションドメインを指定する(Route53で別ドメインとか設定するならそちらのドメインになるはず)
- つまり、Cognitoでログインした後にどこにアクセスさせることを許可するの?って設定
- Authorization code grand
- openid
このAuthorization code grand
とopenid
をチェック忘れていてひどくハマった・・・
L@Eの設定
Lambda@Edgeに記載する情報がそろったので、.envを記載する
.envを用意する
REGION=ap-northeast-1 USERPOOLID=ap-northeast-1_hogehoge USERPOOLAPPID=userpoolappid USERPOOLDOMAIN=domain.auth.ap-northeast-1.amazoncognito.com
Lambdaは必ずバージニア北部で作成する必要があります(Lambda@Edgeとして登録する際の条件)
以下、Lambdaをデプロイするときのコマンド例
zip -r function.zip .env index.js package-lock.json package.json node_modules aws lambda update-function-code --function-name function-name --zip-file fileb://function.zip --region us-east-1 --profile myprofile
- USERPOOLID
- Cognitoのユーザプールの名前。似たような名前が記載されているはず
- USERPOOLAPPID
- これがさっきのアプリクライアントID USERPOOLDOMAIN
- Cognitoの認証エンドポイントを独自にドメインを決められるので、その名前。
👆で設定できる。Cognitoのドメインのものを使う場合は早い者勝ちになる。
Lambda@Edgeの設定
- Lambda@EdgeはCFのビューワリクエストに張り付ける
- ちなみに、ビューワリクエストにLambda@Edgeを貼るということは、リクエストが呼ばれるたびにLambda@Edgeが動くことになる。お金の心配したくなる
- オリジンリクエストにはったLambda@Edgeは、レスポンスをCFがキャッシュしてくれるときには呼ばれない
- キャッシュをしっかり効かせてやると、静的ページであればほとんどLambda@Edge呼ばれないっていう感じになるはず
Lmabda@Edgeの設定
Lambdaの画面から、「バージョン」を選択し、「新しいバージョンを発行」を実施して、新バージョンを作る
「トリガを追加」からCF選ぶ
- ディストリビューションを選ぶ
- CloudFrontイベントは「ビューアーリクエスト」を選ぶ
Lambda@Edgeへのデプロイを確認
をチェックする(これチェックしないとデプロイできない)
確認
CFのデプロイはおそらく5分くらいで終わるので、デプロイ後にCFのディストリビューション名称でアクセスして確認する
Cognitoのログイン画面が出てきて、ログイン求められるはず。作ったユーザでログインできればOK