AWSコンソールだけでCognito + API Gateway + Lambda の認証付きAPIを構築する手順【SAM版との比較付き / 新UI対応】

AWS Basic
スポンサーリンク
スポンサーリンク
  1. はじめに
  2. Cognito 新UIで戸惑いやすいポイント(先読み)
  3. キーワード解説
  4. 前提条件
  5. 使用するAWSサービス
  6. 全体の作業順序
  7. ① Cognito User Pool を作成する
    1. 1-1. アプリケーションを定義する
    2. 1-2. オプションを設定する
    3. 1-3. リターン URL(スキップ)
    4. 控えておく情報
  8. ② テスト用アプリクライアントを作成する
    1. 2-1. アプリケーションを定義する
    2. 2-2. リターン URL(スキップ)
    3. 2-3. Client secret configuration
    4. 2-4. 認証フローを確認する
  9. ③ Lambda 関数を作成する
    1. コードの入力
  10. ④ API Gateway REST API を作成する
    1. 4-1. API タイプの選択
    2. 4-2. リソース /hello を作成する
    3. 4-3. リソース /profile を作成する
    4. 4-4. Cognito Authorizer を作成する
    5. 4-5. /profile GET メソッドに Authorizer を設定する
    6. 4-6. API をデプロイする
  11. ⑤ テストユーザーを作成する
  12. ⑥ 動作テスト
    1. テスト1: 公開エンドポイント(/hello)→ 200
    2. テスト2: 未認証でプライベートエンドポイント(/profile)→ 401
    3. テスト3: IDトークンを取得する
    4. テスト4: 認証ありでプライベートエンドポイント(/profile)→ 200
  13. ⑦ リソースの削除
    1. 1. API Gateway を削除する
    2. 2. Lambda 関数を削除する
    3. 3. Cognito User Pool を削除する
    4. 4. IAM ロールを削除する(任意)
    5. 5. CloudWatch Logs のロググループを削除する(任意)
  14. SAMとの対比
  15. トラブルシューティング
  16. まとめ
  17. コンソール版とSAM版を比較してみる
  18. 関連記事

はじめに

「ログインしたユーザーだけが使えるAPIを作りたい」——そんな要件を、Amazon Cognito + API Gateway + Lambda はサーバー側の認証コードをほぼ書かずに実現します。

この記事では、AWSコンソールのみを使って、以下の構成の認証付き REST API をゼロから構築するハンズオンを紹介します。

クライアント(curl)
  │
  ├─ GET /hello  → 認証不要 → Lambda → 200 OK
  │
  └─ GET /profile
        ├─ Authorizationヘッダーなし → API Gateway が 401 を返す(Lambda は呼ばれない)
        └─ Authorization: <IDトークン>
              → Cognito Authorizer が JWT を検証(Lambda 不要)
              → Lambda → email / sub を返す → 200 OK

このハンズオンで体験できること:

  • Amazon Cognito User Pool によるユーザー管理と JWT 発行
  • API Gateway の Cognito Authorizer を使ったエンドポイントごとの認証制御
  • Lambda 側で認証コードを書かずに claims(ユーザー情報)を取得するパターン
  • 新UI対応 — Cognito コンソールの大幅変更点と、操作でハマりやすいポイント

この記事は SAM版ハンズオン の比較記事です。
コンソール操作でCognitoとAPI Gatewayの連携を視覚的に学び、SAMと何が違うのかを比較したい方向けです。


Amazon検索[本 AWS 開発]

スポンサーリンク

Cognito 新UIで戸惑いやすいポイント(先読み)

操作を始める前に、2026年時点の新UIで戸惑いやすい変更点を把握しておきましょう。

