はじめに
Reactで作成したWebアプリケーションのユーザー認証部分をCognito + Amplifyフレームワークで構築してみました。
本記事では、それぞれのサービスについて、Amplifyの設定方法についてまとめています。
完成画面
今回は、ユーザー名、パスワードとワンタイムパスワードの2段階認証を行います。そして、サインインをしたユーザーを識別し、トップページには「{ユーザー名}さんこんにちは!」という文字が出るようにします。
方法検討
要件
認証方法を考えるにあたり、条件は以下の通りです。
- 静的コンテンツをS3に置いている
- アプリケーション部分はLambdaで実装している
- アプリケーション内でユーザーを管理しており、ユーザーに登録されている人だけ使えるようにしたい
- 今後ユーザーのマイページも作りたいので、認証と合わせてユーザーを識別したい
- パスワードはシステム管理者が管理しないようにするのがベター
- ソーシャルアカウントは使わない
- MFA(多要素認証)を使いたい
結論
この条件に沿って認証部分を考えた結果、Cognitoを利用することにしました。また、Cognitoと既存のWebアプリケーションを簡単に連携できるAWSのAmplifyフレームワークというものがあったので、こちらも使ってみることにしました。
使用するAWSサービスについて
Cognitoってなに?
公式サイトによると、次のように説明されています。
Amazon Cognito を使用すれば、ウェブアプリケーションおよびモバイルアプリに素早く簡単にユーザーのサインアップ/サインインおよびアクセスコントロールの機能を追加できます。Amazon Cognito は、数百万人のユーザーにスケールし、Facebook、Google、Amazon などのソーシャル ID プロバイダー、および SAML 2.0 によるエンタープライズ ID プロバイダーを使用したサインインをサポートします。
Cognitoでできること
今回のCognitoでやることは下記の通りです。
- Webアプリケーションのユーザーの管理(パスワードなど含む)
- ユーザーがサインインするときの認証
料金
料金は使った分だけです。最低料金もかかりません。
今回のように、ユーザープールの認証情報を使ってCognitoユーザープールに直接サインインする場合は50,000MAUの無料枠があります。50,000MAUを超えるアクティブユーザーがいる場合は、0.0055USD/MAUかかります。(人数幅によって多少減額あり。詳細はこちらをご覧ください。)
※1MAU=サインアップ、サインイン、トークンの更新またはパスワードの変更など、当該ユーザーに関わる ID 操作があったユーザー(アクティブユーザー)
参考:https://aws.amazon.com/jp/cognito/pricing/
Amplifyってなに?
公式サイトによると、次のように説明されています。
AWS Amplify は、モバイルとウェブのフロントエンドデベロッパーが、安全でスケーラブルなフルスタックアプリケーションを構築しデプロイできるようにする、AWS によるエンドツーエンドのソリューションです。Amplify を使用すれば、アプリケーションのバックエンドを数分で設定し、わずか数行のコードでそれをアプリケーションに接続できます。そして、3 ステップで静的なウェブアプリケーションをデプロイできます。
その中で、分析や認証などの機能を持つAWSリソースを構成するのに役立つ対話型のCLIを提供していたり、認証処理などの実装や画面の作成に使うライブラリ、UIコンポーネントを提供しているAmplifyフレームワークというものを使います。
Amplifyフレームワークでできること
今回Amplifyフレームワークでやることは下記の通りです。
- Amplify CLIを使ってのCognitoユーザープールの構築
- 既存のソースコードとCognitoの連携
- サインイン画面作成
- ユーザー情報の取得、サインアウト機能の実装
今回はフロントエンドフレームワークとしてReactを使いましたが、他にもReact Native、Angular、Vue、IonicやiOS/Android IDEでも使うことができます。
料金
Amplifyフレームワーク自体には料金はかかりません。
Amplify フレームワーク (ライブラリ、CLI、UIコンポーネント) を使用する場合は、基盤として使用する AWS のサービスに対してのみお支払いいただきます。Amplify フレームワークの使用には、追加料金は発生しません。
参考:https://aws.amazon.com/jp/amplify/pricing/?nc=sn&loc=3
手順
下記の流れで進めていきます。
本記事ではこちらの手順についてまとめています。
- Reactの開発環境の構築
- Amplifyの設定
- Amplify用のIAMユーザーの作成
- Amplifyの初期設定
下記の5番、6番については別記事 構築完成編 へ。
5. Cognitoユーザープールの作成
6. コード実装
やってみる
1. Reactの開発環境の構築
React環境を簡単に構築する環境構築ツールはcreate-react-app
、パッケージマネージャーはyarn
を使いました。
バージョン
- node 14.15.0
- yarn 1.22.10
- create-react-app 4.0.0
2. Amplifyの設定
AmplifyをCLIで操作するために、Amplify CLIをインストールします。
$ yarn global add @aws-amplify/cli
そして、プロジェクトには、Amplifyのパッケージを追加します。
$ yarn add aws-amplify
$ yarn add aws-amplify-react
$ yarn add @aws-amplify/ui-react
3. Amplify用のIAMユーザーの作成
AWSでAmplifyが使うIAMユーザーの作成し、名前付きプロファイルにIAMユーザーを設定します。
$ amplify configure
上記のコマンドを実行すると、AWSのコンソールが自動で開くのでコンソールでIAMユーザーを作成します。その後、コマンドラインで対話形式で作成したIAMユーザーの認証情報をAWS CLIのcredentialsファイルに保存します。今回、プロファイル名はamplify-cognito
で保存しました。
詳しくは、こちらの記事のAWSアカウントの紐付けを参考にしました。
AWS Amplify CLIの使い方〜インストールから初期セットアップまで〜
ただ、Amplify用のIAMユーザーにAdministratorAccessのポリシーをアタッチするのは嫌だったので、こちらを参考に自分でポリシーを作成しました。不要そうなサービスへの権限を削除し、これでは権限が足りずエラーが出てしまったので、"cognito-idp:UntagResource"
を追加しています。
※↓クリックするとIAMポリシーが見れます。
IAMポリシー
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"amplify:CreateApp",
"amplify:CreateBackendEnvironment",
"amplify:CreateBranch",
"amplify:DeleteApp",
"amplify:DeleteBackendEnvironment",
"amplify:DeleteBranch",
"amplify:GetApp",
"amplify:GetBackendEnvironment",
"amplify:ListApps",
"amplify:ListBackendEnvironments",
"amplify:ListBranches",
"amplify:ListDomainAssociations",
"amplify:UpdateApp",
"cloudformation:CreateChangeSet",
"cloudformation:CreateStack",
"cloudformation:CreateStackSet",
"cloudformation:DeleteStack",
"cloudformation:DeleteStackSet",
"cloudformation:DescribeChangeSet",
"cloudformation:DescribeStackEvents",
"cloudformation:DescribeStackResource",
"cloudformation:DescribeStackResources",
"cloudformation:DescribeStackSet",
"cloudformation:DescribeStackSetOperation",
"cloudformation:DescribeStacks",
"cloudformation:ExecuteChangeSet",
"cloudformation:GetTemplate",
"cloudformation:UpdateStack",
"cloudformation:UpdateStackSet",
"cognito-identity:CreateIdentityPool",
"cognito-identity:DeleteIdentityPool",
"cognito-identity:DescribeIdentity",
"cognito-identity:DescribeIdentityPool",
"cognito-identity:SetIdentityPoolRoles",
"cognito-identity:GetIdentityPoolRoles",
"cognito-identity:TagResource",
"cognito-identity:UpdateIdentityPool",
"cognito-idp:AdminAddUserToGroup",
"cognito-idp:AdminCreateUser",
"cognito-idp:CreateGroup",
"cognito-idp:CreateUserPool",
"cognito-idp:CreateUserPoolClient",
"cognito-idp:DeleteGroup",
"cognito-idp:DeleteUser",
"cognito-idp:DeleteUserPool",
"cognito-idp:DeleteUserPoolClient",
"cognito-idp:DescribeUserPool",
"cognito-idp:DescribeUserPoolClient",
"cognito-idp:ListTagsForResource",
"cognito-idp:ListUserPoolClients",
"cognito-idp:UpdateUserPool",
"cognito-idp:UpdateUserPoolClient",
"cognito-idp:UntagResource",
"iam:AttachRolePolicy",
"iam:CreatePolicy",
"iam:CreateRole",
"iam:DeletePolicy",
"iam:DeleteRole",
"iam:DeleteRolePolicy",
"iam:DetachRolePolicy",
"iam:GetPolicy",
"iam:GetRole",
"iam:GetRolePolicy",
"iam:GetUser",
"iam:ListPolicyVersions",
"iam:PassRole",
"iam:PutRolePolicy",
"iam:UpdateRole",
"lambda:AddLayerVersionPermission",
"lambda:AddPermission",
"lambda:CreateEventSourceMapping",
"lambda:CreateFunction",
"lambda:DeleteEventSourceMapping",
"lambda:DeleteFunction",
"lambda:DeleteLayerVersion",
"lambda:GetEventSourceMapping",
"lambda:GetFunction",
"lambda:GetFunctionConfiguration",
"lambda:GetLayerVersion",
"lambda:GetLayerVersionByArn",
"lambda:InvokeAsync",
"lambda:InvokeFunction",
"lambda:ListEventSourceMappings",
"lambda:ListLayerVersions",
"lambda:PublishLayerVersion",
"lambda:RemoveLayerVersionPermission",
"lambda:RemovePermission",
"lambda:UpdateFunctionCode",
"lambda:UpdateFunctionConfiguration",
"s3:CreateBucket",
"s3:DeleteBucket",
"s3:DeleteBucketPolicy",
"s3:DeleteBucketWebsite",
"s3:DeleteObject",
"s3:GetBucketLocation",
"s3:GetObject",
"s3:HeadBucket",
"s3:ListAllMyBuckets",
"s3:ListBucket",
"s3:PutBucketAcl",
"s3:PutBucketCORS",
"s3:PutBucketNotification",
"s3:PutBucketPolicy",
"s3:PutBucketWebsite",
"s3:PutObject",
"s3:PutObjectAcl"
],
"Resource": "*"
}
]
}
これより少なくすることはできるかもしれないですが、この権限があれば今回のCognitoとAmplifyでユーザー認証を構築するのは問題なくできました!
4. Amplifyの初期設定
Amplifyの設定を行うために下記のコマンドを実行します。
$ amplify init
聞かれた通りにプロジェクト名や使っているエディターなどを入力、選択していきます。プロジェクト名や環境名は、AWS上に作成されるリソースの名前になります。
? Enter a name for the project qiitatest
? Enter a name for the environment dev
? Choose your default editor: IntelliJ IDEA
? Choose the type of app that you're building javascript
Please tell us about your project
? What javascript framework are you using react
? Source Directory Path: src
? Distribution Directory Path: build
? Build Command: yarn build
? Start Command: yarn start
そして、使うプロファイルについて聞かれるのでy
と答え、先ほど3. Amplify用のIAMユーザーの作成で作成、保存したプロファイルamplify-cognito
を選択します。
? Do you want to use an AWS profile? Yes
? Please choose the profile you want to use amplify-cognito
この設定が完了すると、プロジェクト内にamplifyフォルダ
とsrc/aws-exports.js
が作成されます。
おわりに
Amplifyフレームワークの設定が完了しました!Amplify用のIAMユーザーの作成方法(ポリシーの内容は変わってきます)やAmplifyの初期設定についてはCognitoに限らず他のサービスでも共通です。
次の構築完成編では、Cognitoユーザープールの作成とソースコードも書いていきます!