1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Nextjs+Cognitoの検証用ローカル環境の作り方

Last updated at Posted at 2025-05-17

Cognito をローカルで検証してみたい人向けの記事です

内容

  • Docker

    • 仮想AWSサーバー(motoサーバー)の起動
    • 仮想AWSサーバーでCognitoの初期設定を行う
      • ユーザープール作成
      • ユーザー作成
  • Nextjs(App Router)

    • ログインフォームの表示
      • aws-amplify + @aws-amplify/ui-react
    • 仮想Cognitoにログイン

環境構築

mkdir local_nextjs_cognito
npx create-next-app@latest .

Nextjs の設定

Need to install the following packages:
create-next-app@15.3.2
Ok to proceed? (y)

√ Would you like to use TypeScript? ... No / Yes
√ Would you like to use ESLint? ... No / Yes
√ Would you like to use Tailwind CSS? ... No / Yes
√ Would you like your code inside a `src/` directory? ... No / Yes
√ Would you like to use App Router? (recommended) ... No / Yes
√ Would you like to use Turbopack for `next dev`? ... No / Yes
√ Would you like to customize the import alias (`@/*` by default)? ... No / Yes
√ What import alias would you like configured? ... @/*

フロントライブラリ追加

npm i aws-amplify @aws-amplify/ui-react

ライブラリのバージョンを掲載しておきます

package.json
  "dependencies": {
    "@aws-amplify/ui-react": "^6.11.2",
    "aws-amplify": "^6.14.4",
    "next": "15.3.2",
    "react": "^19.0.0",
    "react-dom": "^19.0.0"
  },
  "devDependencies": {
    "@eslint/eslintrc": "^3",
    "@types/node": "^20",
    "@types/react": "^19",
    "@types/react-dom": "^19",
    "eslint": "^9",
    "eslint-config-next": "15.3.2",
    "typescript": "^5"
  }

フォルダおよびファイルの作成

(ルートディレクトリで実行)

mkdir .\src\aws
New-Item .\src\aws\CognitoProvider.tsx

mkdir aws_mock
New-Item .\aws_mock\init.sh
New-Item .\aws_mock\Dockerfile

New-Item docker-compose.yml

Cognitoログイン画面の実装

今回は検証のため@aws-amplify/ui-reactで簡単に作ります

CognitoProvider.tsx
"use client";
import React from "react";
import { Amplify } from "aws-amplify";
import "@aws-amplify/ui-react/styles.css";
import { withAuthenticator } from "@aws-amplify/ui-react";

Amplify.configure(
  {
    Auth: {
      Cognito: {
        userPoolId: process.env.NEXT_PUBLIC_MOTO_USER_POOL_ID!,
        userPoolClientId: process.env.NEXT_PUBLIC_MOTO_CLIENT_ID!,
        userPoolEndpoint: process.env.NEXT_PUBLIC_MOTO_ENDPOINT,
      },
    },
  },
  { ssr: true }
);

const CognitoProvider = ({ children }: { children: React.ReactNode }) => {
  return <>{children}</>;
};

export default withAuthenticator(CognitoProvider);

layout.tsx
import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import "./globals.css";
import CognitoProvider from "@/aws/CognitoProvider"; // 追加

const geistSans = Geist({
  variable: "--font-geist-sans",
  subsets: ["latin"],
});

const geistMono = Geist_Mono({
  variable: "--font-geist-mono",
  subsets: ["latin"],
});

export const metadata: Metadata = {
  title: "Create Next App",
  description: "Generated by create next app",
};

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang="ja">   {/**jaに変更 */}
      <body className={`${geistSans.variable} ${geistMono.variable}`}>
        <CognitoProvider>{children}</CognitoProvider> {/**追加 */}
      </body>
    </html>
  );
}

aws_mockフォルダ

init.shの最後にパスワードを変更している理由:

Cognitoでユーザーを作成した際、メール認証が必要になります
モックサーバーのためメール送信ができません
メール認証を回避するためにパスワード変更を行っています

./aws_mock/Dockerfile
FROM alpine:3.19
WORKDIR /app
COPY init.sh .
RUN chmod +x init.sh
RUN apk --no-cache add curl jq

./aws_mock/init.sh
#!/bin/sh

# curlコマンドをインストールして使えるようにする
apk --no-cache add curl
# jqコマンドをインストールして使えるようにする
apk --no-cache add jq

# ユーザープールの作成
RESPONSE=$(curl -s -X POST http://moto:5000/ \
-H 'Content-Type: application/x-amz-json-1.1' \
-H 'X-Amz-Target: AWSCognitoIdentityProviderService.CreateUserPool' \
-H 'X-Amz-Date: 20240227T000000Z' \
-d '{
  "PoolName": "MyTestUserPool",
  "Policies": {
    "PasswordPolicy": {
      "MinimumLength": 8,
      "RequireUppercase": true,
      "RequireLowercase": true,
      "RequireNumbers": true,
      "RequireSymbols": true
    },
    "SignInPolicy": {
      "AllowedFirstAuthFactors": [
        "PASSWORD"
      ]
    }
  },
  "UsernameAttributes": [
    "email"
  ]
}')


