AWS Cognitoを使ってサーバレスアプリケーションに認証をつける
前回のアプリケーションに、AWS Cognitoを使って認証機能をつけた。
認証はメールアドレスとパスワードで行う。初めにサインアップを行う。メールアドレスとパスワードを入力して登録すると、アクティベーションコードが書かれたメールが届く。アクティベーションコードを入力すると登録が完了する。その後、ログインが可能となる。
また、Cognitoでログインしたユーザのみが、自分のデータにアクセスできるようにする。データアクセスはAPI Gatewayを使わずにS3のデータを直接取得している。
AWS Cognitoの設定
Cognitoの設定を行う。ユーザプールとフェデレーテッドアイデンティティの2つの設定を行う必要がある。
ユーザプールの設定
ユーザプールの設定は、画面に表示される内容を選択していくだけ。
フェデレーテッドアイデンティティの設定
ロールを作成することになるので、IAMの権限が必要となるので要注意。
AWS S3の設定
AWS S3のデータは、静的ホスティングをしていると、誰でも閲覧することができる。ユーザに自分だけのデータを見せるには権限設定を行う必要がある。
IAM ロール - Amazon Cognitoを参考にバケットポリシーの設定を行った。
認証周りを実装
aws/amazon-cognito-identity-jsを使って、認証周りを実装していく。README通りに実装して動いたので、簡単だった。
vuexを使っているので、/store/modules/auth.jsとして実装を行なった。全体のソースはeiKatou/Bango_frontendを参照してほしい。
認証を使用してS3のデータを取得
AWS.config.credentialsにJWT Tokenを設定して、S3のオブジェクトを取得する。そのため、JWT Tokenは保持しておかないといけない。
悩んだところ
S3のCORSの設定
以下のエラーとなった。
Failed to load resource: Preflight response is not successful
これは、S3のCORSの設定が出来ていないことが原因だった。
identityPoolIdの指定
以下のエラーとなった。
ValidationException: 1 validation error detected: Value ‘ap-northeast’ at ‘identityPoolId’ failed to satisfy constraint: Member must satisfy regular expression pattern: [\w-]+:[0-9a-f-]+
identityPoolIdが誤っている。ユーザプールのIDを指定するのではなく、フェデレーテッドアイデンティティのIDを指定しないといけない。「ap-northeast-1:XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX」形式の値である。
cognito-identity.amazonaws.com:subとは?
${cognito-identity.amazonaws.com:sub}をバケットポリシーに書いているけど、これは実際に何を指定するのか?これは、アイデンティティIDである。フェデレーテッドアイデンティティ > IDブラウザから確認できる。
Vue.jsで非同期処理後のUI更新
S3上の画像を取得した後、表示を更新する必要があるが、オブジェクトを書き換えても表示できなかった。
Vue.js で表示したデータの更新とイベント処理 | Cubixを参考に、$setを利用するようにした。
参考
以下のサイトを参考にして、無事に実装することができた。感謝!
- aws/amazon-cognito-identity-js
- Amazon Cognito UserPools を JavaScript から使ってみる - Qiita
- [ Serverless ] Cognito、S3、Lambdaで認証機能付きのWebサイトを作ってみました - Qiita
- [ Serverless ] Cognito、S3、Lambdaで認証機能付きのWebサイトを作ってみました<トラブルシューティング編> - Qiita
- 【ServerlessFramework】AWS LambdaとCognitoで作るセキュアなS3へのオブジェクト格納 - production.log