Amazon CognitoのPre-Signup Triggerを利用して、Next.jsアプリにサインアップ機能を実装

こんばんは。

今日は「Amazon CognitoのPre-Signup Triggerを利用して、Next.jsアプリにサインアップ機能を実装する方法」について説明します。

このトリガーを使うと、ユーザーがサインアップフォームを送信した際に、Cognitoによるサインアップ処理の前にカスタムロジックを実行することができます。例えば、サインアップ前に特定のバリデーションを追加したり、条件に応じてサインアップを制御することができます。

以下にその手順を説明します。

# Amplifyのセットアップ

まず、AWS Amplifyがプロジェクトにセットアップされていない場合は、セットアップします。

```bash
# プロジェクトのディレクトリで以下を実行してAmplifyをセットアップ
amplify init
```

このコマンドに従い、プロジェクトの設定を行います。

次に、Auth（Cognito）カテゴリを追加します。

```bash
amplify add auth
```

ここで、Cognitoの設定を選択します。通常は、`Default configuration`を選んで問題ありません。

# Pre-Signup Triggerの設定

AmplifyでCognitoのトリガーを設定するためには、amplify add functionを使ってLambda関数を作成し、そのLambda関数をPre-Signup Triggerとして設定します。

## Lambda関数の作成

```bash
amplify add function
```

プロンプトに従い、以下のように設定します。

- Function name: `PreSignupTrigger`
- Lambda template: `Hello World`
- Access to Cognito: `Yes`

## Pre-Signup Triggerの設定

次に、Lambda関数を作成したら、CognitoのPre-Signupトリガーにその関数を紐付けます。

```bash
amplify update auth
```

このコマンドで設定を変更し、以下のように進めます。

- Auth settings: `Manual configuration`を選択
- Add Pre-Signup Lambda trigger: `Yes`
- Lambda function name: 先ほど作成した`PreSignupTrigger`

## Lambda関数の実装

次に、PreSignupTrigger関数を実装します。`amplify/backend/function/PreSignupTrigger/src/index.js`にアクセスし、サインアップ前に実行したい処理を追加します。

例えば、特定のメールドメインだけでサインアップを許可する場合のコードは以下のようになります。

```javascript
exports.handler = async (event) => {
  // メールアドレスのドメインをチェック
  const email = event.request.userAttributes.email;
  const allowedDomain = 'example.com';

  if (!email.endsWith(`@${allowedDomain}`)) {
    // サインアップを拒否する
    throw new Error('Only email addresses from example.com are allowed');
  }

  // サインアップを許可する場合はそのままイベントを返す
  return event;
};
```

このコードでは、サインアップ時に入力されたメールアドレスがexample.comドメインでない場合にエラーを投げてサインアップを拒否しています。

## 変更のデプロイ

```bash
amplify push
```

これで、CognitoのPre-Signup TriggerにLambda関数が設定され、サインアップ前にカスタムロジックを実行できるようになります。

# Next.jsでサインアップ機能の実装

次に、Next.jsでユーザーがサインアップできるフォームを作成します。AmplifyのAuthモジュールを利用して、ユーザー認証を行います。

まず、`aws-exports.js`をインポートしてAmplifyを設定します。pages/_app.jsに以下を追加します。

```javascript
import { Amplify } from 'aws-amplify';
import awsconfig from '../aws-exports';

Amplify.configure(awsconfig);
```

次に、サインアップフォームを作成します。`pages/signup.js`に以下のように実装します。

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

export default function SignUp() {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [error, setError] = useState('');

  const handleSubmit = async (e) => {
    e.preventDefault();

    try {
      await Auth.signUp({
        username: email,
        password,
        attributes: {
          email,  // ユーザーのメールアドレス
        },
      });
      alert('Sign up successful!');
    } catch (error) {
      setError(error.message);
    }
  };

  return (
    <div>
      <h2>Sign Up</h2>
      <form onSubmit={handleSubmit}>
        <div>
          <label>Email</label>
          <input
            type="email"
            value={email}
            onChange={(e) => setEmail(e.target.value)}
            required
          />
        </div>
        <div>
          <label>Password</label>
          <input
            type="password"
            value={password}
            onChange={(e) => setPassword(e.target.value)}
            required
          />
        </div>
        {error && <p style={{ color: 'red' }}>{error}</p>}
        <button type="submit">Sign Up</button>
      </form>
    </div>
  );
}
```

# サインアップのテスト

これで、サインアップフォームが完成しました。`example.com`以外のメールアドレスでサインアップしようとすると、Pre-Signup Triggerによってエラーメッセージが表示されるはずです。


# まとめ

- AmplifyでCognito Authを設定
- Pre-Signup Trigger用のLambda関数を作成
- Lambda関数でサインアップ前のバリデーション処理を実装
- Next.jsでサインアップフォームを作成し、Auth.signUpを利用してサインアップ機能を実装

これで、CognitoのPre-Signup Triggerを使ってサインアップ時にカスタム処理を追加することができるようになります。

今日は以上です。

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