# RESPONSEからUserPoolIDを取得する
USER_POOL_ID=$(echo $RESPONSE | jq -r '.UserPool.Id')

echo "User Pool ID: $USER_POOL_ID"

# UserPoolClientの作成
RESPONSE=$(curl -s -X POST http://moto:5000/ \
-H 'Content-Type: application/x-amz-json-1.1' \
-H 'X-Amz-Target: AWSCognitoIdentityProviderService.CreateUserPoolClient' \
-H 'X-Amz-Date: 20240227T000000Z' \
-d '{
  "ClientName": "MyTestUserPoolClient",
  "UserPoolId": "'"$USER_POOL_ID"'",
  "GenerateSecret": false
}')

# RESPONSEからUserPoolClientIDを取得
USER_POOL_CLIENT_ID=$(echo $RESPONSE | jq -r '.UserPoolClient.ClientId')

echo "User Pool Client ID: $USER_POOL_CLIENT_ID"



# ユーザープールにユーザーを作成
RESPONSE=$(curl -s -X POST http://moto:5000/ \
-H 'Content-Type: application/x-amz-json-1.1' \
-H 'X-Amz-Target: AWSCognitoIdentityProviderService.AdminCreateUser' \
-H 'X-Amz-Date: 20240227T000000Z' \
-d '{
  "UserPoolId": "'"$USER_POOL_ID"'",
  "Username": "test123@example.com",
  "TemporaryPassword": "Test@1234",
  "UserAttributes": [
    {
      "Name": "email",
      "Value": "test123@example.com"
    },
    {
      "Name": "email_verified",
      "Value": "true"
    }
  ],
  "MessageAction": "SUPPRESS"
}')

# RESPONSEからUserIDを取得
USER_ID=$(echo $RESPONSE | jq -r '.User.Username')

echo "User ID: $USER_ID"

# 抽出した各種IDを含む.env.localファイルを/appディレクトリ(ルートディレクトリ)に作成
cat <<EOF > /app/.env.local
NEXT_PUBLIC_MOTO_USER_POOL_ID=$USER_POOL_ID
NEXT_PUBLIC_MOTO_CLIENT_ID=$USER_POOL_CLIENT_ID
NEXT_PUBLIC_MOTO_ENDPOINT=http://127.0.0.1:5000
USER_ID=$USER_ID
USER_NAME=test123@example.com
USER_PASSWORD=Test@1234
EOF

echo ".env.local file created with the necessary environment variables in /app directory."


# ユーザーのパスワードを変更
RESPONSE=$(curl -s -X POST http://moto:5000/ \
-H 'Content-Type: application/x-amz-json-1.1' \
-H 'X-Amz-Target: AWSCognitoIdentityProviderService.AdminSetUserPassword' \
-H 'X-Amz-Date: 20240227T000000Z' \
-d '{
  "UserPoolId": "'"$USER_POOL_ID"'",
  "Username": "test123@example.com",
  "Password": "Test@1234",
  "Permanent": true
}')

echo "User password set to permanent for user: test123@example.com"

docker-compose.ymlの設定

appとしてフロントエンドの記載をしていますが、Dockerを使わずに起動させることもできます
※初回起動が遅いので、ローカル起動を推奨

docker-compose.yml
services:
  moto:
    image: motoserver/moto:latest
    ports:
      - "5000:5000"
    command: >
      -H 0.0.0.0
    environment:
      - MOTO_PORT=5000

  aws_mock_init:
    build:
      context: ./aws_mock
    volumes:
      - .:/app
    depends_on:
      - moto
    entrypoint: ["/bin/sh", "-c", "sleep 5 && ./aws_mock/init.sh"]

  # フロントエンドをローカル起動するなら以下のappは不要です
  app:
    build:
      context: .
    ports:
      - "3000:3000"
    volumes:
      - .:/app
      - /app/node_modules
    environment:
      - WATCHPACK_POLLING=true
    command: npm run dev
    depends_on:
      - moto
      - aws_mock_init

Dockerで実行

VSCodeなどのエディターでRun All Service実行(VSCodeの場合:拡張機能のDockerが必要)
一応コマンド例を掲載しておきます

#1. サービスのビルドと起動
docker-compose up --build
#2. バックグラウンド(デタッチド)で起動
docker-compose up -d
#3. サービスの停止
docker-compose down
#4. サービスの再ビルド
docker-compose build
#5. 特定サービスのみ起動(例: app)
docker-compose up moto
#6. ログの確認
docker-compose logs
#7. 特定サービスのログ確認(例: moto)
docker-compose logs moto

Dockerでmotoサーバーが起動している状態で、aws_mock_initを実行すると、
.env.localファイル内に仮想環境のCognito接続用の各種IDが記載されます
ログイン用のIDとパスワードも記載してありますので、検証時にお使いください

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?