変更点旧UI新UI(現在)
User Pool 作成の入口「ユーザープールを作成」ボタンから**「アプリケーションを作成」**ボタンから(名称が変わった)
作成の粒度User Pool → App Client を別々に作成1ページのウィザードで User Pool とクライアントを同時作成
クライアントシークレットデフォルトなし「従来のウェブアプリケーション」を選ぶとシークレット必須になる
User Pool 名指定した名前がそのまま付くアプリ名の前に User pool - が自動で付く(例: User pool - MyWebApp
クライアント ID の場所概要ページに表示左サイドバー → 「アプリケーション」から辿る

最大のハマりポイント(クライアントシークレット):
新UIの「アプリケーションを作成」で「従来のウェブアプリケーション」を選ぶと、クライアントシークレットが自動で付与されます。シークレットありのクライアントで initiate-auth を実行すると SECRET_HASH was not received エラーが出て詰まります。
このハンズオンでは②の手順でシークレットなしのクライアントを別途作成します。


スポンサーリンク

キーワード解説

用語意味
User PoolCognitoのユーザーディレクトリ。ユーザー登録・認証・JWT発行を一手に担う
User Pool Clientアプリが User Pool に接続するための設定。Client ID を持つ
IDトークンログイン成功時に Cognito が発行する JWT。email / sub などのユーザー情報を含む
Cognito AuthorizerAPI Gateway が IDトークンを検証する認可機能。Lambdaコードが不要で動作する
claimsJWT ペイロードに含まれる情報(email / sub / token_use など)
FORCE_CHANGE_PASSWORD管理者作成ユーザーの初期状態。この状態では initiate-auth がトークンを返さない

前提条件

ツール確認コマンド備考
AWSアカウントIAMユーザーまたはルートユーザー
AWS CLI v2(テスト用)aws --versionIDトークン取得・ユーザー作成に使用

AWS CLI がない場合は、テスト操作に AWSコンソールの CloudShell を代用できます(後述)。


使用するAWSサービス

サービス役割料金
Amazon Cognitoユーザー管理・認証・JWT発行月5万MAU(月間アクティブユーザー)まで無料
API GatewayREST API のエンドポイント管理・認可月100万リクエストまで無料(無料期間12ヶ月)
LambdaAPIのビジネスロジック(1関数)月100万リクエスト・400,000 GB-秒まで無料
IAMLambda の実行権限管理無料
CloudWatch LogsLambda の実行ログ月5GBまで無料

全体の作業順序

① Cognito User Pool を作成する(新UI対応)
      ↓
② テスト用アプリクライアントを作成する(シークレットなし)
      ↓
③ Lambda 関数を作成する
      ↓
④ API Gateway REST API を作成する
  (/hello・/profile エンドポイント + Cognito Authorizer 設定)
      ↓
⑤ テストユーザーを作成する
      ↓
⑥ 動作テスト(401確認 → JWTトークン取得 → 認証成功)
      ↓
⑦ リソースの削除

① Cognito User Pool を作成する

AWSコンソール → Cognito → 「アプリケーションを作成」

新UIの注意:
旧UIにあった「ユーザープールを作成」ボタンは廃止されています。現在は「アプリケーションを作成」からウィザードで User Pool とクライアントをまとめて作成します。

1-1. アプリケーションを定義する

設定項目
アプリケーションタイプ従来のウェブアプリケーション
アプリケーション名MyWebApp

1-2. オプションを設定する

設定項目
サインイン識別子のオプションメールアドレス にチェック(電話番号・ユーザー名はチェック不要)
自己登録を有効チェックする(デフォルトでチェック済み)
サインアップのための必須属性空欄のまま(属性を選択しない)

サインイン識別子は作成後に変更不可。 「メールアドレス」のみ選択しておくことを推奨します。

1-3. リターン URL(スキップ)

「リターン URL を追加」は入力不要(今回はマネージドログインページを使わないため)。

画面下部の「ユーザーディレクトリを作成する」をクリック。

控えておく情報

作成後、User Pool の概要ページが開きます。

  • ユーザープール ID(例: ap-northeast-1_XXXXXXXX
    → 概要ページの「ユーザープール情報」欄に表示
  • クライアント ID(例: XXXXXXXXXXXXXXXXXXXXXXXXXX
    → 左サイドバー「アプリケーション」→「アプリケーションクライアント」→ MyWebApp をクリック → 「クライアント ID」欄

注意: 概要ページの「レコメンデーション」欄にも MyWebApp のリンクが表示されますが、これは Quick Setup ガイドへの誘導です。クライアント ID は左サイドバーから辿ってください。

User Pool 名について:
新UIでは、アプリ名の前に User pool - が自動で付きます(例: User pool - MyWebApp)。以降の手順では「作成した User Pool」と表記します。


② テスト用アプリクライアントを作成する

新UIの「アプリケーションを作成」で自動作成された MyWebApp クライアントにはクライアントシークレットが自動付与されています。シークレットありのクライアントで CLI から initiate-auth を実行すると SECRET_HASH was not received エラーが出ます。

そのため、シークレットなし・ALLOW_USER_PASSWORD_AUTH 有効の新しいクライアントを別途作成します。

Cognito → 作成した User Pool → 左サイドバー「アプリケーション」→「アプリケーションクライアント」→「アプリケーションクライアントを作成」

2-1. アプリケーションを定義する

設定項目
アプリケーションタイプシングルページアプリケーション (SPA)
アプリケーション名MyWebAppClient

「SPA」を選ぶ理由:
新UIでは「従来のウェブアプリケーション」を選ぶとクライアントシークレットが必須になります。「SPA」を選ぶとシークレットなしで作成できます。CLI テスト目的ではこちらを使います。

2-2. リターン URL(スキップ)

入力不要。

2-3. Client secret configuration

SPA を選択した場合、この欄は表示されません(シークレットなしで自動確定)。

アプリケーションクライアントを作成」をクリック。

2-4. 認証フローを確認する

作成後、MyWebAppClient をクリックして詳細画面を開きます。

「認証フロー」セクションに ALLOW_USER_PASSWORD_AUTH が含まれていることを確認します。

含まれていない場合は「編集」→「ALLOW_USER_PASSWORD_AUTH」にチェック → 「変更を保存」。

ALLOW_USER_PASSWORD_AUTH とは:
CLI から username と password を直接指定して認証する「ユーザーパスワード認証」フローです。テスト用に有効化します(本番環境では SRP フローが推奨)。

控えておく情報(更新):

  • クライアント ID → 新しく作成した MyWebAppClient のクライアント ID を使う(① の MyWebApp のクライアント ID は使わない)

③ Lambda 関数を作成する

AWSコンソール → Lambda → 「関数の作成」

設定項目
作成方法一から作成
関数名CognitoApiFunction
ランタイムPython 3.12
アーキテクチャx86_64
実行ロール「基本的な Lambda アクセス権限で新しいロールを作成」(デフォルトのまま)

「関数の作成」をクリック。

コードの入力

関数ページ → 「コード」タブ → lambda_function.py を開いて既存の内容を全て置き換えて以下を貼り付けます。

import json


def lambda_handler(event, context):
    resource = event.get("resource", "/")  # API Gateway プロキシ統合: リクエストパスが "resource" に入る

    if resource == "/hello":
        return {
            "statusCode": 200,
            "headers": {"Content-Type": "application/json"},
            "body": json.dumps({"message": "Hello! This is a public endpoint."}),
        }

    if resource == "/profile":
        # event["requestContext"]["authorizer"]["claims"] に JWT ペイロードが格納される
        claims = (
            event.get("requestContext", {})
            .get("authorizer", {})
            .get("claims", {})
        )
        return {
            "statusCode": 200,
            "headers": {"Content-Type": "application/json"},
            "body": json.dumps(
                {
                    "message": "認証成功",
                    "email": claims.get("email"),
                    "sub": claims.get("sub"),          # Cognito が生成したユーザーの一意 ID
                    "token_use": claims.get("token_use"),  # "id" が返る(IDトークンを使っているため)
                },
                ensure_ascii=False,
            ),
        }

    return {
        "statusCode": 404,
        "headers": {"Content-Type": "application/json"},
        "body": json.dumps({"message": "Not Found"}),
    }

Deploy」ボタンをクリックしてコードを保存します。

Lambda 側で認証コードが不要な理由:
API Gateway の Cognito Authorizer が IDトークン(JWT)の検証をすべて担っています。Lambda が呼ばれた時点では認証済みであることが保証されており、検証済みの claims だけを受け取って使えばよい設計です。


④ API Gateway REST API を作成する

AWSコンソール → API Gateway → 「APIを作成」

4-1. API タイプの選択

「REST API」の「構築」をクリック。

設定項目
API タイプREST API(「プライベート」ではない方)
新しい API の作成「新しい API」
API 名CognitoSampleApi
エンドポイントタイプリージョン

APIを作成」をクリック。


4-2. リソース /hello を作成する

左のリソースツリーで /(ルート)を選択 → 「リソースを作成」ボタンをクリック

設定項目
リソースパス(親パス)/(変更不要)
リソース名hello

新UIの注意点:
「リソースパス」はリソースを作成する親パスの選択/ = ルート配下という意味)です。/hello と入力する欄ではありません。「リソース名」に hello と入力するだけで OK です。

リソースを作成」をクリック。

/hello を選択した状態で → 「メソッドを作成」→ メソッドタイプ GET を選択

設定項目
統合タイプLambda 関数
Lambda プロキシ統合の使用チェックする
Lambda 関数CognitoApiFunction

「保存」→「OK」(Lambda 呼び出し権限の追加確認)。


4-3. リソース /profile を作成する

左のリソースツリーで /(ルート)を選択 → 「リソースを作成

設定項目
リソースパス(親パス)/(変更不要)
リソース名profile

リソースを作成」をクリック。

/profile を選択した状態で → 「メソッドを作成」→ メソッドタイプ GET を選択

設定項目
統合タイプLambda 関数
Lambda プロキシ統合の使用チェックする
Lambda 関数CognitoApiFunction

「保存」をクリック。


4-4. Cognito Authorizer を作成する

左側メニューの「オーソライザー」→「オーソライザーを作成

設定項目
オーソライザー名CognitoAuthorizer
オーソライザーのタイプCognito
Cognito ユーザープール(リージョン)ap-northeast-1(変更不要)
Cognito ユーザープール(検索欄)① で作成した User Pool を選択(例: User pool - MyWebApp
トークンのソースAuthorization必ず入力する
トークンの検証(オプション)空欄のまま

新UIの注意点:
「トークンのソース」はデフォルトで空欄になっています。Authorization と入力しないと動作しません。入力を忘れると全リクエストが 401 になります。

オーソライザーを作成」をクリック。

動作確認:

「オーソライザーのテスト」→ テスト用トークン欄に適当な文字を入力 → 「テスト」→ 401 が返れば正常(正しいトークンがないため 401 が正解)。


4-5. /profile GET メソッドに Authorizer を設定する

左のリソースツリーで /profileGET を選択 → 「メソッドリクエストの設定」セクションの「編集」ボタンをクリック

「認可」ドロップダウンを開き、Cognito ユーザープールオーソライザー の配下にある CognitoAuthorizer を選択 → 「保存

新UIの注意点:
選択肢は なし / AWS IAM / Cognito ユーザープールオーソライザー(カテゴリ)→ CognitoAuthorizer の階層構造になっています。
CognitoAuthorizer はカテゴリ名ではなく、その下にインデントされた項目を選んでください。

ポイント:
/hello GET には Authorizer を設定しない(認証不要)。
/profile GET にのみ CognitoAuthorizer を設定することで、エンドポイントごとに認証要件を分けます。


4-6. API をデプロイする

「アクション」→「API のデプロイ」

設定項目
デプロイされるステージ「新しいステージ」
ステージ名Prod

「デプロイ」をクリック。

控えておく情報:

「Prod ステージエディター」に表示される URL の呼び出し(例: https://XXXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/Prod)をコピーします。


⑤ テストユーザーを作成する

Cognito → 作成した User Pool → 左サイドバー「ユーザー管理」→「ユーザー」→「ユーザーを作成」

設定項目
招待メッセージ「招待を送信しない」 を選択
E メールアドレスtest@example.com
仮パスワード「パスワードの設定」 を選択
パスワードTestPass1!

パスワードポリシー(新UIのデフォルト):
最小8文字 / 数字・小文字・大文字・特殊文字をそれぞれ1文字以上含むこと。
TestPass1 は特殊文字がないため不可。TestPass1! を使ってください。

ユーザーを作成」をクリック。

ユーザーの「確認ステータス」列に 「パスワードを強制的に変更」 と表示されます(= FORCE_CHANGE_PASSWORD 状態)。
この状態で initiate-auth を実行してもトークンが返らず NEW_PASSWORD_REQUIRED チャレンジが返されます。
次の CLI コマンドで永続パスワードを設定して「確認済み」(CONFIRMED)に変更します。

CLI で永続パスワードを設定する:

方法 A: CloudShell(コンソール版ハンズオンにおすすめ)

AWSコンソール画面下部の「CloudShell」をクリックして起動します。コンソールと同じ認証情報が自動で使われるため追加設定は不要。

aws cognito-idp admin-set-user-password \
  --user-pool-id ap-northeast-1_XXXXXXXX \
  --username test@example.com \
  --password 'TestPass1!' \
  --permanent \
  --region ap-northeast-1

CloudShell は Linux シェルのため \ で改行します。! を含むパスワードはシングルクォート '...' で囲んでください(ダブルクォートだと bash がエラーになる場合があります)。

方法 B: ローカルの AWS CLI(コマンドプロンプト)

aws cognito-idp admin-set-user-password ^
  --user-pool-id ap-northeast-1_XXXXXXXX ^
  --username test@example.com ^
  --password TestPass1! ^
  --permanent ^
  --region ap-northeast-1

ap-northeast-1_XXXXXXXX を ① で控えたユーザープール ID に置き換えてください。

コマンドが出力なしで返れば成功です。コンソールでユーザーの「確認ステータス」が**「確認済み」**に変わったことを確認してください。


⑥ 動作テスト

テスト1: 公開エンドポイント(/hello)→ 200

curl https://XXXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/Prod/hello

期待するレスポンス:

{"message": "Hello! This is a public endpoint."}

テスト2: 未認証でプライベートエンドポイント(/profile)→ 401

curl https://XXXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/Prod/profile

期待するレスポンス(API Gateway が返す。Lambda は呼ばれていない):

{"message": "Unauthorized"}

テスト3: IDトークンを取得する

aws cognito-idp initiate-auth ^
  --auth-flow USER_PASSWORD_AUTH ^
  --auth-parameters "USERNAME=test@example.com,PASSWORD=TestPass1!" ^
  --client-id XXXXXXXXXXXXXXXXXXXXXXXXXX ^
  --region ap-northeast-1

XXXXXXXXXXXXXXXXXXXXXXXXXX② で控えた MyWebAppClient のクライアント ID に置き換えてください(① の MyWebApp のクライアント ID ではありません)。

レスポンス例(抜粋):

{
    "AuthenticationResult": {
        "AccessToken": "eyJra...",
        "ExpiresIn": 3600,
        "TokenType": "Bearer",
        "RefreshToken": "eyJjb...",
        "IdToken": "eyJra..."
    }
}

IdToken の値をコピーしておきます(次のテストで使用)。

IdToken と AccessToken の違い:

トークン用途含まれる情報
IdTokenユーザー認証(今回使用)email / sub など
AccessTokenCognito API へのアクセスsub / scope など

API Gateway の Cognito Authorizer に渡すのは IdToken。AccessToken を渡しても 403 になります。


テスト4: 認証ありでプライベートエンドポイント(/profile)→ 200

IdToken は非常に長いため、変数に格納してから実行します。

方法 A: CloudShell(おすすめ)

TOKEN="eyJra...(IdToken全体を貼り付ける)"
curl -H "Authorization: $TOKEN" https://XXXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/Prod/profile

方法 B: Windows CMD(変数使用)

set TOKEN=eyJra...(IdToken全体を貼り付ける)
curl -H "Authorization: %TOKEN%" https://XXXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/Prod/profile

重要: CMD では変数展開に %TOKEN% を使います。$TOKEN(bash 構文)を CMD で使うと文字列 $TOKEN がそのまま送られ 401 になります。
また Bearer プレフィックスは不要です。raw JWT をそのまま Authorization ヘッダーに指定してください。

期待するレスポンス:

{
  "message": "認証成功",
  "email": "test@example.com",
  "sub": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "token_use": "id"
}

sub は Cognito が自動生成したユーザーの一意 ID です。
token_use: "id" は IDトークンを使っていることを示します。


⑦ リソースの削除

課金を止めるために、ハンズオン完了後は必ずリソースを削除してください。

1. API Gateway を削除する

API Gateway → APIs → CognitoSampleApi を選択 → 「アクション」→「APIの削除」


2. Lambda 関数を削除する

Lambda → 関数 → CognitoApiFunction を選択 → 「アクション」→「削除」


3. Cognito User Pool を削除する

Cognito → 作成した User Pool → 右上の「ユーザープールを削除」ボタン → ユーザープール名を入力 → 「削除」

ユーザーとアプリクライアントも一緒に削除されます。


4. IAM ロールを削除する(任意)

IAM → ロール → CognitoApiFunction-role-XXXX を検索して削除


5. CloudWatch Logs のロググループを削除する(任意)

CloudWatch → ロググループ → /aws/lambda/CognitoApiFunction → 削除


SAMとの対比

SAMの記述コンソールでやること
AWS::Cognito::UserPoolCognito → 「アプリケーションを作成」で User Pool を作成
AWS::Cognito::UserPoolClient(シークレットなし)② の手順で SPA タイプのクライアント MyWebAppClient を別途作成
Auth.DefaultAuthorizer: CognitoAuthorizerAPI Gateway → オーソライザーを作成して /profile GET に適用
Auth: Authorizer: NONE(/hello 側)/hello GET には Authorizer を設定しない
sam deleteAPI Gateway / Lambda / Cognito / IAM ロール / ロググループを個別に削除

トラブルシューティング

症状原因対処
initiate-authClient is configured with secret but SECRET_HASH was not received① で自動作成された MyWebApp(シークレットあり)のクライアント ID を使っている② の手順で MyWebAppClient(シークレットなし)を作成し、そちらの Client ID を使う
initiate-authNotAuthorizedExceptionユーザーが FORCE_CHANGE_PASSWORD 状態admin-set-user-password --permanent で CONFIRMED に変更する
initiate-authInvalidParameterExceptionALLOW_USER_PASSWORD_AUTH が無効User Pool Client の認証フロー設定を確認する
/profile に IDトークンを送っても 401Bearer TOKEN 形式で送っているBearer を外し raw JWT(eyJra...)をそのまま Authorization ヘッダーに指定する
/profile に IDトークンを送っても 403トークンが期限切れ(1時間で失効)initiate-auth で新しいトークンを取得し直す
/profile に IDトークンを送っても 403AccessToken を使っている(IdToken ではない)AuthenticationResult.IdToken を使用しているか確認する
Lambda の claims が空/profile GET に Authorizer が設定されていない④ 4-5 の手順で CognitoAuthorizer を設定し直す
Lambda の resource/ になるLambda プロキシ統合が有効になっていないGET メソッドで「Lambda プロキシ統合の使用」をチェックする
Authorizer テストが 500 になるUser Pool が選択されていない、またはトークンのソースが空オーソライザーの設定を確認し Authorization を入力し直す

まとめ

今回のハンズオンで体験できたこと:

確認項目内容
Cognito User Poolユーザー作成・JWT 発行・パスワードポリシーを新UIで設定
Cognito AuthorizerAPI Gateway がIDトークンを自動検証 → Lambda は認証コード不要
エンドポイント別認証制御/hello(認証なし)と /profile(認証必須)を同じ Lambda で分岐
FORCE_CHANGE_PASSWORD 対処admin-set-user-password --permanent で CONFIRMED 状態に変更
新UI操作「アプリケーションを作成」→ SPA クライアントの追加作成 → Authorizer のトークンソース設定

コンソール版とSAM版を比較してみる

コンソールでCognitoとAPI Gatewayの連携を理解したら、SAMで同じ構成をコードで定義することで「SAMが何を自動化しているか」が明確になります。DefaultAuthorizer によるワンライン認証設定や、ALLOW_USER_PASSWORD_AUTH の自動有効化など、コンソールでの手動操作がコードに対応しています。


関連記事

Amazon検索[本 AWS 開発]

コメント