LoginSignup
0
0

Astro✖️Amplify✖️Cognitoでログイン機能を作る

Last updated at Posted at 2024-05-12

成果物

img_01.png

img_02.png

ログインの仕組みのイメージ

大雑把に下図のイメージの理解です。

img_understanding_2.png

前提

フロントの実装に焦点を当てています。

Cognitoでユーザープールとアプリケーションクライアントを予め作成して下さい。

「セルフサービスのサインアップ」は有効にして下さい。

ユーザーが自分でユーザー登録出来るように作りたいです。

ディレクトリ構成(完成時)

ほぼデフォルトのままです。

.
├── astro.config.mjs
├── package-lock.json
├── package.json
├── public
│   └── favicon.svg
├── src
│   ├── env.d.ts
│   ├── layouts
│   │   └── Layout.astro
│   └── pages
│       ├── auth.astro
│       └── index.astro
└── tsconfig.json

手順

  1. プロジェクト作成
  2. Aamplifyインストール
  3. auth.astro作成
  4. index.astro変更

プロジェクト作成

npm create astro@latest

Aamplifyインストール

Amplifyライブラリをインストールします。

npm install aws-amplify

auth.astro作成

/src/pages/auth.astroを以下の内容で作成します。

/src/pages/auth.astro
---
import Layout from '../layouts/Layout.astro';
---

<Layout title="認証ページ">
	<main>
    <h2>ユーザー登録</h2>
    <form name="signup">
      <div>
        <label for="email">ユーザー名:</label>
        <input type="text" name="user" />
      </div>
      <div>
        <label for="email">メールアドレス:</label>
        <input type="text" name="email" />
      </div>
      <div>
        <label for="password">パスワード:</label>
        <input type="password" name="password" />
      </div>
      <div>
        <input type="submit" value="登録" />
      </div>
    </form>
    <h2>ユーザー検証</h2>
    <form name="confirm">
      <div>
        <label for="email">メールアドレス:</label>
        <input type="text"name="email" />
      </div>
      <div>
        <label for="password">検証コード:</label>
        <input type="text" name="code" />
      </div>
      <div>
        <input type="submit" name="submit" value="検証" />
      </div>
    </form>
    <h2>ログイン</h2>
    <form name="login">
      <div>
        <label for="email">メールアドレス:</label>
        <input type="text"name="email" />
      </div>
      <div>
        <label for="password">パスワード:</label>
        <input type="password" name="password" />
      </div>
      <div>
        <input type="submit" name="submit" value="ログイン" />
      </div>
    </form>
  </main>
</Layout>

<script>

  import { Amplify } from 'aws-amplify';
  import { signIn, signUp, confirmSignUp } from 'aws-amplify/auth'

  Amplify.configure({
    Auth: {
      Cognito: {
        userPoolId: 'ご自身のユーザープールID',
        userPoolClientId: 'ご自身のクライアントID',
      }
    }
  });

  // ユーザー登録
  const formSignUp = document.forms['signup'];

  formSignUp.addEventListener('submit', async e => {
    e.preventDefault();
    const user = formSignUp.elements['user'].value;
    const email = formSignUp.elements['email'].value;
    const password = formSignUp.elements['password'].value;
    const { isSignUpComplete, userId, nextStep } = await signUp({
      username: email,
      password: password,
      options: {
        userAttributes: {
          name: user,
        },
      }
    });
    console.log({ isSignUpComplete, userId, nextStep });
    console.log(`${email}に確認のメールを送りました。`);
  });

  // ユーザー検証
  const formVeryficate = document.forms['confirm'];

  formVeryficate.addEventListener('submit', async e => {
    e.preventDefault();
    const email = formVeryficate.elements['email'].value;
    const code = formVeryficate.elements['code'].value;
    const { isSignUpComplete, nextStep } = await confirmSignUp({
      username: email,
      confirmationCode: code
    });
    console.log({ isSignUpComplete, nextStep });
    console.log(`ユーザー検証成功`);
  });

  // ログイン
  const loginForm = document.forms['login'];

  loginForm.addEventListener('submit', async e => {
    e.preventDefault();
    const email = loginForm.elements['email'].value;
    const password = loginForm.elements['password'].value;

    try {
      const result = await signIn({
        username: email,
        password: password,
      });
      console.log(result);
      console.log(`ログイン成功`);
    } catch (err) {
      console.log(err);
    }

  });
</script>

<style>
  main {
    padding: 0 16px;
    /* width: 640px;
    margin: 0 auto; */
  }
  h2 {
    margin-top: 24px;
  }
  form > div {
    margin-top: 16px;
    display: flex;
  }
  label {
    display: block;
    width: 160px;
  }
</style>

index.astro変更

/src/pages/index.astroを以下のように変更します。

/src/pages/index.astro
---
import Layout from '../layouts/Layout.astro';
---

<Layout title="トップページ">
	<main>
    <p id="greet">こんにちは、ゲストさん</p>
	</main>
</Layout>

<script>
  import { Amplify } from 'aws-amplify';
  import { fetchUserAttributes, fetchAuthSession } from 'aws-amplify/auth'

  Amplify.configure({
    Auth: {
      Cognito: {
        userPoolId: 'ご自身のユーザープールID',
        userPoolClientId: 'ご自身のクライアントID',
      }
    }
  });

  try {
    // ログイン時に保存したアクセストークンを使いCognitoにユーザー情報を取りに行く
    const userInfo = await fetchUserAttributes();
    console.log({ userInfo });
    // アクセストークンを使い、APIGWなどを叩きたい場合は以下でアクセストークンを取得出来る
    const { tokens: { accessToken } } = await fetchAuthSession();
    console.log( accessToken );
    
    document.getElementById('greet').innerText = `こんにちは、${userInfo.name}さん`;
  } catch (err) {
    console.log(err);
  }

</script>

<style>
  main {
    padding: 0 16px;
    /* width: 640px;
    margin: 0 auto; */
  }
  p {
    margin-top: 24px;
  }
</style>

ユーザー登録

npm run devしてauthページ(http://localhost:4321/auth)にアクセスします。

img_register.png

ユーザー検証

ユーザー登録すると、入力したメールアドレス宛に検証コードが届きます。

img_confirm.png

ログイン

ログイン成功の文字がConsoleに出力されます。

img_login.png

ユーザーページ

トップページ(http://localhost:4321)にアクセスします。

登録したユーザー名で「こんにちは、⚫︎⚫︎さん」と表示されます。

img_userinfo.png

ユーザー名(⚫︎⚫︎さん)を何処で取得しているか?

ログインするとアクセストークンなどがブラウザのローカルストレージに保存されます。

fetchUserAttributes( )をすると、ローカルストレージよりアクセストークンを取り出して、Cognitoからユーザー情報を取得しているようです。

開発者ツールの「Network」タブにてAccessTokenを送信している事が確認出来ます。

img_fetchdata_2.png

アクセストークンを使いAPIGWなどにアクセスしたい

index.astroに記述しましたが、fetchAuthSession( )でアクセストークンを取得出来ます。

アクセストークンをtoString()するとJWTになります。

おわりに

ざっくり理解するためにシンプルに作ることを目標にしました。

実際のプロジェクトだと、ログインを制御するコンポーネントを作ったりするのかな、と想像しています。一旦、動かして見たかったぐらいの気持ちだったので、ここまでの実装にとどめております。悪しからずです。

0
0
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
0
0