2023.3.5
Next.js + CognitoでHosted UIを使わずに自前のUIからサインイン、サインアップ、AuthGuardなどの認証周りの挙動を実現するサンプルアプリを公開しました
概要
Cognitoを利用する際にHosted UIを使うと認証関連の機能と画面を簡単に提供できますが、プロダクトとして認証周りの画面も統一感のある自前の画面を提供したいことがあると思います。
その場合に、機能面では@aws-amplify/authライブラリを使い、画面としてはNext.js(React)で構成された画面に組み込みが必要となるため、実際に組み込んでみたときの気付きなどをまとめました。
また、ソースコードとしては サンプルリポジトリ を公開しました。
Cognitoユーザープールの作成
2023/03/05時点でのCognitoユーザープール作成画面を例として進めていきます。
サインインエクスペリエンス
セキュリティ要件
パスワードのポリシーはお好みで変更してください。
なお、概要にリンクを付けたサンプルリポジトリでは下記のパスワードポリシーに対するバリデーションをフロントエンドでつけています。
サインアップエクスペリエンス
メッセージ配信
アプリケーションを統合
ここでは「CognitoのホストされたUIを使用」のチェックが外れていることを確認します。
また「クライアントシークレットを生成しない」が選択されていることを確認します。
クライアントシークレットを生成するかどうかはあとから変更できない項目であり、クライアントシークレットが生成される設定になっていると今回利用する @aws-amplify/auth
が利用できなくなってしまうので必ず確認します。
@aws-amplify/authの機能の確認
細かい実装などは概要にもリンクをつけた サンプルリポジトリ から確認できるとして、ここでは機能の確認をしていきます。@aws-amplify/auth
が提供するメソッドを自前のUIから呼び出すことになります。
今回のサンプルリポジトリで使用したメソッドは以下のとおりです。
・currentAuthenticatedUser
・signUp
・confirmSignUp
・resendSignUp
・completeNewPassword
・signIn
・forgotPassword
・forgotPasswordSubmit
・signOut
getUserAttributesは非同期っぽいけどawaitできない
CognitoUserオブジェクトには、そのユーザーの attributes
を取得するためのメソッド getUserAttributes
が用意されています。
このメソッドはPromiseが返ってこないのでawaitできませんが、例えば以下のように実装すると getUserAttributes
以降の処理が先に実行されてしまいます。
TypeScript_____sample_____cognitoUser.getUserAttributes((_, attributes) => {
const { email, email_verified } = Object.fromEntries(
attributes!.map(({ Name, Value }) => [Name, Value])
);
userAttributes = { email, email_verified }
console.log(userAttributes);
})
console.log('This line should be called after getUserAttributes'); // <- この行が先に呼び出される
つまり getUserAttributes
したあとに、取得した attributes
を使用する処理は getUserAttributes
の完了を待ってから実行する必要があります。
サンプルリポジトリではその点についても考慮されています。
signUpとcompleteNewPassword
上記のメソッドについては基本的に必要なメソッドを必要なときに呼び出して、エラーハンドリングは適宜行うだけではありますが、この中でsignUp関連で少しだけポイントがあります。
上記メソッドから、signUp、confirmSignUpを通して作成されたアカウントについてはsingInしたときのレスポンスであるCognitoUserオブジェクトのプロパティとして attributes
が存在し、ユーザーのemail、email_verifiedなど属性値が参照できます。
ただ、AWSコンソール画面から作成されたユーザーについては、signInしたときのレスポンスに attributes
プロパティが存在せず challengeName
というプロパティが存在します。
このプロパティを参照すると NEW_PASSWORD_REQUIRED
というテキストがセットされており、このユーザーのステータスとして新しいパスワードを設定しなければならないことがわかります。
この確認にひとつ上の項目でとりあげた getUserAttributes
の結果を利用します。getUserAttributes
はCognitoUserオブジェクトに存在する attributes
プロパティの値が取得できます。まだこのプロパティの値を取得できないユーザーについては null
が返ってきますのでその場合には completeNewPassword
を使って新しいパスワードを設定してもらいます。
こうすることで次回からこのユーザーはCognitoUserオブジェクトから attributes
プロパティの値を取得できるようになります。
まとめ
今回の記事では @aws-amplify/auth
を使ってCognitoのHosted UIを使用せずに自前の画面から認証機能を提供する際の気にするポイントをまとめました。
Cognitoの認証機能を提供したい場合の参考になれば幸いです。