React.jsとAWS Cognitoを使用して、新規ユーザー登録機能を実装する

こんばんは。

今日は「Next.jsとAWS Cognitoを使用して、新規ユーザー登録機能を実装する」について説明いたします。

# 前提準備

- AWSでCognitoユーザープールを作成済みであること
- Next.jsアプリケーションがセットアップ済みであること

# AWS Amplifyを使ってCognitoと接続

AWS Amplifyライブラリを使用すると、Cognitoユーザープールと簡単に統合できます。以下の手順で設定していきます。

## AWS Amplifyと依存関係をインストール

```
npm install aws-amplify @aws-amplify/auth
```

## Amplify設定ファイル作成

AWSのCognitoユーザープールの情報を含めて、aws-exports.jsファイルを作成します。

```js
// aws-exports.js
export default {
  Auth: {
    region: 'us-east-1', // ご自身のAWSリージョンに置き換え
    userPoolId: 'us-east-1_example', // CognitoユーザープールID
    userPoolWebClientId: 'exampleclientid', // アプリクライアントID
  },
};
```

# Amplifyの設定をNext.jsで初期化

`pages/_app.js`に設定を追加し、Amplifyを初期化します。

```js
import { Amplify } from 'aws-amplify';
import awsExports from '../aws-exports';

Amplify.configure(awsExports);

export default function MyApp({ Component, pageProps }) {
  return <Component {...pageProps} />;
}
```

# Emailを入力するフォームの作成

新規登録ページ (`pages/signup.js`) にEmailを入力するフォームを作成します。

```js
import { Auth } from 'aws-amplify';
import { useState } from 'react';

export default function SignUp() {
  const [email, setEmail] = useState('');
  const [confirmationSent, setConfirmationSent] = useState(false);

  const signUp = async () => {
    try {
      await Auth.signUp({
        username: email,
        password: Math.random().toString(36).slice(-8), // 仮パスワード
        attributes: {
          email,
        },
      });
      setConfirmationSent(true);
    } catch (error) {
      console.error('Error signing up:', error);
    }
  };

  return (
    <div>
      <h2>Sign Up</h2>
      {confirmationSent ? (
        <p>Confirmation email has been sent. Please check your email.</p>
      ) : (
        <div>
          <input
            type="email"
            value={email}
            onChange={(e) => setEmail(e.target.value)}
            placeholder="Enter your email"
          />
          <button onClick={signUp}>Sign Up</button>
        </div>
      )}
    </div>
  );
}
```

# 認証URLをクリック後のユーザー情報入力ページ

認証メールに含まれるリンクは、AWS Cognitoで指定する必要があるため、Cognitoユーザープール設定で「確認完了後リダイレクトURL」を設定します。

- `pages/confirm.js`ページでユーザー情報入力画面を作成します。
- `Auth.confirmSignUp`で認証を完了させ、ユーザー情報を受け取ります。

```js
import { useRouter } from 'next/router';
import { useState } from 'react';
import { Auth } from 'aws-amplify';

export default function ConfirmSignUp() {
  const router = useRouter();
  const [username, setUsername] = useState('');
  const [password, setPassword] = useState('');
  const [confirming, setConfirming] = useState(false);

  const confirmSignUp = async () => {
    try {
      setConfirming(true);
      const user = await Auth.confirmSignUp(username);
      await Auth.signIn(username, password);
      router.push('/profile'); // 登録後のリダイレクト先
    } catch (error) {
      console.error('Error confirming sign up:', error);
      setConfirming(false);
    }
  };

  return (
    <div>
      <h2>Confirm Sign Up</h2>
      <input
        type="text"
        value={username}
        onChange={(e) => setUsername(e.target.value)}
        placeholder="Username"
      />
      <input
        type="password"
        value={password}
        onChange={(e) => setPassword(e.target.value)}
        placeholder="New Password"
      />
      <button onClick={confirmSignUp} disabled={confirming}>
        {confirming ? 'Confirming...' : 'Confirm'}
      </button>
    </div>
  );
}
```

# まとめ

- signup.jsでEmailを入力し、新規ユーザーがCognitoに登録。
- Cognitoから送られた認証URLをクリック後、confirm.jsでユーザー情報（パスワード等）を設定して、最終的にサインイン完了。

これで、新規ユーザーがEmailを通じて認証し、アカウント情報を入力して完了するフローが構築されます。

今日は以上です。

ありがとうございました。
よろしくお願いいたします。