🤗

【Next.js×Auth.js×Cognito】Amazon Cognitoマネージドログイン使ってみた

2025/02/19に公開

はじめに

ログイン画面の作成面倒だな。セキュリティの配慮なるべく減らしたいな。
そんな願いを叶えてくれるかもしれないCognitoマネージドログイン機能を使ってみました。

Amazon Cognitoマネージドログインとは

アプリケーションにログイン機能を簡単に追加するためのサービスです。
Amazon Cognitoに「ホストされたUI」機能は昔からありましたが、ログイン画面のカスタマイズがいまいち不便だったため、結局自分で実装するしかない状況でした。
しかし、2024年にマネージドログイン機能が導入され、文字やボタンの色、ファビコンやページ背景など、細かなところまでカスタマイズ可能になりました。これはうれしいアップデートです。

Auth.jsとは

https://authjs.dev/getting-started
もともとNextAuthという名前のライブラリでNext.jsに認証機能を組み込むためのOSSでしたが、現在はフレームワークに依存しない形に進化しています。
数多くのプロバイダに対応している点は非常に素晴らしい!もちろんCognitoにも対応しています。

検証概要

以下の手順で作成します。

  1. Next.jsプロジェクトの作成
  2. Auth.jsの導入
  3. Amazon Cognitoの設定
  4. Cognitoプロバイダの設定
  5. 動作確認画面の作成
  6. サインイン画面の日本語化

やってみる

以下のバージョンで実装しています。

  • Node.js 22.13.1
  • pnpm 9.15.4
  • Next.js 15.1.7
  • Auth.js 5.0.0 beta

Node.js、pnpmはインストール済み、AWSアカウントは作成済みの前提で進めます。

Next.jsプロジェクトの作成

create-next-appでNext.jsプロジェクトを作成します。

terminal
npx create-next-app@latest

プロンプトは以下のようにしました。最後だけNo、他はYesです。

terminal
? What is your project named? ... next-auth-cognito
? Would you like to use TypeScript? ... Yes
? Would you like to use ESLint? ... Yes
? Would you like to use Tailwind CSS? ... Yes
? Would you like your code inside a `src/` directory? ... Yes
? Would you like to use App Router? (recommended) ... Yes
? Would you like to use Turbopack for `next dev`? ... Yes
? Would you like to customize the import alias (`@/*` by default)? » No

Auth.jsの導入

公式ページに従います。
https://authjs.dev/getting-started/installation?framework=next-js

インストールコマンドを実行します。

terminal
pnpm add next-auth@beta

以下のコマンドで環境変数を作成します。
.env.localファイルが作成され、AUTH_SECRETにランダムな文字が設定されます。

terminal
npx auth secret

続いて以下3ファイルauth.ts route.ts middleware.tsを作成します。

./src/auth.ts
import NextAuth from "next-auth"
 
export const { handlers, signIn, signOut, auth } = NextAuth({
  providers: [],
})
./src/app/api/auth/[...nextauth]/route.ts
import { handlers } from "@/auth"
export const { GET, POST } = handlers
./src/middleware.ts
export { auth as middleware } from "@/auth"

これで基本的なセットアップは完了です。

Amazon Cognitoの設定

ここからはAWSを操作します。Amazon Cognitoのユーザープールメニューから「ユーザープールを作成」をクリックします。

アプリケーションタイプは「従来のウェブアプリケーション」を選択します。
アプリケーション名は何でもいいです。

オプションについては要件にあったものを選択してください。
ここでは「メールアドレス」を選択しました。

リターンURLにhttp://localhost:3000/api/auth/callback/cognitoを設定します。ローカル環境で実行するためにhttp://localhost:3000としていますが、本番環境では本番環境用のURLを設定してください。
「ユーザーディレクトリを作成する」をクリックします。

これでユーザプールの作成が完了しました。

次にOpenID Connectのスコープに「プロファイル」を追加します。Auth.jsがログイン時にプロファイルを要求するため、ここで設定しておかないとログイン時にエラーとなります。
アプリケーションクライアントのメニューからアプリケーションクライアント名を選択します。

