AWS Amplify Gen 2 の標準サインアップ機能にメールドメイン制限を加える
この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
いわさです。
社内向けのある企画があり、その中のタスクのひとつとして Web アプリケーションを作成する必要がありました。
 チームで「どうやって作ろうか?」という話をしていた時に「Amplify とかでサクッと出来るのでは」と言ってしまい、私が担当することになりました。
 今思えば「知らんけど」を付けるのを忘れていたなと思います。
というわけで、本当にサクッと作れるのかはわからないですが、せっかくなのでちょっと前に GA した Amplify Gen 2 を使って作り始めてみることにしました。
まずはお決まりですが、ドキュメントに従ってテンプレートからデフォルトアプリケーションの起動までを行いました。
 そして、認証が必要なアプリケーションになるので認証機能を追加しました。
 さらに、とりあえず社内向けということでクラスメソッドのメールアドレスでのみサインアップ出来るようにカスタマイズまでしました。
テンプレートから作成
公式ドキュメントの Quickstart に従って従って新規アプリケーションを作成して起動するところまでは非常に簡単です。
 以下の公式ドキュメントを参考にテンプレートリポジトリをクローンし、Amplify コンソールから Git 連携を行ってそのままデプロイします。

これだけで、まずは最低限の TODO アプリみたいなのものをとりあえず動かすことができます。

認証機能を追加
ここから色々と変更しながら学んでいけば良いかなという感じですが、まずは認証機能を追加することにしました。
 Amplify はデフォルトで認証コンポーネントが提供されており、Cognito ユーザープールが使用されています。
Amplify コンソールの認証セットアップ手順に従って認証機能の追加を行います。

import { Authenticator } from '@aws-amplify/ui-react' import '@aws-amplify/ui-react/styles.css' import { useEffect, useState } from "react"; import type { Schema } from "../amplify/data/resource"; import { generateClient } from "aws-amplify/data"; const client = generateClient<Schema>(); function App() { const [todos, setTodos] = useState<Array<Schema["Todo"]["type"]>>([]); useEffect(() => { client.models.Todo.observeQuery().subscribe({ next: (data) => setTodos([...data.items]), }); }, []); function createTodo() { client.models.Todo.create({ content: window.prompt("Todo content") }); } return ( <Authenticator> {({ signOut }) => ( <main> <h1>My todos</h1> <button onClick={createTodo}>+ new</button> <ul> {todos.map((todo) => ( <li key={todo.id}>{todo.content}</li> ))} </ul> <div> 🥳 App successfully hosted. Try creating a new todo. <br /> <a href="https://docs.amplify.aws/react/start/quickstart/#make-frontend-updates"> Review next step of this tutorial. </a> </div> <button onClick={signOut}>Sign out</button> </main> )} </Authenticator> ); } export default App; <main>タグを<Authenticator>タグで囲います。
 まずはローカル環境で実行してみましょう。テンプレートに認証コンポーネントは最初から含まれていたのでバックエンドの再構築は不要でフロントエンドの変更のみで追加が可能でした。
% npm run dev > amplify-vite-react-template@0.0.0 dev > vite Re-optimizing dependencies because lockfile has changed VITE v5.3.4 ready in 387 ms ➜ Local: http://localhost:5173/ ➜ Network: use --host to expose ➜ press h + enter to show help アクセスしてみると認証画面が表示されるようになりました。

ユーザーアカウントをまだ用意できていないので「Create Account」からサインアップ機能を使ってみます。
 メールアドレスとパスワードを入力すると、認証コードがメールで送信されました。

コードを入力するとサインアップが完了し、そのままサインインされます。
 なるほどね。

認証機能については Amplify コンソールと統合されておりこちらからユーザーの管理が可能です。

一方で裏側の仕組みは Cognito ユーザープールなので、Cognito リソースに直接アクセスすることも可能です。
 自動でユーザープールが作成されており、先程登録したユーザーが追加されていました。
 直接変更して良いのかはまだ謎ですが、Cognito で実現出来ることであれば何でもできそうな気がしてきました。

一部のメールドメインのみサインアップを許可してみる
で、Cognito ユーザープールということは Lambda トリガーを使うことで、認証フローであれやこれやと色々出来るわけですよね。
 今回だとチームの概念を取り入れたかったので、グループやカスタムクレームを設定したりなどやりたいことは色々あるのですが、そもそも Amplify Gen 2 において Lambda トリガー設定方法を試してみることにしました。
いくつか認証カスタマイズの例が載っており、このメールドメインでのサインアップ制限は使っておきたいかつ、導入しやすいなと思ったので早速やってみることにしました。
基本的に上記ドキュメントのとおりで、以下のALLOW_DOMAINのみ変更しています。
import { defineFunction } from '@aws-amplify/backend'; export const preSignUp = defineFunction({ name: 'pre-sign-up', // optionally define an environment variable for your filter environment: { ALLOW_DOMAIN: 'classmethod.jp' } }); 関数なども作成しておりバックエンドの更新が必要なので、バックエンドを更新しましょう。
 ただ、本番環境にいきなりデプロイはしないのでサンドボックス環境にデプロイします。なるほど。
CloudFormation スタックを確認したところ Lambda 関数はデプロイされているようだったので良さそうです。

そしてローカル環境にアクセスしたところ、Cognito のサインアップ前トリガーが動作して許可されたドメイン以外ではサインアップができなくなりました。もちろんclassmethod.jpドメインであればサインアップはできます。良いですね。

動作確認して良さそうだったので本番環境にもデプロイしてみます。
 GitHub リポジトリと統合されているのでリモートブランチにプッシュしてやるだけです。
 GitHub Action が設定されているわけではないのですが、Amplify 側で勝手に検出してくれます。ビルドとデプロイが開始されました。

デプロイ完了後に運用 URL にアクセスしたところ、こちらでもサインアップの制限を確認することができました。良さそうです。

さいごに
本日は AWS Amplify Gen 2 の標準サインアップ機能にメールドメイン制限を加えるところまでやってみました。
Amplify に慣れている方にとっては、非常に基本的なところだと思いますが、ひとつづつ「なるほど」と思いながら進めていきました。
そうですねぇ。認証が追加出来たので、次はとあるバックエンド API を定期的にポーリングするような動きを実装してみたいと思います。ポーリングじゃなくて双方向でも良いんですがそれは次回考えます。







