【Next.js】Next.jsからCognitoを使ってログイン画面を実装する①

前回はログイン画面を作成し、バリデーションチェックしてからフォームから入力情報を渡すところまでを実装しました。前回の記事はこちらを参照してください。

今回はいよいよ認証処理を実装していきます。
認証処理を実装するにあたり、Amazon Cognitoを利用します。今回はCognitoサービスの立ち上げとローカルで起動しているNext.jsからCognitoに認証要求のリクエストを送る処理を実装してきます。
※AWSアカウントをあらかじめ取得している前提に紹介しています。作成方法については以下をご覧ください。

目次

Amazon Cognitoとは

Amazon Cognitoは、AWS(Amazon Web Services)が提供する、ユーザー認証とユーザー管理のためのサービスです。ユーザーのサインアップ、サインイン、アクセス制御、ユーザーデータの管理を簡単に実装できるようにするためのサービスで、特にモバイルアプリケーションやウェブアプリケーションでユーザー認証や認可を扱う際に便利です。
ユーザー認証とユーザー管理で利用するユーザープール機能は、月ごとのアクティブユーザ(サインインなどが生じたユーザ)の数で、今(2024年9月)のところ、50,000ユーザまで無料、そこから 0.0055 USD / ユーザ、もっといくとスケールメリットで安くなるとなっています。50,000ユーザまで無料なのはありがたいですね。
私も個人で開発する際に利用していますが、課金対象にならず重宝しています。
ちなみにCognitoはログイン画面を実装しなくてもCognitoのUIを使用することができますが、今回はオリジナルのログイン画面を使用したいので前回作成しました。

詳しい記事はこちらに記載されています。

Cognitoユーザープール構築

AWSマネジメントコンソールからCognitoユーザープールを構築していきます。

画面上部の検索バーで「Cognito」と入力し、Cognitoをクリックします。

「ユーザープールを作成」をクリックします。

今回はEメールを選択します。

パスワードポリシーは記号を強制にしないことにしました。(ポリシーモードにカスタムを選択し、「少なくとも1つの特殊文字を含む」からチェックをはずします)
また、多要素認証は「MFAなし」を選択します。

特に変更せずにそのまま次へをクリックします。

EメールプロバイダーはCognitoを選択します。本当はSESのほうがいいと思いますが、開発で使用するだけであればCognitoで問題ないと思います。

ユーザープール名とアプリケーションクライアント名を入力します。

入力内容を確認して「ユーザープールを作成」をクリックします。

これでCognitoの準備は整いました。

動作確認用ユーザーを作成する

Cognitoを使用する際の検証やテストのために、ユーザを追加します。
ユーザー欄に「ユーザーを作成」ボタンがあるため、クリックします。

Eメールアドレスとパスワードを入力してユーザーを作成します。

ユーザーが作成されました!

ただ作成後の状態ですと確認ステータスが「パスワードを強制に変更」になっています。
この場合ログイン後のパスワード変更を行う必要があります。今回はログイン画面を作成しますが、パスワード変更画面は作成しないため、動作確認のためにステータスを変更します。

ステータスを変更するにはAWSCLIを使用します。
AWSCLIのインストール方法はこちらを参考にしてください。

下記コマンドでセッション情報を取得します。

aws cognito-idp admin-initiate-auth \
--user-pool-id ap-northeast-1_xxxxxxxxx \
--client-id xxxxxxxxxxxxxxxxxxxxx \
--auth-flow ADMIN_NO_SRP_AUTH \
--auth-parameters \
USERNAME=username,PASSWORD=password

ここで実行に失敗してしまいました。
An error occurred (InvalidParameterException) when calling the AdminInitiateAuth operation: Auth flow not enabled for this client

エラー内容を確認したところ、アプリクライアントの認証フローの設定に「ALLOW_ADMIN_USER_PASSWORD_AUTH」が設定されていないことが原因でした。またログインするためには「ALLOW_USER_SRP_AUTH」も必要だったようで、以下のように設定します。

もう一度下記コマンドでセッション情報を取得します。

aws cognito-idp admin-initiate-auth \
--user-pool-id ap-northeast-1_xxxxxxxxx \
--client-id xxxxxxxxxxxxxxxxxxxxx \
--auth-flow ADMIN_NO_SRP_AUTH \
--auth-parameters \
USERNAME=username,PASSWORD=password

成功すると下記レスポンスが返却されます。