「ログインページ」タブのマネージドログインページの設定から「編集」をクリックします。

OpenID Connectのスコープの「OIDCスコープを選択」をクリックすると、選択可能なリストが表示されます。その中の「プロファイル」を選択します。

「プロファイル」が追加されたことを確認し、「変更を保存」をクリックします。

Cognitoプロバイダの設定

公式ページに従い、Auth.jsにCognitoの設定を追加していきます。
https://authjs.dev/getting-started/authentication/oauth?framework=next-js

.env.localに環境変数(AUTH_COGNITO_IDAUTH_COGNITO_SECRETAUTH_COGNITO_ISSUER)を設定します。

AUTH_COGNITO_IDAUTH_COGNITO_SECRETはアプリケーションクライアントに関する情報から確認できます。

AUTH_COGNITO_ISSUERは少しスクロールしたところにあるQuick Setup ガイドの中から確認できます。

次にauth.tsのprovidersにCognitoを設定します。

./src/auth.ts
import NextAuth from "next-auth"
+ import Cognito from "next-auth/providers/cognito"
 
export const { handlers, signIn, signOut, auth } = NextAuth({
+  providers: [Cognito],
-  providers: [],
})

動作確認画面の作成

サインインボタンを作成します。

./src/sign-in.tsx
import { signIn } from "@/auth"
 
export default function SignIn() {
  return (
    <form
      action={async () => {
        "use server"
        await signIn("cognito")
      }}
    >
      <button className="border rounded" type="submit">サインイン</button>
    </form>
  )
}

トップページにサインインボタンとユーザ情報を表示します。

./src/page.tsx
import { auth } from "@/auth";
import SignIn from "./sign-in";

export default async function Home() {
  const session = await auth();
  return (
    <div>
      <SignIn />
      <div>{ session?.user?.email }</div>
    </div>
  );
}

動作確認

トップページにボタンを配置したので、ブラウザからhttp://localhost:3000/にアクセスします。

「サインイン」ボタンをクリックするとCognitoのサインイン画面へ移動します。

サインイン画面の日本語化

デフォルトではサインイン画面が英語になっていますが、サインインページのクエリパラメーターにlang=jaを指定することで日本語になります。Auth.jsを使用している場合、signIn関数の引数でクエリパラメータを指定することができます。

./src/sign-in.tsx
import { signIn } from "@/auth"
 
export default function SignIn() {
  return (
    <form
      action={async () => {
        "use server"
+        await signIn("cognito", {}, "lang=ja")
-        await signIn("cognito")
      }}
    >
      <button className="border rounded" type="submit">サインイン</button>
    </form>
  )
}

Cognitoで確認用ユーザを作成し、それを使ってサインインしてみます。
メールアドレスを入力するとパスワード入力画面が表示されました。

初回のサインインではパスワード変更を促されました。

サインインが成功するとアプリ側にリダイレクトされ、セッション情報が取得できていることが確認できました!

まとめ

Amazon Cognitoマネージドログインを使ってみました。
サインイン機能に加え、パスワード変更やアカウント作成機能もマネージドなのは魅力的ですね。
この記事が誰かのお役に立てれば幸いです。

マネージドログイン画面いじってみた

ロゴ画像と背景画像を変更しました。ボタンの色などを調整するとそれっぽい画面に変身しました。

Amazon Cognitoにブランディングデザイナーという機能が用意されていて、コーディングなしでスタイルの変更が行えるのはすごく便利ですね。

Auth.jsがうまく動かないとき

この記事の内容にたどり着くまでにAuth.jsのエラーで苦労しました。
以下のデバッグのオプションに助けられたため紹介しておきます。このオプションを有効にするとリクエスト内容がコンソールに表示されます。レスポンスのエラー内容も確認できます。
https://authjs.dev/guides/debugging

./src/auth.ts
import NextAuth from "next-auth"
 
export const { handlers, signIn, signOut, auth } = NextAuth({
  providers: [],
+  debug: true,
})

Discussion