はじめに
cognitoを使ってユーザー管理をしたい!と思ったのでreactと組み合わせて実装してみます。
Cognitoユーザープールを作成する
Cognitoユーザープールを作成します。
参考:
ユーザープール作成 ステップ1
サインインオプションを指定します。
今回はEメールアドレスとパスワードで認証したいので、
ここではEメールを指定しておきます。
次へをクリックし、進みます。
ユーザープール作成 ステップ2
セキュリティ要件を設定します。
パスワードポリシーはデフォルトのままにします。
テストなので、MFAはなしにしておきます。
次へをクリックし、進みます。
ユーザープール作成 ステップ3
サインアップ処理の挙動を設定します。
フロントエンドから認可なしでサインアップ関数を実行するため、自己登録を有効化しておきます。
サインアップ時に検証メッセージを自動送信する設定を有効化しておきます。
無効にした場合、lambda、SESなどで自前実装できます。
その他の設定はデフォルトのままにしておきます。
次へをクリックし、進みます。
ユーザープール作成 ステップ4
ステップ3で有効化した検証メッセージの送信方法を設定します。
テストなので、簡単なSESを使用しない設定にします。
その他の設定はデフォルトのままにしておきます。
次へをクリックし、進みます。
ユーザープール作成 ステップ5
ユーザープールの設定を行います。
名前とホストされた認証ページを用意するかを選択します。
認証ページはreactで作成するので、チェックを外します。
今回のreactアプリ用のアプリケーションクライアントを設定します。
スイッチロールのようなイメージで、アプリケーションクライアントを複数用意することで、ユーザープール内のユーザーに対し、複数の認証フローやOpenID Connect のスコープを指定することができます。
クライアント名を指定します。
テストなのでクライアントシークレットは不要としておきます。
※参考
認証フローはデフォルトのままとしておきます。
次へをクリックし、進みます。
ユーザープール作成 ステップ6
問題なければ、ユーザープールを作成します。
ユーザープールIDとアプリケーションクライアントIDを取得する
アプリで使用するので、ユーザープールIDとアプリケーションクライアントIDを取得します。
マネジメントコンソールから取得します。
アプリケーションクライアントのクライアントIDも同様に取得します。
Cognitoの初期設定はここまでで完了です。
必要なライブラリのインポート
reactプロジェクトの用意
npx create-react-app react-cognito --template typescript
必要なライブラリのインポート
aws amplifyライブラリが必要なのでインポートします。
※amplify appは作成せず、関数だけ利用します。
npm i aws-amplify
実装後の認証フローを整理する
アプリは以下のドキュメントのフローでユーザーを作成・確認します。
- ユーザーは、アプリで作成した [Create an account] (アカウントを作成) ボタンを選択します。E メールアドレスとパスワードを入力します。
- アプリケーションは SignUp API リクエストを送信し、ユーザープールに新しいユーザーを作成します。
- アプリケーションは、ユーザーに E メールの確認コードを求めます。ユーザーは、E メールメッセージで受け取ったコードを入力します。
- アプリは、ユーザーの確認コードを含む ConfirmSignUp API リクエストを送信します。
早速コードを準備してテストしてみます!!
reactコードを準備してテストする
index.tsxに以下のコードを追加し、Cognito ユーザープールへの接続設定を行います。
// 追加コードここから
import { Amplify } from 'aws-amplify';
Amplify.configure({
Auth: {
Cognito: {
userPoolId: process.env.REACT_APP_USER_POOL_ID!,
userPoolClientId: process.env.REACT_APP_USER_POOL_CLIENT_ID!,
}
}
})
// 追加コードここまで
// ここからデフォルトのindex.tsx
const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement
);
また、以下のコードをsrcに追加し、テスト用ページを表示します。
import React, { useState } from 'react';
import { signUp, confirmSignUp, signIn, getCurrentUser, signOut } from 'aws-amplify/auth';
const Test: React.FC = () => {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [confirmationCode, setConfirmationCode] = useState('');
const handleSignUp = async () => {
// signUp関数を使用する。
// アカウントはUnconfirmed状態作成され、別途有効化する必要がある。
const output = await signUp({
username: email,
password,
})
console.log(output)
};
const handleVerify = async () => {
// 入力されたコードを検証し、ユーザーの有効化を行う
const output = await confirmSignUp({
username: email,
confirmationCode,
})
console.log(output)
};
const handleLogin = async () => {
// 入力されたemail, passwordを使用し、ユーザーのログイン処理を行う
await signIn({
username: email,
password,
})
const output = await getCurrentUser()
console.log(output)
}
const handleLogout = async () => {
await signOut()
}
return (
<div className="App" style={{ maxWidth: "900px", margin: "auto", padding: "10px 50px" }}>
<h1>Cognito Test</h1>
<h2>SignUp</h2>
<div>
<label htmlFor="email">登録メールアドレス:</label>
<input
id="email"
type="text"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
</div>
<div>
<label htmlFor="password">パスワード:</label>
<input
id="password"
type="text"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
</div>
<div>
<button onClick={handleSignUp}>検証用コードをメールアドレスに送信する</button>
</div>
<h2>VerifyUser</h2>
<div>
<label htmlFor="confirmationCode">検証コード:</label>
<input
id="confirmationCode"
type="text"
value={confirmationCode}
onChange={(e) => setConfirmationCode(e.target.value)}
/>
</div>
<div>
<button onClick={handleVerify}>コードを検証する</button>
</div>
<h2>Login/Logout</h2>
<div>
<button onClick={handleLogin}>ログインする</button>
</div>
<div>
<button onClick={handleLogout}>ログアウトする</button>
</div>
</div>
);
};
export default Test;
コード解説
signUp関数
フロントエンドのクライアントに、ユーザープールへの登録をさせるメソッドです。
signUp関数は上記したフローのステップ2を実行します。
- アプリケーションは SignUp API リクエストを送信し、ユーザープールに新しいユーザーを作成します。
※参考:詳しいドキュメント
confirmSignUp関数
confirmSignUp関数は上記したフローのステップ4を実行します。
今回は、クライアントにメールを確認してもらい、メール内にあるコードを受け取り、リクエストボディとしてます。
アプリは、ユーザーの確認コードを含む ConfirmSignUp API リクエストを送信します。
※参考:詳しいドキュメント
signIn関数
そのままの関数です。
※参考:詳しいドキュメント
getCurrentUser関数
signIn状態の場合、ユーザー情報を取得できます。
今回はテスト用に実行します。
※参考:詳しいドキュメント
テスト
作成したテストページで動作をテストします。
SignUpしてみる
メールアドレスとパスワードを入力し、SignUp関数を実行します。
関数の戻り値をコンソールに出力しています。
SignUpが完了していないことや、Confirmが必要なことがわかります。
Cognitoユーザープールに保存されているユーザー情報も確認してみます。
ユーザーが登録できてます!!!
ただ、確認ステータスが未確認なことがわかります。
メーラーを確認します。
検証コードが送信されていることがわかります。
Confirmしてみる
メールされた検証コードを使用し、SignUpを完了してみます。
入力した検証コードとemailでconfirmSignUp関数を実行します。
関数の戻り値をコンソールに出力しています。
SignUpが完了していそうです!!
Cognitoユーザープールに保存されているユーザー情報も確認してみます。
確認ステータスが確認になっていることがわかります!!!!
SignInしてみる
SignIn関数とgetCurrentUser関数を実行してみます。
エラーも出ず、ユーザー情報が取れました!!!
おわりに
CognitoとReactでユーザーのサインアップ~ログインまで動作確認しました。
Cognitoは複雑なイメージがあったのですが、簡単に疎通させることができました!!
メールに認証用リンクを乗せて、リンクを踏むだけで検証完了とするつくりを目指したいので、次はその仕組みを考えようかなと思います!