{
    "ChallengeName": "NEW_PASSWORD_REQUIRED",
    "Session": "AYABeIDL_AbY-x4BSnAdHLWHjh8AHQABAAdTZXJ2aWNlABBDb2duaXRvVXNlclBvb2xzAAEAB2F3cy1rbXMAUGFybjphd3M6a21zOmFwLW5vcnRoZWFzdC0xOjM0NjM3NzU0NDkyNzprZXkvZDNhY2NlYmQtNTdhOC00NWE0LTk1ZmEtYzc2YzY5ZDIwYTRkALgBAgEAeBE2TfZ_8ma_gHZ_GQQsBbrCXyeeUzL6X63Mn4L5d8v0AeOW_NKLxcvn18p4P-n6DeoAAAB-MHwGCSqGSIb3DQEHBqBvMG0CAQAwaAYJKoZIhvcNAQcBMB4GCWCGSAFlAwQBLjARBAwU6Z4aUU2es-hICEkCARCAO5G4s76UFPElZgCMX9oDM0KmmH5G8qYnqFnZyg-6vK7Q00mqDdoAbBFNQnJCGPqLjDQlDSlGe_72ZJwOAgAAAAAMAAAQAAAAAAAAAAAAAAAAAJsUu-EJbEbfHGrBQlshOVf_____AAAAAQAAAAAAAAAAAAAAAQAAANX4ljbqwCiFlOU6LrzbdGkNEcAGDjNVAbBMHUTgisLZ65hpbajcIGAfOHAG8NRhqRet41J7HT-dQ4EvTuzq_NJRfU9V2IKcY2aGGRHrqkL2Ys0KWN2prx8duiMf5siz5Gbng-ik5fXdYb6hMfvaBE1JxpVW896qrvZraphXToKpv9hXzQbJGXOD2eDmneX1GAXIZzC48VoC2GXQvCKWhzSH1xbtItSXDi5Nt_jTkUcC1goihOBhKRWK5JNxBvmbTz_q0Ku08sWM3ceD18bZvZuUjZbZeoo9oa6Xf9CY-l32wHRIh9MW",
    "ChallengeParameters": {
        "USER_ID_FOR_SRP": "xxxxxxxx",
        "requiredAttributes": "[]",
        "userAttributes": "{\"email\":\"example@gmail.com\"}"
    }
}

返却されたセッション情報を利用してパスワードを変更します。

aws cognito-idp admin-respond-to-auth-challenge \
--user-pool-id ap-northeast-1_xxxxxxxxx \
--client-id xxxxxxxxxxxxxxxxxxxxx \
--challenge-name NEW_PASSWORD_REQUIRED \
--challenge-responses NEW_PASSWORD=Pass1111,USERNAME=xxxxxxxx \
--session "AYABeIDL_AbY-x4BSnAdHLWHjh8AHQABAAdTZXJ2aWNlABBDb2duaXRvVXNlclBvb2xzAAEAB2F3cy1rbXMAUGFybjphd3M6a21zOmFwLW5vcnRoZWFzdC0xOjM0NjM3NzU0NDkyNzprZXkvZDNhY2NlYmQtNTdhOC00NWE0LTk1ZmEtYzc2YzY5ZDIwYTRkALgBAgEAeBE2TfZ_8ma_gHZ_GQQsBbrCXyeeUzL6X63Mn4L5d8v0AeOW_NKLxcvn18p4P-n6DeoAAAB-MHwGCSqGSIb3DQEHBqBvMG0CAQAwaAYJKoZIhvcNAQcBMB4GCWCGSAFlAwQBLjARBAwU6Z4aUU2es-hICEkCARCAO5G4s76UFPElZgCMX9oDM0KmmH5G8qYnqFnZyg-6vK7Q00mqDdoAbBFNQnJCGPqLjDQlDSlGe_72ZJwOAgAAAAAMAAAQAAAAAAAAAAAAAAAAAJsUu-EJbEbfHGrBQlshOVf_____AAAAAQAAAAAAAAAAAAAAAQAAANX4ljbqwCiFlOU6LrzbdGkNEcAGDjNVAbBMHUTgisLZ65hpbajcIGAfOHAG8NRhqRet41J7HT-dQ4EvTuzq_NJRfU9V2IKcY2aGGRHrqkL2Ys0KWN2prx8duiMf5siz5Gbng-ik5fXdYb6hMfvaBE1JxpVW896qrvZraphXToKpv9hXzQbJGXOD2eDmneX1GAXIZzC48VoC2GXQvCKWhzSH1xbtItSXDi5Nt_jTkUcC1goihOBhKRWK5JNxBvmbTz_q0Ku08sWM3ceD18bZvZuUjZbZeoo9oa6Xf9CY-l32wHRIh9MW"

成功すると下記レスポンスが返却されます。

