LoginSignup
2
2

Nuxt3 + AWS Cognito スターターセット

Last updated at Posted at 2023-10-31

初めに

仕事で認証系を実装することになったが、cognito等を使って外に出した方が実装コストや保守運用も楽になるので、簡単な実装ガイドとして本記事を書く

コードは以下のリポジトリ

準備

AWS Cognito

まず、認証用のユーザープールをaws cognitoで作成する必要がある。
Amazon Cognito > ユーザープール > ユーザープールを作成
image.png

ユーザープールの作成後に Cognito ユーザープールのサインインオプションを変更することはできません。

cognito関連の設定は変更が効かないので、慎重に。
今回はメールアドレスとパスワードのみのシンプルな認証なので以下で設定

認証プロバイダー
プロバイダータイプ:Cognito ユーザープール
Cognito ユーザープールのサインインオプション:Eメール

image.png

パスワードポリシー
パスワードポリシーモード:Cognito のデフォルト

image.png

多要素認証
MFA の強制:MFAなし(本当は必要だよ)

image.png

ユーザーアカウントの復旧
セルフサービスのアカウントの復旧情報:セルフサービスのアカウントの復旧を有効化 - 推奨
ユーザーアカウント復旧メッセージの配信方法:Eメールのみ

image.png

サインアップエクスペリエンスを設定
セルフサービスのサインアップ:自己登録を有効化

image.png

属性検証とユーザーアカウントの確認
検証する属性: E メールのメッセージを送信、E メールアドレスを検証
属性変更の確認: 未完了の更新があるときに元の属性値をアクティブに保つ - 推奨
未完了の更新があるときのアクティブな属性値: E メールアドレス

image.png

追加の必須属性: 無し

image.png

メッセージ配信を設定
E メール: Cognito で E メールを送信
image.png

ユーザープール名: 任意

image.png

ホストされた認証ページ: 無効

image.png

アプリケーションタイプ: パブリッククライアント
アプリケーションクライアント名: 任意
クライアントシークレット: クライアントのシークレットを生成しない

image.png

ユーザープールIDとクライアントIDを保存しておく

コード

何はともあれgit clone

git clone https://github.com/sandy-sunday/nuxt3_cognito_tutorial.git

環境変数のテンプレートをコピーして、先ほど保存したユーザープールIDとクライアントIDをコピぺする。

cp .env.example .env
NUXT_PUBLIC_USER_POOL_ID=your_user_pool_id
NUXT_PUBLIC_CLIENT_ID=your_client_id

必要パッケージをインストールしてサーバーを起動

yarn install
yarn dev

image.png

localhost:3000 にアクセスして画面が表示されたら成功。

コード補足

cognitoで作ったユーザーでログインできない

実装時に詰まった部分として、cognitoのコンソール上で作成したユーザーで初めてログインしようとしたら、"Error: New password is required."と出てログインに失敗することがあった。この状況でcognitoUser.forgotPassword()を使っても、認証コードが送られてくることは無く、cognitoコンソール上で「E メールアドレスを検証済みとしてマークする」にチェックを入れても解消されることは無かった。

どうやら初回ログインのみcognitoUser.completeNewPasswordChallenge()でパスワードを設定する必要がある。

// /pages/login.ts
  cognitoUser.authenticateUser(authenticationDetails, {
    onSuccess: function() {
      window.location.href = '/login-success';
    },
    newPasswordRequired: function(userAttributes, requiredAttributes) {
      showNewPasswordInput.value = true;
      buttonLabel.value = 'Reset Password';
      
      // On initial login, the user must change their password
      cognitoUser.completeNewPasswordChallenge(newPassword.value, {}, {
        onSuccess: function() {
          window.location.href = '/login-success';
        },
        onFailure: function(err) {
          console.log("Error:", err);
        }
      });
    },
    onFailure: function(err) {
      console.log("Error:", err);
    }
  });

global is not defined

cognito 関連の設定は/plugins/cognito.tsに実装している。プラグインとして、各ページで利用できるようにしているのだが、JavaScriptのグローバルオブジェクトは、ブラウザ上とNode.js上では異なり、ブラウザ上では”window”、Node.js上では”global”が対応するため、yarn devで実行しようとすると500 global is not definedと出てしまう。

// /nuxt.config.ts
export default defineNuxtConfig({
  devtools: { enabled: true },
  vite: {
    define: {
      'window.global': {}, // In SSR, window is not defined. This is a workaround.
    },
  },
  .....
  ...

対策として、globalに空オブジェクトを定義してあげるとエラーを回避できる。詳しくは下の記事を参照

環境変数の設定

// /nuxt.config.ts
export default defineNuxtConfig({
  runtimeConfig: {
    public: {
      userPoolId: '',
      clientId: '',
    }
  },
});

.envを用意して環境変数に指定する方法を忘れていたため、記載。NUXT_PUBLIC_USER_POOL_IDのように接頭にNUXTを付けると環境変数として認知される。続けてPUBLICのようにネストすることも可能。nuxt3からはdotenvがプリインストールされているようで設定が楽になってる。

ログインにリダイレクト

// /middleware/redirect-login.ts
export default defineNuxtRouteMiddleware((to,from) => {
    return navigateTo('/login')
  })
<!-- /pages/index.vue -->
<template>
    <h1>Landing Page</h1>
</template>

<script setup lang="ts">
  definePageMeta({
    middleware: ['redirect-login'] // redirecting to login page if not logged in
  })
</script>

デフォルトのランディングページであるindex.vueはログイン画面にリダイレクトするよう設定した。実際のWebサービスでは認証トークンに有効期限を設定して、有効期限が切れたらログインないしトップページに戻す為、先行実装。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2