{
    "ChallengeParameters": {},
    "AuthenticationResult": {
        "AccessToken": "eyJraWQiOiJMRStFTWw1QVwvNnhNcTBmTVRzbCtuWGczamg0RkJ2K3dlXC9tbytjYzZMOHM9IiwiYWxnIjoiUlMyNTYifQ.eyJzdWIiOiJmNzU0N2E2OC01MGIxLTcwYWUtNzI3NC04YTQ5ZTM2NWUwMTgiLCJpc3MiOiJodHRwczpcL1wvY29nbml0by1pZHAuYXAtbm9ydGhlYXN0LTEuYW1hem9uYXdzLmNvbVwvYXAtbm9ydGhlYXN0LTFfY3BKUUtFOEpXIiwiY2xpZW50X2lkIjoiNnZ1cXMydXB1a3VndnJuYjU1YTF1Y2NqY2MiLCJvcmlnaW5fanRpIjoiYmFmOGNhYzYtMDY4YS00ZmU3LTllODYtNWNkNmJmMWVhN2U1IiwiZXZlbnRfaWQiOiI4Y2ExYzc3Yi1jNzhiLTQwN2QtOGNlYS1lMTc4YjhlM2JhMjMiLCJ0b2tlbl91c2UiOiJhY2Nlc3MiLCJzY29wZSI6ImF3cy5jb2duaXRvLnNpZ25pbi51c2VyLmFkbWluIiwiYXV0aF90aW1lIjoxNzI2MjkyMjQ0LCJleHAiOjE3MjYyOTU4NDQsImlhdCI6MTcyNjI5MjI0NCwianRpIjoiYjFlNjJkZmItOTE2YS00YWNkLWIyNzEtZmQ1MWIyMTNlN2YzIiwidXNlcm5hbWUiOiJmNzU0N2E2OC01MGIxLTcwYWUtNzI3NC04YTQ5ZTM2NWUwMTgifQ.swu6FJ65NHD6m8OCJinC8czxsuZdSuedLmqWp5kuB7gfV6-MAetPiXXLKEQpKVADVMmq6b8qm5ay3LygNh-hc2HZfO90z3ExtXrhadBnP_YWY8oXjjE__RpudrlLpiDyHm-UFm_xhXOr49z0e0v6bsa1Bd7d-d8z0wkKdXBfxfaCsTbdXlXd_fQ28XliK_8PUJjXtApHMJsP_YE5I8a0lyefkaYlL4RTFzSiBoBajwkfPT27zEJ5ql9z4-zAi7ErkvsZi7E6ICT5rMZsOKv0Ors09qEwb2UCWt1awg_AEUI94RReozuqL3-d1PXrK0OXkBBYi45fj5t0iOLvGu2Wog",
        "ExpiresIn": 3600,
        "TokenType": "Bearer",
        "RefreshToken": "eyJjdHkiOiJKV1QiLCJlbmMiOiJBMjU2R0NNIiwiYWxnIjoiUlNBLU9BRVAifQ.M2gc0WBKlWF_ZFk4QJoZ-VT-velPnLfs4RiC_bc_ZK0V_fNMX9VASBfTG64FDhSlMOPaatwHXWK0uZLLx2u3j-W8otNyrO18K-GEEeDMh7q8P74P8VglKAsHmJctpv0eKukCFDo3xZLX5ZGgBwRDNY8cAbWBDrrzCB_F1Rr8JFZs731BJnIxWpVoNS5MUpyQW88SErD0Bm3dHG73Y39y6RPfesWdfQNm3gTV6g-UXFDNlTA_GTWhfOK6G4tyqd5j1HrTwMhfaq4Nx4c1LToPNpk5kFbxETO-0hBlkbpi0Dl0-p9sM3_jI6xXVfG_AKybaV-VoquJRLfO1QMfQVELiw.UPFGjVLvm662T_3v.nNbFg7miZV9OuJOMkMuvkBEFtU3AYsTIY1jnkzI_Q0KOJb45DAvZAuAaKMA15--96KLzTdUhL0T2Lt5VRYGBg7tPRIcD0fiHVS2NTkLW3JqpSEOv1d5j0CQ0oW3goUQFO_FmHTR6dJ0G56FbfC4WB6I27VRoGrlyX8peuBXqPzH088Cv45EEC7bo9vvI2ktBG7jHuLc6yeNF8B05UTEPOn1qsOC4TNf5Y3GC1-pB5NNukNcrStqiULAvLVz4YewrykfYGhzamNC2BR2dicAKMoKWz_14ViMZeivF9z7-epN63ohNjN5GVAS6lXwqKmtNT1sOHwONi1JKrPQ_z8Gh4qmXnZYliPcb9gyGOO2_sZ5DacYISJ3KqU-Hp-1HsT7BDvh8ohay2nDtE0goQEVtb7xTeUTvLmO_PNdKKzljboKdXfZI2D3OVHzw4yUC7QJQtjKArJ6acDlwy5_wiTQWOdAlKrZYNuHYsjVzcsi1pO-ZaJY_KgjQ3VAu8fVOkJFwfS5JTjVJsmOFbZsoJWvu1eeDfnB_UphfxzrZzdpnmdEw2yBWfjk1HHuwd4gYkdpbo61md5AKdouyLkUvDtyZlNDDCoHdY7gjlBKrGP4IPzi1fu8X0-afCoPiW-9nMwfceIkvSSYuY_QMAzkoqQ73ZwUM2DxwkAUvGYuSDByaZpdra-5EEts7sKXdmPTNrTCItB_brcF_rRo5OAJPlJJD2E8q6Jg0Afrh_xrdPj2aRmhSCSGG2fdDz1Q-zYkpopo4wCy_Ds4Acxg9hQF5h2f4VjixCBwpzT9xnjzc8NrgjId_uFu9igfcw2dU9e0kZaWBB_9me36yFIyw4zcIyjYi499xe_iDM3HomAYUtjG2XNY9yRQKXWWEYo0sE9aVA9BuATpsAXMa9alxMQfMgGePsBKt9_qGOIovpT_38n7ReLiSBN_WSxfbuZghhETA1ICIQA8EOnzoI2UkeMyrQnRMAlSnV9xDuK8B28jowopSnV5fcWMYyddWQ2SsLusl2WD4X0Y3Tgs-cmY0o-oBVtQMBuQ7tEvC0PCpTKCA_-37gLcIS9-QGnq14CmQ0T21ru4thKwjpeC6qkC36FRRv6OYLX0w7Oy3bLNWVG8xdzgc7oii8YCSL_VZjci2lJSM0hy5MScLlbSs3tgX6ohWIxcrK2SxaKP5dgTuDGBrRINiikLb22WBlEDz_8WMpuRD4bf8u35nm9kzyTMUsWHR2q5boNs8DecDWPwufiaYiNUtMojqF_qWpkasNMWCs5ILXv2YqnWiNhhj8iApYUm82-ODrOoXLogai1ip3pYXVOo5TFsg_f9wQcR48r-iZ-w6_qQlIOlxl9c9j1Q6.uXKrIOgkcNHtFJJ6AQAnqA",
        "IdToken": "eyJraWQiOiJXY3ozaXpwYzFkdzJyTTV0dGMzbm5UMk1ZTUxtYko4WUxWZ1QyQ1wvWlVOST0iLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJmNzU0N2E2OC01MGIxLTcwYWUtNzI3NC04YTQ5ZTM2NWUwMTgiLCJpc3MiOiJodHRwczpcL1wvY29nbml0by1pZHAuYXAtbm9ydGhlYXN0LTEuYW1hem9uYXdzLmNvbVwvYXAtbm9ydGhlYXN0LTFfY3BKUUtFOEpXIiwiY29nbml0bzp1c2VybmFtZSI6ImY3NTQ3YTY4LTUwYjEtNzBhZS03Mjc0LThhNDllMzY1ZTAxOCIsIm9yaWdpbl9qdGkiOiJiYWY4Y2FjNi0wNjhhLTRmZTctOWU4Ni01Y2Q2YmYxZWE3ZTUiLCJhdWQiOiI2dnVxczJ1cHVrdWd2cm5iNTVhMXVjY2pjYyIsImV2ZW50X2lkIjoiOGNhMWM3N2ItYzc4Yi00MDdkLThjZWEtZTE3OGI4ZTNiYTIzIiwidG9rZW5fdXNlIjoiaWQiLCJhdXRoX3RpbWUiOjE3MjYyOTIyNDQsImV4cCI6MTcyNjI5NTg0NCwiaWF0IjoxNzI2MjkyMjQ0LCJqdGkiOiIxZGZjYjdlNi1lMGRiLTQwMDQtOTYyYy1hMzQzM2NhMmUwZjYiLCJlbWFpbCI6InRvcnVrby5lbmdpbm5lckBnbWFpbC5jb20ifQ.LTJg9yMMr7FwwAD53sM3_yym4r1bUo_4C7WS9IQixb47U7R0GzeOOstpXsUQBhQ44hSXYhPgE7gK2n-1uhJ4yROOdxuRdtQpphTvEWRUZko6e1cO0vLwdXRFtVPMPeapU_pmP2_67vHDGSZhIbOI6lTsUVUKTl91dDnb42R08VrbdSoVzJEVUntB_0dNXuCi1C1h10O2HvqDSJiAtzE5b36e25yXrX2bgHdCPy9yfZwfLJQms6LNJMvlIm90lspn99ttWXM9zoAIFInXNMW8xomzXnncyJdo82D2ydlPprAz2KSD0wIs_Uy5nzlWPygQpuIzTU7cgGaoTfuaVyM-7Q"
    }
}

マネジメントコンソールに戻り、作成したユーザーのステータスが「確認済み」になっていることを確認します。

下記を参考にしました。詳しい内容を確認したい場合は参照してください。

よかったらシェアしてね!
  • URLをコピーしました!

コメント

コメントする

目次