<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>JWT - CayTech Lab</title>
	<atom:link href="https://caymezon.com/tag/jwt/feed/" rel="self" type="application/rss+xml" />
	<link>https://caymezon.com</link>
	<description></description>
	<lastBuildDate>Sun, 01 Mar 2026 08:50:35 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://caymezon.com/wp-content/uploads/2026/01/cropped-CayTechLab-32x32.jpg</url>
	<title>JWT - CayTech Lab</title>
	<link>https://caymezon.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<atom:link rel='hub' href='https://caymezon.com/?pushpress=hub'/>
	<item>
		<title>AWSコンソールだけでCognito + API Gateway + Lambda の認証付きAPIを構築する手順【SAM版との比較付き / 新UI対応】</title>
		<link>https://caymezon.com/aws-handson-console-cognito-api-gateway-lambda/</link>
					<comments>https://caymezon.com/aws-handson-console-cognito-api-gateway-lambda/#respond</comments>
		
		<dc:creator><![CDATA[caymezon]]></dc:creator>
		<pubDate>Sun, 01 Mar 2026 08:50:35 +0000</pubDate>
				<category><![CDATA[AWS Basic]]></category>
		<category><![CDATA[Cloud & Infra]]></category>
		<category><![CDATA[APIGateway]]></category>
		<category><![CDATA[AWS]]></category>
		<category><![CDATA[Cognito]]></category>
		<category><![CDATA[JWT]]></category>
		<category><![CDATA[Lambda]]></category>
		<category><![CDATA[REST API]]></category>
		<category><![CDATA[SAM比較]]></category>
		<category><![CDATA[サーバーレス]]></category>
		<category><![CDATA[ハンズオン]]></category>
		<category><![CDATA[初心者]]></category>
		<category><![CDATA[新UI]]></category>
		<category><![CDATA[認証]]></category>
		<guid isPermaLink="false">https://caymezon.com/?p=20237</guid>

					<description><![CDATA[<p>目次 はじめにCognito 新UIで戸惑いやすいポイント（先読み）キーワード解説前提条件使用するAWSサービス全体の作業順序① Cognito User Pool を作成する1-1. アプリケーションを定義する1-2. [&#8230;]</p>
<p>The post <a href="https://caymezon.com/aws-handson-console-cognito-api-gateway-lambda/">AWSコンソールだけでCognito + API Gateway + Lambda の認証付きAPIを構築する手順【SAM版との比較付き / 新UI対応】</a> first appeared on <a href="https://caymezon.com">CayTech Lab</a>.</p>]]></description>
										<content:encoded><![CDATA[<div id="toc" class="toc tnt-number toc-center tnt-number border-element"><input type="checkbox" class="toc-checkbox" id="toc-checkbox-2" checked><label class="toc-title" for="toc-checkbox-2">目次</label>
    <div class="toc-content">
    <ol class="toc-list open"><li><a href="#toc1" tabindex="0">はじめに</a></li><li><a href="#toc2" tabindex="0">Cognito 新UIで戸惑いやすいポイント（先読み）</a></li><li><a href="#toc3" tabindex="0">キーワード解説</a></li><li><a href="#toc4" tabindex="0">前提条件</a></li><li><a href="#toc5" tabindex="0">使用するAWSサービス</a></li><li><a href="#toc6" tabindex="0">全体の作業順序</a></li><li><a href="#toc7" tabindex="0">① Cognito User Pool を作成する</a><ol><li><a href="#toc8" tabindex="0">1-1. アプリケーションを定義する</a></li><li><a href="#toc9" tabindex="0">1-2. オプションを設定する</a></li><li><a href="#toc10" tabindex="0">1-3. リターン URL（スキップ）</a></li><li><a href="#toc11" tabindex="0">控えておく情報</a></li></ol></li><li><a href="#toc12" tabindex="0">② テスト用アプリクライアントを作成する</a><ol><li><a href="#toc13" tabindex="0">2-1. アプリケーションを定義する</a></li><li><a href="#toc14" tabindex="0">2-2. リターン URL（スキップ）</a></li><li><a href="#toc15" tabindex="0">2-3. Client secret configuration</a></li><li><a href="#toc16" tabindex="0">2-4. 認証フローを確認する</a></li></ol></li><li><a href="#toc17" tabindex="0">③ Lambda 関数を作成する</a><ol><li><a href="#toc18" tabindex="0">コードの入力</a></li></ol></li><li><a href="#toc19" tabindex="0">④ API Gateway REST API を作成する</a><ol><li><a href="#toc20" tabindex="0">4-1. API タイプの選択</a></li><li><a href="#toc21" tabindex="0">4-2. リソース /hello を作成する</a></li><li><a href="#toc22" tabindex="0">4-3. リソース /profile を作成する</a></li><li><a href="#toc23" tabindex="0">4-4. Cognito Authorizer を作成する</a></li><li><a href="#toc24" tabindex="0">4-5. /profile GET メソッドに Authorizer を設定する</a></li><li><a href="#toc25" tabindex="0">4-6. API をデプロイする</a></li></ol></li><li><a href="#toc26" tabindex="0">⑤ テストユーザーを作成する</a></li><li><a href="#toc27" tabindex="0">⑥ 動作テスト</a><ol><li><a href="#toc28" tabindex="0">テスト1: 公開エンドポイント（/hello）→ 200</a></li><li><a href="#toc29" tabindex="0">テスト2: 未認証でプライベートエンドポイント（/profile）→ 401</a></li><li><a href="#toc30" tabindex="0">テスト3: IDトークンを取得する</a></li><li><a href="#toc31" tabindex="0">テスト4: 認証ありでプライベートエンドポイント（/profile）→ 200</a></li></ol></li><li><a href="#toc32" tabindex="0">⑦ リソースの削除</a><ol><li><a href="#toc33" tabindex="0">1. API Gateway を削除する</a></li><li><a href="#toc34" tabindex="0">2. Lambda 関数を削除する</a></li><li><a href="#toc35" tabindex="0">3. Cognito User Pool を削除する</a></li><li><a href="#toc36" tabindex="0">4. IAM ロールを削除する（任意）</a></li><li><a href="#toc37" tabindex="0">5. CloudWatch Logs のロググループを削除する（任意）</a></li></ol></li><li><a href="#toc38" tabindex="0">SAMとの対比</a></li><li><a href="#toc39" tabindex="0">トラブルシューティング</a></li><li><a href="#toc40" tabindex="0">まとめ</a></li><li><a href="#toc41" tabindex="0">コンソール版とSAM版を比較してみる</a></li><li><a href="#toc42" tabindex="0">関連記事</a></li></ol>
    </div>
  </div>

<h2><span id="toc1">はじめに</span></h2>
<p>「ログインしたユーザーだけが使えるAPIを作りたい」——そんな要件を、<strong>Amazon Cognito + API Gateway + Lambda</strong> はサーバー側の認証コードをほぼ書かずに実現します。</p>
<p>この記事では、<strong>AWSコンソールのみ</strong>を使って、以下の構成の認証付き REST API をゼロから構築するハンズオンを紹介します。</p>
<pre><code class="language-plaintext">クライアント（curl）
  │
  ├─ GET /hello  → 認証不要 → Lambda → 200 OK
  │
  └─ GET /profile
        ├─ Authorizationヘッダーなし → API Gateway が 401 を返す（Lambda は呼ばれない）
        └─ Authorization: &lt;IDトークン&gt;
              → Cognito Authorizer が JWT を検証（Lambda 不要）
              → Lambda → email / sub を返す → 200 OK</code></pre>
<p><strong>このハンズオンで体験できること：</strong></p>
<ul>
<li>Amazon Cognito <strong>User Pool</strong> によるユーザー管理と JWT 発行</li>
<li>API Gateway の <strong>Cognito Authorizer</strong> を使ったエンドポイントごとの認証制御</li>
<li>Lambda 側で認証コードを書かずに <code>claims</code>（ユーザー情報）を取得するパターン</li>
<li><strong>新UI対応</strong> — Cognito コンソールの大幅変更点と、操作でハマりやすいポイント</li>
</ul>
<hr>
<blockquote>
<p><strong>この記事は <a href="#">SAM版ハンズオン</a> の比較記事です。</strong><br />コンソール操作でCognitoとAPI Gatewayの連携を視覚的に学び、SAMと何が違うのかを比較したい方向けです。</p>
</blockquote>
<hr>
<p><a rel="nofollow" href="//af.moshimo.com/af/c/click?a_id=1384942&p_id=170&pc_id=185&pl_id=4062&url=https%3A%2F%2Fwww.amazon.co.jp%2Fs%3Fk%3D%25E6%259C%25AC%2BAWS%2B%25E9%2596%258B%25E7%2599%25BA%26__mk_ja_JP%3D%25E3%2582%25AB%25E3%2582%25BF%25E3%2582%25AB%25E3%2583%258A%26crid%3D1DE63UBHFOR4K%26sprefix%3D%25E6%259C%25AC%2Baws%2B%25E9%2596%258B%25E7%2599%25BA%252Caps%252C167%26ref%3Dnb_sb_noss" referrerpolicy="no-referrer-when-downgrade" attributionsrc>Amazon検索[本 AWS 開発]</a><img decoding="async" src="//i.moshimo.com/af/i/impression?a_id=1384942&p_id=170&pc_id=185&pl_id=4062" width="1" height="1" style="border:none;" alt="" loading="lazy"></p>
<p><!-- START MoshimoAffiliateEasyLink --><script type="text/javascript">(function(b,c,f,g,a,d,e){b.MoshimoAffiliateObject=a;b[a]=b[a]||function(){arguments.currentScript=c.currentScript||c.scripts[c.scripts.length-2];(b[a].q=b[a].q||[]).push(arguments)};c.getElementById(a)||(d=c.createElement(f),d.src=g,d.id=a,e=c.getElementsByTagName("body")[0],e.appendChild(d))})(window,document,"script","//dn.msmstatic.com/site/cardlink/bundle.js?20220329","msmaflink");msmaflink({"n":"AWSの基本・仕組み・重要用語が全部わかる教科書 (見るだけ図解)","b":"SBクリエイティブ","t":"","d":"https:\/\/m.media-amazon.com","c_p":"\/images\/I","p":["\/51DEDQXj6oL._SL500_.jpg","\/41F589smNwL._SL500_.jpg","\/41R6f9yyCWL._SL500_.jpg","\/41HqWQ9BvmL._SL500_.jpg","\/41p8p0ZU79L._SL500_.jpg","\/41qLC-fndBL._SL500_.jpg","\/41fcLv9VT5L._SL500_.jpg","\/51lRvCsvHqL._SL500_.jpg"],"u":{"u":"https:\/\/www.amazon.co.jp\/dp\/4815607850","t":"amazon","r_v":""},"v":"2.1","b_l":[{"id":1,"u_tx":"Amazonで見る","u_bc":"#f79256","u_url":"https:\/\/www.amazon.co.jp\/dp\/4815607850","a_id":1384942,"p_id":170,"pl_id":27060,"pc_id":185,"s_n":"amazon","u_so":1},{"id":2,"u_tx":"楽天市場で見る","u_bc":"#f76956","u_url":"https:\/\/search.rakuten.co.jp\/search\/mall\/AWS%E3%81%AE%E5%9F%BA%E6%9C%AC%E3%83%BB%E4%BB%95%E7%B5%84%E3%81%BF%E3%83%BB%E9%87%8D%E8%A6%81%E7%94%A8%E8%AA%9E%E3%81%8C%E5%85%A8%E9%83%A8%E3%82%8F%E3%81%8B%E3%82%8B%E6%95%99%E7%A7%91%E6%9B%B8%20(%E8%A6%8B%E3%82%8B%E3%81%A0%E3%81%91%E5%9B%B3%E8%A7%A3)\/","a_id":1384917,"p_id":54,"pl_id":27059,"pc_id":54,"s_n":"rakuten","u_so":2},{"id":3,"u_tx":"Yahoo!ショッピングで見る","u_bc":"#66a7ff","u_url":"https:\/\/shopping.yahoo.co.jp\/search?first=1\u0026p=AWS%E3%81%AE%E5%9F%BA%E6%9C%AC%E3%83%BB%E4%BB%95%E7%B5%84%E3%81%BF%E3%83%BB%E9%87%8D%E8%A6%81%E7%94%A8%E8%AA%9E%E3%81%8C%E5%85%A8%E9%83%A8%E3%82%8F%E3%81%8B%E3%82%8B%E6%95%99%E7%A7%91%E6%9B%B8%20(%E8%A6%8B%E3%82%8B%E3%81%A0%E3%81%91%E5%9B%B3%E8%A7%A3)","a_id":1466950,"p_id":1225,"pl_id":27061,"pc_id":1925,"s_n":"yahoo","u_so":3}],"eid":"eaCUB","s":"s"});</script></p>
<div id="msmaflink-eaCUB">リンク</div>
<p><!-- MoshimoAffiliateEasyLink END --></p>
<h2><span id="toc2">Cognito 新UIで戸惑いやすいポイント（先読み）</span></h2>
<p>操作を始める前に、<strong>2026年時点の新UI</strong>で戸惑いやすい変更点を把握しておきましょう。</p>
<table>
<thead>
<tr>
<th>変更点</th>
<th>旧UI</th>
<th>新UI（現在）</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>User Pool 作成の入口</strong></td>
<td>「ユーザープールを作成」ボタンから</td>
<td>**「アプリケーションを作成」**ボタンから（名称が変わった）</td>
</tr>
<tr>
<td><strong>作成の粒度</strong></td>
<td>User Pool → App Client を別々に作成</td>
<td><strong>1ページのウィザード</strong>で User Pool とクライアントを同時作成</td>
</tr>
<tr>
<td><strong>クライアントシークレット</strong></td>
<td>デフォルトなし</td>
<td>「従来のウェブアプリケーション」を選ぶと<strong>シークレット必須</strong>になる</td>
</tr>
<tr>
<td><strong>User Pool 名</strong></td>
<td>指定した名前がそのまま付く</td>
<td>アプリ名の前に <strong><code>User pool - </code></strong> が自動で付く（例: <code>User pool - MyWebApp</code>）</td>
</tr>
<tr>
<td><strong>クライアント ID の場所</strong></td>
<td>概要ページに表示</td>
<td>左サイドバー → 「アプリケーション」から辿る</td>
</tr>
</tbody>
</table>
<blockquote>
<p><strong>最大のハマりポイント（クライアントシークレット）：</strong><br />新UIの「アプリケーションを作成」で「従来のウェブアプリケーション」を選ぶと、クライアントシークレットが<strong>自動で付与</strong>されます。シークレットありのクライアントで <code>initiate-auth</code> を実行すると <code>SECRET_HASH was not received</code> エラーが出て詰まります。<br />このハンズオンでは②の手順でシークレットなしのクライアントを別途作成します。</p>
</blockquote>
<hr>
<h2><span id="toc3">キーワード解説</span></h2>
<table>
<thead>
<tr>
<th>用語</th>
<th>意味</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>User Pool</strong></td>
<td>Cognitoのユーザーディレクトリ。ユーザー登録・認証・JWT発行を一手に担う</td>
</tr>
<tr>
<td><strong>User Pool Client</strong></td>
<td>アプリが User Pool に接続するための設定。<strong>Client ID</strong> を持つ</td>
</tr>
<tr>
<td><strong>IDトークン</strong></td>
<td>ログイン成功時に Cognito が発行する JWT。email / sub などのユーザー情報を含む</td>
</tr>
<tr>
<td><strong>Cognito Authorizer</strong></td>
<td>API Gateway が IDトークンを検証する認可機能。Lambdaコードが不要で動作する</td>
</tr>
<tr>
<td><strong>claims</strong></td>
<td>JWT ペイロードに含まれる情報（email / sub / token_use など）</td>
</tr>
<tr>
<td><strong>FORCE_CHANGE_PASSWORD</strong></td>
<td>管理者作成ユーザーの初期状態。この状態では <code>initiate-auth</code> がトークンを返さない</td>
</tr>
</tbody>
</table>
<hr>
<h2><span id="toc4">前提条件</span></h2>
<table>
<thead>
<tr>
<th>ツール</th>
<th>確認コマンド</th>
<th>備考</th>
</tr>
</thead>
<tbody>
<tr>
<td>AWSアカウント</td>
<td>—</td>
<td>IAMユーザーまたはルートユーザー</td>
</tr>
<tr>
<td>AWS CLI v2（テスト用）</td>
<td><code>aws --version</code></td>
<td>IDトークン取得・ユーザー作成に使用</td>
</tr>
</tbody>
</table>
<blockquote>
<p>AWS CLI がない場合は、テスト操作に <strong>AWSコンソールの CloudShell</strong> を代用できます（後述）。</p>
</blockquote>
<hr>
<h2><span id="toc5">使用するAWSサービス</span></h2>
<table>
<thead>
<tr>
<th>サービス</th>
<th>役割</th>
<th>料金</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Amazon Cognito</strong></td>
<td>ユーザー管理・認証・JWT発行</td>
<td>月5万MAU（月間アクティブユーザー）まで無料</td>
</tr>
<tr>
<td><strong>API Gateway</strong></td>
<td>REST API のエンドポイント管理・認可</td>
<td>月100万リクエストまで無料（無料期間12ヶ月）</td>
</tr>
<tr>
<td><strong>Lambda</strong></td>
<td>APIのビジネスロジック（1関数）</td>
<td>月100万リクエスト・400,000 GB-秒まで無料</td>
</tr>
<tr>
<td><strong>IAM</strong></td>
<td>Lambda の実行権限管理</td>
<td>無料</td>
</tr>
<tr>
<td><strong>CloudWatch Logs</strong></td>
<td>Lambda の実行ログ</td>
<td>月5GBまで無料</td>
</tr>
</tbody>
</table>
<hr>
<h2><span id="toc6">全体の作業順序</span></h2>
<pre><code class="language-plaintext">① Cognito User Pool を作成する（新UI対応）
      ↓
② テスト用アプリクライアントを作成する（シークレットなし）
      ↓
③ Lambda 関数を作成する
      ↓
④ API Gateway REST API を作成する
  （/hello・/profile エンドポイント + Cognito Authorizer 設定）
      ↓
⑤ テストユーザーを作成する
      ↓
⑥ 動作テスト（401確認 → JWTトークン取得 → 認証成功）
      ↓
⑦ リソースの削除</code></pre>
<hr>
<h2><span id="toc7">① Cognito User Pool を作成する</span></h2>
<p><strong>AWSコンソール → Cognito → 「アプリケーションを作成」</strong></p>
<p><!-- ![Cognito コンソールのトップ画面](images/cognito-top.jpg) --></p>
<blockquote>
<p><strong>新UIの注意：</strong><br />旧UIにあった「ユーザープールを作成」ボタンは廃止されています。現在は「<strong>アプリケーションを作成</strong>」からウィザードで User Pool とクライアントをまとめて作成します。</p>
</blockquote>
<h3><span id="toc8">1-1. アプリケーションを定義する</span></h3>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>アプリケーションタイプ</td>
<td><strong>従来のウェブアプリケーション</strong></td>
</tr>
<tr>
<td>アプリケーション名</td>
<td><code>MyWebApp</code></td>
</tr>
</tbody>
</table>
<h3><span id="toc9">1-2. オプションを設定する</span></h3>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>サインイン識別子のオプション</td>
<td><strong>メールアドレス</strong> にチェック（電話番号・ユーザー名はチェック不要）</td>
</tr>
<tr>
<td>自己登録を有効</td>
<td>チェックする（デフォルトでチェック済み）</td>
</tr>
<tr>
<td>サインアップのための必須属性</td>
<td>空欄のまま（属性を選択しない）</td>
</tr>
</tbody>
</table>
<blockquote>
<p><strong>サインイン識別子は作成後に変更不可。</strong> 「メールアドレス」のみ選択しておくことを推奨します。</p>
</blockquote>
<h3><span id="toc10">1-3. リターン URL（スキップ）</span></h3>
<p>「リターン URL を追加」は入力不要（今回はマネージドログインページを使わないため）。</p>
<p>画面下部の「<strong>ユーザーディレクトリを作成する</strong>」をクリック。</p>
<h3><span id="toc11">控えておく情報</span></h3>
<p>作成後、User Pool の概要ページが開きます。</p>
<ul>
<li><strong>ユーザープール ID</strong>（例: <code>ap-northeast-1_XXXXXXXX</code>）<br />→ 概要ページの「ユーザープール情報」欄に表示</li>
<li><strong>クライアント ID</strong>（例: <code>XXXXXXXXXXXXXXXXXXXXXXXXXX</code>）<br />→ 左サイドバー「アプリケーション」→「アプリケーションクライアント」→ <code>MyWebApp</code> をクリック → 「クライアント ID」欄</li>
</ul>
<blockquote>
<p><strong>注意：</strong> 概要ページの「レコメンデーション」欄にも <code>MyWebApp</code> のリンクが表示されますが、これは Quick Setup ガイドへの誘導です。クライアント ID は左サイドバーから辿ってください。</p>
</blockquote>
<blockquote>
<p><strong>User Pool 名について：</strong><br />新UIでは、アプリ名の前に <code>User pool - </code> が自動で付きます（例: <code>User pool - MyWebApp</code>）。以降の手順では「作成した User Pool」と表記します。</p>
</blockquote>
<hr>
<h2><span id="toc12">② テスト用アプリクライアントを作成する</span></h2>
<p>新UIの「アプリケーションを作成」で自動作成された <code>MyWebApp</code> クライアントには<strong>クライアントシークレットが自動付与</strong>されています。シークレットありのクライアントで CLI から <code>initiate-auth</code> を実行すると <code>SECRET_HASH was not received</code> エラーが出ます。</p>
<p>そのため、<strong>シークレットなし・<code>ALLOW_USER_PASSWORD_AUTH</code> 有効</strong>の新しいクライアントを別途作成します。</p>
<p><strong>Cognito → 作成した User Pool → 左サイドバー「アプリケーション」→「アプリケーションクライアント」→「アプリケーションクライアントを作成」</strong></p>
<h3><span id="toc13">2-1. アプリケーションを定義する</span></h3>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>アプリケーションタイプ</td>
<td><strong>シングルページアプリケーション (SPA)</strong></td>
</tr>
<tr>
<td>アプリケーション名</td>
<td><code>MyWebAppClient</code></td>
</tr>
</tbody>
</table>
<blockquote>
<p><strong>「SPA」を選ぶ理由：</strong><br />新UIでは「従来のウェブアプリケーション」を選ぶとクライアントシークレットが<strong>必須</strong>になります。「SPA」を選ぶとシークレットなしで作成できます。CLI テスト目的ではこちらを使います。</p>
</blockquote>
<h3><span id="toc14">2-2. リターン URL（スキップ）</span></h3>
<p>入力不要。</p>
<h3><span id="toc15">2-3. Client secret configuration</span></h3>
<p>SPA を選択した場合、この欄は表示されません（シークレットなしで自動確定）。</p>
<p>「<strong>アプリケーションクライアントを作成</strong>」をクリック。</p>
<h3><span id="toc16">2-4. 認証フローを確認する</span></h3>
<p>作成後、<code>MyWebAppClient</code> をクリックして詳細画面を開きます。</p>
<p>「認証フロー」セクションに <strong><code>ALLOW_USER_PASSWORD_AUTH</code></strong> が含まれていることを確認します。</p>
<p>含まれていない場合は「編集」→「ALLOW_USER_PASSWORD_AUTH」にチェック → 「変更を保存」。</p>
<blockquote>
<p><strong>ALLOW_USER_PASSWORD_AUTH とは：</strong><br />CLI から username と password を直接指定して認証する「ユーザーパスワード認証」フローです。テスト用に有効化します（本番環境では SRP フローが推奨）。</p>
</blockquote>
<p><strong>控えておく情報（更新）：</strong></p>
<ul>
<li><strong>クライアント ID</strong> → 新しく作成した <code>MyWebAppClient</code> のクライアント ID を使う（① の <code>MyWebApp</code> のクライアント ID は使わない）</li>
</ul>
<hr>
<h2><span id="toc17">③ Lambda 関数を作成する</span></h2>
<p><strong>AWSコンソール → Lambda → 「関数の作成」</strong></p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>作成方法</td>
<td>一から作成</td>
</tr>
<tr>
<td>関数名</td>
<td><code>CognitoApiFunction</code></td>
</tr>
<tr>
<td>ランタイム</td>
<td><strong>Python 3.12</strong></td>
</tr>
<tr>
<td>アーキテクチャ</td>
<td>x86_64</td>
</tr>
<tr>
<td>実行ロール</td>
<td>「基本的な Lambda アクセス権限で新しいロールを作成」（デフォルトのまま）</td>
</tr>
</tbody>
</table>
<p>「関数の作成」をクリック。</p>
<h3><span id="toc18">コードの入力</span></h3>
<p>関数ページ → 「コード」タブ → <code>lambda_function.py</code> を開いて既存の内容を<strong>全て置き換え</strong>て以下を貼り付けます。</p>
<pre><code class="language-python">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"}),
    }</code></pre>
<p>「<strong>Deploy</strong>」ボタンをクリックしてコードを保存します。</p>
<blockquote>
<p><strong>Lambda 側で認証コードが不要な理由：</strong><br />API Gateway の Cognito Authorizer が IDトークン（JWT）の検証をすべて担っています。Lambda が呼ばれた時点では認証済みであることが保証されており、検証済みの <code>claims</code> だけを受け取って使えばよい設計です。</p>
</blockquote>
<hr>
<h2><span id="toc19">④ API Gateway REST API を作成する</span></h2>
<p><strong>AWSコンソール → API Gateway → 「APIを作成」</strong></p>
<h3><span id="toc20">4-1. API タイプの選択</span></h3>
<p>「REST API」の「<strong>構築</strong>」をクリック。</p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>API タイプ</td>
<td><strong>REST API</strong>（「プライベート」ではない方）</td>
</tr>
<tr>
<td>新しい API の作成</td>
<td>「新しい API」</td>
</tr>
<tr>
<td>API 名</td>
<td><code>CognitoSampleApi</code></td>
</tr>
<tr>
<td>エンドポイントタイプ</td>
<td>リージョン</td>
</tr>
</tbody>
</table>
<p>「<strong>APIを作成</strong>」をクリック。</p>
<hr>
<h3><span id="toc21">4-2. リソース /hello を作成する</span></h3>
<p>左のリソースツリーで <strong><code>/</code>（ルート）を選択</strong> → 「<strong>リソースを作成</strong>」ボタンをクリック</p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>リソースパス（親パス）</td>
<td><code>/</code>（変更不要）</td>
</tr>
<tr>
<td>リソース名</td>
<td><code>hello</code></td>
</tr>
</tbody>
</table>
<blockquote>
<p><strong>新UIの注意点：</strong><br />「リソースパス」はリソースを作成する<strong>親パスの選択</strong>（<code>/</code> = ルート配下という意味）です。<code>/hello</code> と入力する欄ではありません。「リソース名」に <code>hello</code> と入力するだけで OK です。</p>
</blockquote>
<p>「<strong>リソースを作成</strong>」をクリック。</p>
<p><strong><code>/hello</code> を選択した状態で → 「メソッドを作成」→ メソッドタイプ <code>GET</code> を選択</strong></p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>統合タイプ</td>
<td><strong>Lambda 関数</strong></td>
</tr>
<tr>
<td>Lambda プロキシ統合の使用</td>
<td><strong>チェックする</strong></td>
</tr>
<tr>
<td>Lambda 関数</td>
<td><code>CognitoApiFunction</code></td>
</tr>
</tbody>
</table>
<p>「保存」→「OK」（Lambda 呼び出し権限の追加確認）。</p>
<hr>
<h3><span id="toc22">4-3. リソース /profile を作成する</span></h3>
<p>左のリソースツリーで <strong><code>/</code>（ルート）を選択</strong> → 「<strong>リソースを作成</strong>」</p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>リソースパス（親パス）</td>
<td><code>/</code>（変更不要）</td>
</tr>
<tr>
<td>リソース名</td>
<td><code>profile</code></td>
</tr>
</tbody>
</table>
<p>「<strong>リソースを作成</strong>」をクリック。</p>
<p><strong><code>/profile</code> を選択した状態で → 「メソッドを作成」→ メソッドタイプ <code>GET</code> を選択</strong></p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>統合タイプ</td>
<td><strong>Lambda 関数</strong></td>
</tr>
<tr>
<td>Lambda プロキシ統合の使用</td>
<td><strong>チェックする</strong></td>
</tr>
<tr>
<td>Lambda 関数</td>
<td><code>CognitoApiFunction</code></td>
</tr>
</tbody>
</table>
<p>「保存」をクリック。</p>
<hr>
<h3><span id="toc23">4-4. Cognito Authorizer を作成する</span></h3>
<p>左側メニューの「<strong>オーソライザー</strong>」→「<strong>オーソライザーを作成</strong>」</p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>オーソライザー名</td>
<td><code>CognitoAuthorizer</code></td>
</tr>
<tr>
<td>オーソライザーのタイプ</td>
<td><strong>Cognito</strong></td>
</tr>
<tr>
<td>Cognito ユーザープール（リージョン）</td>
<td><code>ap-northeast-1</code>（変更不要）</td>
</tr>
<tr>
<td>Cognito ユーザープール（検索欄）</td>
<td>① で作成した User Pool を選択（例: <code>User pool - MyWebApp</code>）</td>
</tr>
<tr>
<td>トークンのソース</td>
<td><code>Authorization</code>（<strong>必ず入力する</strong>）</td>
</tr>
<tr>
<td>トークンの検証（オプション）</td>
<td>空欄のまま</td>
</tr>
</tbody>
</table>
<blockquote>
<p><strong>新UIの注意点：</strong><br />「トークンのソース」はデフォルトで<strong>空欄</strong>になっています。<code>Authorization</code> と入力しないと動作しません。入力を忘れると全リクエストが 401 になります。</p>
</blockquote>
<p>「<strong>オーソライザーを作成</strong>」をクリック。</p>
<p><strong>動作確認：</strong></p>
<p>「オーソライザーのテスト」→ テスト用トークン欄に適当な文字を入力 → 「テスト」→ <code>401</code> が返れば正常（正しいトークンがないため 401 が正解）。</p>
<p><!-- ![Cognito Authorizer のテスト画面](images/cognito-authorizer-test.jpg) --></p>
<hr>
<h3><span id="toc24">4-5. /profile GET メソッドに Authorizer を設定する</span></h3>
<p>左のリソースツリーで <strong><code>/profile</code> → <code>GET</code></strong> を選択 → 「メソッドリクエストの設定」セクションの「<strong>編集</strong>」ボタンをクリック</p>
<p>「認可」ドロップダウンを開き、<strong><code>Cognito ユーザープールオーソライザー</code></strong> の配下にある <strong><code>CognitoAuthorizer</code></strong> を選択 → 「<strong>保存</strong>」</p>
<blockquote>
<p><strong>新UIの注意点：</strong><br />選択肢は <code>なし</code> / <code>AWS IAM</code> / <code>Cognito ユーザープールオーソライザー</code>（カテゴリ）→ <code>CognitoAuthorizer</code> の階層構造になっています。<br /><code>CognitoAuthorizer</code> はカテゴリ名ではなく、その下にインデントされた項目を選んでください。</p>
</blockquote>
<blockquote>
<p><strong>ポイント：</strong><br /><code>/hello GET</code> には Authorizer を<strong>設定しない</strong>（認証不要）。<br /><code>/profile GET</code> にのみ CognitoAuthorizer を設定することで、エンドポイントごとに認証要件を分けます。</p>
</blockquote>
<hr>
<h3><span id="toc25">4-6. API をデプロイする</span></h3>
<p><strong>「アクション」→「API のデプロイ」</strong></p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>デプロイされるステージ</td>
<td><strong>「新しいステージ」</strong></td>
</tr>
<tr>
<td>ステージ名</td>
<td><code>Prod</code></td>
</tr>
</tbody>
</table>
<p>「デプロイ」をクリック。</p>
<p><strong>控えておく情報：</strong></p>
<p>「Prod ステージエディター」に表示される <strong>URL の呼び出し</strong>（例: <code>https://XXXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/Prod</code>）をコピーします。</p>
<hr>
<h2><span id="toc26">⑤ テストユーザーを作成する</span></h2>
<p><strong>Cognito → 作成した User Pool → 左サイドバー「ユーザー管理」→「ユーザー」→「ユーザーを作成」</strong></p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>値</th>
</tr>
</thead>
<tbody>
<tr>
<td>招待メッセージ</td>
<td><strong>「招待を送信しない」</strong> を選択</td>
</tr>
<tr>
<td>E メールアドレス</td>
<td><code>test@example.com</code></td>
</tr>
<tr>
<td>仮パスワード</td>
<td><strong>「パスワードの設定」</strong> を選択</td>
</tr>
<tr>
<td>パスワード</td>
<td><code>TestPass1!</code></td>
</tr>
</tbody>
</table>
<blockquote>
<p><strong>パスワードポリシー（新UIのデフォルト）：</strong><br />最小8文字 / 数字・小文字・大文字・特殊文字をそれぞれ1文字以上含むこと。<br /><code>TestPass1</code> は特殊文字がないため不可。<code>TestPass1!</code> を使ってください。</p>
</blockquote>
<p>「<strong>ユーザーを作成</strong>」をクリック。</p>
<blockquote>
<p>ユーザーの「確認ステータス」列に <strong>「パスワードを強制的に変更」</strong> と表示されます（= FORCE_CHANGE_PASSWORD 状態）。<br />この状態で <code>initiate-auth</code> を実行してもトークンが返らず <code>NEW_PASSWORD_REQUIRED</code> チャレンジが返されます。<br />次の CLI コマンドで永続パスワードを設定して「確認済み」（CONFIRMED）に変更します。</p>
</blockquote>
<p><strong>CLI で永続パスワードを設定する：</strong></p>
<p><strong>方法 A: CloudShell（コンソール版ハンズオンにおすすめ）</strong></p>
<p>AWSコンソール画面下部の「<strong>CloudShell</strong>」をクリックして起動します。コンソールと同じ認証情報が自動で使われるため追加設定は不要。</p>
<pre><code class="language-bash">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</code></pre>
<blockquote>
<p>CloudShell は Linux シェルのため <code>\</code> で改行します。<code>!</code> を含むパスワードはシングルクォート <code>&#39;...&#39;</code> で囲んでください（ダブルクォートだと bash がエラーになる場合があります）。</p>
</blockquote>
<p><strong>方法 B: ローカルの AWS CLI（コマンドプロンプト）</strong></p>
<pre><code class="language-cmd">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</code></pre>
<blockquote>
<p><code>ap-northeast-1_XXXXXXXX</code> を ① で控えた<strong>ユーザープール ID</strong> に置き換えてください。</p>
</blockquote>
<p>コマンドが出力なしで返れば成功です。コンソールでユーザーの「確認ステータス」が**「確認済み」**に変わったことを確認してください。</p>
<hr>
<h2><span id="toc27">⑥ 動作テスト</span></h2>
<h3><span id="toc28">テスト1: 公開エンドポイント（/hello）→ 200</span></h3>
<pre><code class="language-cmd">curl https://XXXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/Prod/hello</code></pre>
<p>期待するレスポンス:</p>
<pre><code class="language-json">{"message": "Hello! This is a public endpoint."}</code></pre>
<hr>
<h3><span id="toc29">テスト2: 未認証でプライベートエンドポイント（/profile）→ 401</span></h3>
<pre><code class="language-cmd">curl https://XXXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/Prod/profile</code></pre>
<p>期待するレスポンス（API Gateway が返す。Lambda は呼ばれていない）:</p>
<pre><code class="language-json">{"message": "Unauthorized"}</code></pre>
<hr>
<h3><span id="toc30">テスト3: IDトークンを取得する</span></h3>
<pre><code class="language-cmd">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</code></pre>
<blockquote>
<p><code>XXXXXXXXXXXXXXXXXXXXXXXXXX</code> を <strong>② で控えた <code>MyWebAppClient</code> のクライアント ID</strong> に置き換えてください（① の <code>MyWebApp</code> のクライアント ID ではありません）。</p>
</blockquote>
<p>レスポンス例（抜粋）:</p>
<pre><code class="language-json">{
    "AuthenticationResult": {
        "AccessToken": "eyJra...",
        "ExpiresIn": 3600,
        "TokenType": "Bearer",
        "RefreshToken": "eyJjb...",
        "IdToken": "eyJra..."
    }
}</code></pre>
<p><strong><code>IdToken</code> の値をコピーしておきます</strong>（次のテストで使用）。</p>
<blockquote>
<p><strong>IdToken と AccessToken の違い：</strong></p>
<table>
<thead>
<tr>
<th>トークン</th>
<th>用途</th>
<th>含まれる情報</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>IdToken</strong></td>
<td>ユーザー認証（今回使用）</td>
<td>email / sub など</td>
</tr>
<tr>
<td>AccessToken</td>
<td>Cognito API へのアクセス</td>
<td>sub / scope など</td>
</tr>
</tbody>
</table>
<p>API Gateway の Cognito Authorizer に渡すのは <strong>IdToken</strong>。AccessToken を渡しても 403 になります。</p>
</blockquote>
<hr>
<h3><span id="toc31">テスト4: 認証ありでプライベートエンドポイント（/profile）→ 200</span></h3>
<p>IdToken は非常に長いため、変数に格納してから実行します。</p>
<p><strong>方法 A: CloudShell（おすすめ）</strong></p>
<pre><code class="language-bash">TOKEN="eyJra...（IdToken全体を貼り付ける）"
curl -H "Authorization: $TOKEN" https://XXXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/Prod/profile</code></pre>
<p><strong>方法 B: Windows CMD（変数使用）</strong></p>
<pre><code class="language-cmd">set TOKEN=eyJra...（IdToken全体を貼り付ける）
curl -H "Authorization: %TOKEN%" https://XXXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/Prod/profile</code></pre>
<blockquote>
<p><strong>重要：</strong> CMD では変数展開に <code>%TOKEN%</code> を使います。<code>$TOKEN</code>（bash 構文）を CMD で使うと文字列 <code>$TOKEN</code> がそのまま送られ 401 になります。<br />また <code>Bearer</code> プレフィックスは不要です。raw JWT をそのまま Authorization ヘッダーに指定してください。</p>
</blockquote>
<p>期待するレスポンス:</p>
<pre><code class="language-json">{
  "message": "認証成功",
  "email": "test@example.com",
  "sub": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "token_use": "id"
}</code></pre>
<blockquote>
<p><code>sub</code> は Cognito が自動生成したユーザーの一意 ID です。<br /><code>token_use: &quot;id&quot;</code> は IDトークンを使っていることを示します。</p>
</blockquote>
<p><!-- ![認証成功レスポンス](images/cognito-auth-success.jpg) --></p>
<hr>
<h2><span id="toc32">⑦ リソースの削除</span></h2>
<p><strong>課金を止めるために、ハンズオン完了後は必ずリソースを削除してください。</strong></p>
<h3><span id="toc33">1. API Gateway を削除する</span></h3>
<p><strong>API Gateway → APIs → <code>CognitoSampleApi</code> を選択 → 「アクション」→「APIの削除」</strong></p>
<hr>
<h3><span id="toc34">2. Lambda 関数を削除する</span></h3>
<p><strong>Lambda → 関数 → <code>CognitoApiFunction</code> を選択 → 「アクション」→「削除」</strong></p>
<hr>
<h3><span id="toc35">3. Cognito User Pool を削除する</span></h3>
<p><strong>Cognito → 作成した User Pool → 右上の「ユーザープールを削除」ボタン → ユーザープール名を入力 → 「削除」</strong></p>
<blockquote>
<p>ユーザーとアプリクライアントも一緒に削除されます。</p>
</blockquote>
<hr>
<h3><span id="toc36">4. IAM ロールを削除する（任意）</span></h3>
<p><strong>IAM → ロール → <code>CognitoApiFunction-role-XXXX</code> を検索して削除</strong></p>
<hr>
<h3><span id="toc37">5. CloudWatch Logs のロググループを削除する（任意）</span></h3>
<p><strong>CloudWatch → ロググループ → <code>/aws/lambda/CognitoApiFunction</code> → 削除</strong></p>
<hr>
<h2><span id="toc38">SAMとの対比</span></h2>
<table>
<thead>
<tr>
<th>SAMの記述</th>
<th>コンソールでやること</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>AWS::Cognito::UserPool</code></td>
<td>Cognito → 「アプリケーションを作成」で User Pool を作成</td>
</tr>
<tr>
<td><code>AWS::Cognito::UserPoolClient</code>（シークレットなし）</td>
<td>② の手順で SPA タイプのクライアント <code>MyWebAppClient</code> を別途作成</td>
</tr>
<tr>
<td><code>Auth.DefaultAuthorizer: CognitoAuthorizer</code></td>
<td>API Gateway → オーソライザーを作成して /profile GET に適用</td>
</tr>
<tr>
<td><code>Auth: Authorizer: NONE</code>（/hello 側）</td>
<td>/hello GET には Authorizer を設定しない</td>
</tr>
<tr>
<td><code>sam delete</code></td>
<td>API Gateway / Lambda / Cognito / IAM ロール / ロググループを個別に削除</td>
</tr>
</tbody>
</table>
<hr>
<h2><span id="toc39">トラブルシューティング</span></h2>
<table>
<thead>
<tr>
<th>症状</th>
<th>原因</th>
<th>対処</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>initiate-auth</code> で <code>Client is configured with secret but SECRET_HASH was not received</code></td>
<td>① で自動作成された <code>MyWebApp</code>（シークレットあり）のクライアント ID を使っている</td>
<td>② の手順で <code>MyWebAppClient</code>（シークレットなし）を作成し、そちらの Client ID を使う</td>
</tr>
<tr>
<td><code>initiate-auth</code> で <code>NotAuthorizedException</code></td>
<td>ユーザーが FORCE_CHANGE_PASSWORD 状態</td>
<td><code>admin-set-user-password --permanent</code> で CONFIRMED に変更する</td>
</tr>
<tr>
<td><code>initiate-auth</code> で <code>InvalidParameterException</code></td>
<td><code>ALLOW_USER_PASSWORD_AUTH</code> が無効</td>
<td>User Pool Client の認証フロー設定を確認する</td>
</tr>
<tr>
<td><code>/profile</code> に IDトークンを送っても 401</td>
<td><code>Bearer TOKEN</code> 形式で送っている</td>
<td><code>Bearer</code> を外し raw JWT（<code>eyJra...</code>）をそのまま Authorization ヘッダーに指定する</td>
</tr>
<tr>
<td><code>/profile</code> に IDトークンを送っても 403</td>
<td>トークンが期限切れ（1時間で失効）</td>
<td><code>initiate-auth</code> で新しいトークンを取得し直す</td>
</tr>
<tr>
<td><code>/profile</code> に IDトークンを送っても 403</td>
<td>AccessToken を使っている（IdToken ではない）</td>
<td><code>AuthenticationResult.IdToken</code> を使用しているか確認する</td>
</tr>
<tr>
<td>Lambda の <code>claims</code> が空</td>
<td><code>/profile GET</code> に Authorizer が設定されていない</td>
<td>④ 4-5 の手順で CognitoAuthorizer を設定し直す</td>
</tr>
<tr>
<td>Lambda の <code>resource</code> が <code>/</code> になる</td>
<td>Lambda プロキシ統合が有効になっていない</td>
<td>GET メソッドで「Lambda プロキシ統合の使用」をチェックする</td>
</tr>
<tr>
<td>Authorizer テストが 500 になる</td>
<td>User Pool が選択されていない、またはトークンのソースが空</td>
<td>オーソライザーの設定を確認し <code>Authorization</code> を入力し直す</td>
</tr>
</tbody>
</table>
<hr>
<h2><span id="toc40">まとめ</span></h2>
<p>今回のハンズオンで体験できたこと：</p>
<table>
<thead>
<tr>
<th>確認項目</th>
<th>内容</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Cognito User Pool</strong></td>
<td>ユーザー作成・JWT 発行・パスワードポリシーを新UIで設定</td>
</tr>
<tr>
<td><strong>Cognito Authorizer</strong></td>
<td>API Gateway がIDトークンを自動検証 → Lambda は認証コード不要</td>
</tr>
<tr>
<td><strong>エンドポイント別認証制御</strong></td>
<td>/hello（認証なし）と /profile（認証必須）を同じ Lambda で分岐</td>
</tr>
<tr>
<td><strong>FORCE_CHANGE_PASSWORD 対処</strong></td>
<td><code>admin-set-user-password --permanent</code> で CONFIRMED 状態に変更</td>
</tr>
<tr>
<td><strong>新UI操作</strong></td>
<td>「アプリケーションを作成」→ SPA クライアントの追加作成 → Authorizer のトークンソース設定</td>
</tr>
</tbody>
</table>
<hr>
<h2><span id="toc41">コンソール版とSAM版を比較してみる</span></h2>
<p>コンソールでCognitoとAPI Gatewayの連携を理解したら、SAMで同じ構成をコードで定義することで「SAMが何を自動化しているか」が明確になります。<code>DefaultAuthorizer</code> によるワンライン認証設定や、<code>ALLOW_USER_PASSWORD_AUTH</code> の自動有効化など、コンソールでの手動操作がコードに対応しています。</p>
<p><!-- TODO: SAM版記事へのリンクを追加 --></p>
<hr>
<h2><span id="toc42">関連記事</span></h2>
<p><a rel="nofollow" href="//af.moshimo.com/af/c/click?a_id=1384942&p_id=170&pc_id=185&pl_id=4062&url=https%3A%2F%2Fwww.amazon.co.jp%2Fs%3Fk%3D%25E6%259C%25AC%2BAWS%2B%25E9%2596%258B%25E7%2599%25BA%26__mk_ja_JP%3D%25E3%2582%25AB%25E3%2582%25BF%25E3%2582%25AB%25E3%2583%258A%26crid%3D1DE63UBHFOR4K%26sprefix%3D%25E6%259C%25AC%2Baws%2B%25E9%2596%258B%25E7%2599%25BA%252Caps%252C167%26ref%3Dnb_sb_noss" referrerpolicy="no-referrer-when-downgrade" attributionsrc>Amazon検索[本 AWS 開発]</a><img decoding="async" src="//i.moshimo.com/af/i/impression?a_id=1384942&p_id=170&pc_id=185&pl_id=4062" width="1" height="1" style="border:none;" alt="" loading="lazy"></p>
<p><!-- START MoshimoAffiliateEasyLink --><script type="text/javascript">(function(b,c,f,g,a,d,e){b.MoshimoAffiliateObject=a;b[a]=b[a]||function(){arguments.currentScript=c.currentScript||c.scripts[c.scripts.length-2];(b[a].q=b[a].q||[]).push(arguments)};c.getElementById(a)||(d=c.createElement(f),d.src=g,d.id=a,e=c.getElementsByTagName("body")[0],e.appendChild(d))})(window,document,"script","//dn.msmstatic.com/site/cardlink/bundle.js?20220329","msmaflink");msmaflink({"n":"AWS運用入門 改訂第2版 押さえておきたいAWSの基本と運用ノウハウ [AWS深掘りガイド]","b":"SBクリエイティブ","t":"","d":"https:\/\/m.media-amazon.com","c_p":"\/images\/I","p":["\/51AAOubymTL._SL500_.jpg","\/51VMG6YKHdL._SL500_.jpg","\/41EdPB8azAL._SL500_.jpg","\/41v2JFE-9jL._SL500_.jpg","\/41FEEqR-yDL._SL500_.jpg","\/41JfZAdnTPL._SL500_.jpg","\/41vGK0czQrL._SL500_.jpg","\/41-SnYtz2aL._SL500_.jpg","\/41sPrV5fi3L._SL500_.jpg","\/41p7JtvYJ1L._SL500_.jpg","\/4169GVNTs8L._SL500_.jpg","\/41BPI5HP3zL._SL500_.jpg","\/41QOyk60CYL._SL500_.jpg","\/41APjk6FphL._SL500_.jpg","\/41ezKUu7VRL._SL500_.jpg","\/41A1n3K+r5L._SL500_.jpg","\/41aY2T8lEOL._SL500_.jpg","\/419Ca1V6HZL._SL500_.jpg","\/41zQkYyLPzL._SL500_.jpg","\/41YpHcyxiTL._SL500_.jpg","\/41-tKN5mt6L._SL500_.jpg","\/419Mv6m55IL._SL500_.jpg"],"u":{"u":"https:\/\/www.amazon.co.jp\/dp\/4815631085","t":"amazon","r_v":""},"v":"2.1","b_l":[{"id":1,"u_tx":"Amazonで見る","u_bc":"#f79256","u_url":"https:\/\/www.amazon.co.jp\/dp\/4815631085","a_id":1384942,"p_id":170,"pl_id":27060,"pc_id":185,"s_n":"amazon","u_so":1},{"id":2,"u_tx":"楽天市場で見る","u_bc":"#f76956","u_url":"https:\/\/search.rakuten.co.jp\/search\/mall\/AWS%E9%81%8B%E7%94%A8%E5%85%A5%E9%96%80%20%E6%94%B9%E8%A8%82%E7%AC%AC2%E7%89%88%20%E6%8A%BC%E3%81%95%E3%81%88%E3%81%A6%E3%81%8A%E3%81%8D%E3%81%9F%E3%81%84AWS%E3%81%AE%E5%9F%BA%E6%9C%AC%E3%81%A8%E9%81%8B%E7%94%A8%E3%83%8E%E3%82%A6%E3%83%8F%E3%82%A6%20%5BAWS%E6%B7%B1%E6%8E%98%E3%82%8A%E3%82%AC%E3%82%A4%E3%83%89%5D\/","a_id":1384917,"p_id":54,"pl_id":27059,"pc_id":54,"s_n":"rakuten","u_so":2},{"id":3,"u_tx":"Yahoo!ショッピングで見る","u_bc":"#66a7ff","u_url":"https:\/\/shopping.yahoo.co.jp\/search?first=1\u0026p=AWS%E9%81%8B%E7%94%A8%E5%85%A5%E9%96%80%20%E6%94%B9%E8%A8%82%E7%AC%AC2%E7%89%88%20%E6%8A%BC%E3%81%95%E3%81%88%E3%81%A6%E3%81%8A%E3%81%8D%E3%81%9F%E3%81%84AWS%E3%81%AE%E5%9F%BA%E6%9C%AC%E3%81%A8%E9%81%8B%E7%94%A8%E3%83%8E%E3%82%A6%E3%83%8F%E3%82%A6%20%5BAWS%E6%B7%B1%E6%8E%98%E3%82%8A%E3%82%AC%E3%82%A4%E3%83%89%5D","a_id":1466950,"p_id":1225,"pl_id":27061,"pc_id":1925,"s_n":"yahoo","u_so":3}],"eid":"E8MM1","s":"s"});</script></p>
<div id="msmaflink-E8MM1">リンク</div>
<p><!-- MoshimoAffiliateEasyLink END --></p><p>The post <a href="https://caymezon.com/aws-handson-console-cognito-api-gateway-lambda/">AWSコンソールだけでCognito + API Gateway + Lambda の認証付きAPIを構築する手順【SAM版との比較付き / 新UI対応】</a> first appeared on <a href="https://caymezon.com">CayTech Lab</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://caymezon.com/aws-handson-console-cognito-api-gateway-lambda/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>AWSハンズオン - Cognito + API Gateway + Lambda で認証付きAPIをSAMで構築しよう【コンソール版との比較付き】</title>
		<link>https://caymezon.com/aws-handson-cognito-api-gateway-lambda/</link>
					<comments>https://caymezon.com/aws-handson-cognito-api-gateway-lambda/#respond</comments>
		
		<dc:creator><![CDATA[caymezon]]></dc:creator>
		<pubDate>Sun, 01 Mar 2026 08:50:28 +0000</pubDate>
				<category><![CDATA[AWS Basic]]></category>
		<category><![CDATA[Cloud & Infra]]></category>
		<category><![CDATA[APIGateway]]></category>
		<category><![CDATA[AWS]]></category>
		<category><![CDATA[Cognito]]></category>
		<category><![CDATA[IaC]]></category>
		<category><![CDATA[JWT]]></category>
		<category><![CDATA[Lambda]]></category>
		<category><![CDATA[REST API]]></category>
		<category><![CDATA[SAM]]></category>
		<category><![CDATA[サーバーレス]]></category>
		<category><![CDATA[ハンズオン]]></category>
		<category><![CDATA[初心者]]></category>
		<category><![CDATA[認証]]></category>
		<guid isPermaLink="false">https://caymezon.com/?p=20235</guid>

					<description><![CDATA[<p>目次 はじめにSAM vs コンソール：どれだけ違うかキーワード解説前提条件使用するAWSサービスStep 1: プロジェクトフォルダを開くフォルダ構造Step 2: SAMテンプレートの確認（template.yaml [&#8230;]</p>
<p>The post <a href="https://caymezon.com/aws-handson-cognito-api-gateway-lambda/">AWSハンズオン - Cognito + API Gateway + Lambda で認証付きAPIをSAMで構築しよう【コンソール版との比較付き】</a> first appeared on <a href="https://caymezon.com">CayTech Lab</a>.</p>]]></description>
										<content:encoded><![CDATA[<div id="toc" class="toc tnt-number toc-center tnt-number border-element"><input type="checkbox" class="toc-checkbox" id="toc-checkbox-4" checked><label class="toc-title" for="toc-checkbox-4">目次</label>
    <div class="toc-content">
    <ol class="toc-list open"><li><a href="#toc1" tabindex="0">はじめに</a></li><li><a href="#toc2" tabindex="0">SAM vs コンソール：どれだけ違うか</a></li><li><a href="#toc3" tabindex="0">キーワード解説</a></li><li><a href="#toc4" tabindex="0">前提条件</a></li><li><a href="#toc5" tabindex="0">使用するAWSサービス</a></li><li><a href="#toc6" tabindex="0">Step 1: プロジェクトフォルダを開く</a><ol><li><a href="#toc7" tabindex="0">フォルダ構造</a></li></ol></li><li><a href="#toc8" tabindex="0">Step 2: SAMテンプレートの確認（template.yaml）</a><ol><li><a href="#toc9" tabindex="0">Cognito リソースの定義</a></li><li><a href="#toc10" tabindex="0">API Gateway と Cognito Authorizer の定義</a></li><li><a href="#toc11" tabindex="0">Lambda 関数とエンドポイントの定義</a></li><li><a href="#toc12" tabindex="0">template.yaml のポイント解説</a></li></ol></li><li><a href="#toc13" tabindex="0">Step 3: Lambda コードの確認（src/app.py）</a></li><li><a href="#toc14" tabindex="0">Step 4: samconfig.toml を作成する</a></li><li><a href="#toc15" tabindex="0">Step 5: sam build（ビルド）</a></li><li><a href="#toc16" tabindex="0">Step 6: sam deploy（デプロイ）</a><ol><li><a href="#toc17" tabindex="0">デプロイ完了の確認</a></li><li><a href="#toc18" tabindex="0">デプロイされるリソース一覧</a></li></ol></li><li><a href="#toc19" tabindex="0">Step 7: 動作テスト</a><ol><li><a href="#toc20" tabindex="0">事前準備: 変数を設定する</a></li><li><a href="#toc21" tabindex="0">テスト1: テストユーザーを作成する</a></li><li><a href="#toc22" tabindex="0">テスト2: 公開エンドポイントのテスト（/hello）→ 200</a></li><li><a href="#toc23" tabindex="0">テスト3: 未認証でプライベートエンドポイント（/profile）→ 401</a></li><li><a href="#toc24" tabindex="0">テスト4: IDトークンを取得する</a></li><li><a href="#toc25" tabindex="0">テスト5: 認証ありでプライベートエンドポイント（/profile）→ 200</a></li></ol></li><li><a href="#toc26" tabindex="0">Step 8: AWSコンソールで確認（任意）</a></li><li><a href="#toc27" tabindex="0">Step 9: リソースの削除</a><ol><li><a href="#toc28" tabindex="0">削除完了の確認</a></li><li><a href="#toc29" tabindex="0">sam delete で削除されるリソース一覧</a></li></ol></li><li><a href="#toc30" tabindex="0">トラブルシューティング</a></li><li><a href="#toc31" tabindex="0">まとめ</a><ol><li><a href="#toc32" tabindex="0">SAMのメリットを実感できたポイント</a></li></ol></li><li><a href="#toc33" tabindex="0">コンソール版と比較してみる</a></li><li><a href="#toc34" tabindex="0">関連記事</a></li></ol>
    </div>
  </div>

<h2><span id="toc1">はじめに</span></h2>
<p>「認証付きAPIの構成をコードで管理して、チームで再現できるようにしたい」——そんな要件に、<strong>AWS SAM（Serverless Application Model）</strong> は最適な選択肢のひとつです。</p>
<p>この記事では、<strong>AWS SAM</strong> を使って、Cognito + API Gateway + Lambda による認証付き REST API をゼロから構築するハンズオンを紹介します。</p>
<pre><code class="language-plaintext">クライアント（curl）
  │
  ├─ GET /hello  → API Gateway（認証なし）→ Lambda → 200 OK
  │
  └─ GET /profile
        ├─ Authorization ヘッダーなし → API Gateway が 401 を返す
        └─ Authorization: &lt;IDトークン&gt;
              → Cognito Authorizer が JWT を検証（Lambda 不要）
              → Lambda → email / sub を返す → 200 OK</code></pre>
<p><strong>このハンズオンで体験できること：</strong></p>
<ul>
<li><code>AWS::Cognito::UserPool</code> と <code>AWS::Cognito::UserPoolClient</code> の SAM 定義</li>
<li><code>DefaultAuthorizer</code> を使ったエンドポイント単位の認証制御（1行で全エンドポイントに認証を適用）</li>
<li><code>Authorizer: NONE</code> で特定エンドポイントだけ認証を除外するパターン</li>
<li>CLI でのテスト実行（ユーザー作成 → IDトークン取得 → 認証済みリクエスト）</li>
</ul>
<p><strong>このハンズオンの特徴：</strong></p>
<ul>
<li><code>sam build</code> + <code>sam deploy</code> の <strong>2コマンドで全リソースをデプロイ</strong></li>
<li>Cognito User Pool / User Pool Client / API Gateway / Lambda / IAM ロールを <code>template.yaml</code> 1ファイルで管理</li>
<li><code>sam delete</code> で<strong>全リソースを一括削除</strong>（コンソール版では各リソースを個別に削除する必要がある）</li>
</ul>
<hr>
<p><a rel="nofollow" href="//af.moshimo.com/af/c/click?a_id=1384942&p_id=170&pc_id=185&pl_id=4062&url=https%3A%2F%2Fwww.amazon.co.jp%2Fs%3Fk%3D%25E6%259C%25AC%2BAWS%2B%25E9%2596%258B%25E7%2599%25BA%26__mk_ja_JP%3D%25E3%2582%25AB%25E3%2582%25BF%25E3%2582%25AB%25E3%2583%258A%26crid%3D1DE63UBHFOR4K%26sprefix%3D%25E6%259C%25AC%2Baws%2B%25E9%2596%258B%25E7%2599%25BA%252Caps%252C167%26ref%3Dnb_sb_noss" referrerpolicy="no-referrer-when-downgrade" attributionsrc>Amazon検索[本 AWS 開発]</a><img decoding="async" src="//i.moshimo.com/af/i/impression?a_id=1384942&p_id=170&pc_id=185&pl_id=4062" width="1" height="1" style="border:none;" alt="" loading="lazy"></p>
<p><!-- START MoshimoAffiliateEasyLink --><script type="text/javascript">(function(b,c,f,g,a,d,e){b.MoshimoAffiliateObject=a;b[a]=b[a]||function(){arguments.currentScript=c.currentScript||c.scripts[c.scripts.length-2];(b[a].q=b[a].q||[]).push(arguments)};c.getElementById(a)||(d=c.createElement(f),d.src=g,d.id=a,e=c.getElementsByTagName("body")[0],e.appendChild(d))})(window,document,"script","//dn.msmstatic.com/site/cardlink/bundle.js?20220329","msmaflink");msmaflink({"n":"AWSの基本・仕組み・重要用語が全部わかる教科書 (見るだけ図解)","b":"SBクリエイティブ","t":"","d":"https:\/\/m.media-amazon.com","c_p":"\/images\/I","p":["\/51DEDQXj6oL._SL500_.jpg","\/41F589smNwL._SL500_.jpg","\/41R6f9yyCWL._SL500_.jpg","\/41HqWQ9BvmL._SL500_.jpg","\/41p8p0ZU79L._SL500_.jpg","\/41qLC-fndBL._SL500_.jpg","\/41fcLv9VT5L._SL500_.jpg","\/51lRvCsvHqL._SL500_.jpg"],"u":{"u":"https:\/\/www.amazon.co.jp\/dp\/4815607850","t":"amazon","r_v":""},"v":"2.1","b_l":[{"id":1,"u_tx":"Amazonで見る","u_bc":"#f79256","u_url":"https:\/\/www.amazon.co.jp\/dp\/4815607850","a_id":1384942,"p_id":170,"pl_id":27060,"pc_id":185,"s_n":"amazon","u_so":1},{"id":2,"u_tx":"楽天市場で見る","u_bc":"#f76956","u_url":"https:\/\/search.rakuten.co.jp\/search\/mall\/AWS%E3%81%AE%E5%9F%BA%E6%9C%AC%E3%83%BB%E4%BB%95%E7%B5%84%E3%81%BF%E3%83%BB%E9%87%8D%E8%A6%81%E7%94%A8%E8%AA%9E%E3%81%8C%E5%85%A8%E9%83%A8%E3%82%8F%E3%81%8B%E3%82%8B%E6%95%99%E7%A7%91%E6%9B%B8%20(%E8%A6%8B%E3%82%8B%E3%81%A0%E3%81%91%E5%9B%B3%E8%A7%A3)\/","a_id":1384917,"p_id":54,"pl_id":27059,"pc_id":54,"s_n":"rakuten","u_so":2},{"id":3,"u_tx":"Yahoo!ショッピングで見る","u_bc":"#66a7ff","u_url":"https:\/\/shopping.yahoo.co.jp\/search?first=1\u0026p=AWS%E3%81%AE%E5%9F%BA%E6%9C%AC%E3%83%BB%E4%BB%95%E7%B5%84%E3%81%BF%E3%83%BB%E9%87%8D%E8%A6%81%E7%94%A8%E8%AA%9E%E3%81%8C%E5%85%A8%E9%83%A8%E3%82%8F%E3%81%8B%E3%82%8B%E6%95%99%E7%A7%91%E6%9B%B8%20(%E8%A6%8B%E3%82%8B%E3%81%A0%E3%81%91%E5%9B%B3%E8%A7%A3)","a_id":1466950,"p_id":1225,"pl_id":27061,"pc_id":1925,"s_n":"yahoo","u_so":3}],"eid":"eaCUB","s":"s"});</script></p>
<div id="msmaflink-eaCUB">リンク</div>
<p><!-- MoshimoAffiliateEasyLink END --></p>
<h2><span id="toc2">SAM vs コンソール：どれだけ違うか</span></h2>
<table>
<thead>
<tr>
<th>比較項目</th>
<th>SAM（コード）</th>
<th>コンソール（手動）</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Cognito Client 作成</strong></td>
<td><code>GenerateSecret: false</code> の1行でシークレットなしクライアントを定義</td>
<td>新UIで「SPA」タイプのクライアントを別途手動作成</td>
</tr>
<tr>
<td><strong>Authorizer の紐付け</strong></td>
<td><code>UserPoolArn: !GetAtt UserPool.Arn</code> で自動連携</td>
<td>コンソールで User Pool を手動選択し、トークンのソースを手入力</td>
</tr>
<tr>
<td><strong>エンドポイント別認証</strong></td>
<td><code>DefaultAuthorizer</code> + 除外箇所に <code>Authorizer: NONE</code></td>
<td>エンドポイントごとにオーソライザーを手動設定</td>
</tr>
<tr>
<td><strong>削除</strong></td>
<td><code>sam delete</code> 1コマンド</td>
<td>API Gateway / Lambda / Cognito / IAM を個別に削除</td>
</tr>
<tr>
<td><strong>再現性</strong></td>
<td>チームで同じ環境を即座に再現できる</td>
<td>手順書が必要</td>
</tr>
</tbody>
</table>
<hr>
<h2><span id="toc3">キーワード解説</span></h2>
<table>
<thead>
<tr>
<th>用語</th>
<th>意味</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>User Pool</strong></td>
<td>Cognito のユーザーディレクトリ。ユーザー登録・認証・JWT 発行を担う</td>
</tr>
<tr>
<td><strong>User Pool Client</strong></td>
<td>アプリが User Pool に接続するための設定。<strong>Client ID</strong> を持つ</td>
</tr>
<tr>
<td><strong>IDトークン</strong></td>
<td>ログイン成功時に Cognito が発行する JWT。email / sub などのユーザー情報を含む</td>
</tr>
<tr>
<td><strong>Cognito Authorizer</strong></td>
<td>API Gateway が IDトークンを検証する認可機能。Lambda コードが不要で動作する</td>
</tr>
<tr>
<td><strong>claims</strong></td>
<td>JWT ペイロードに含まれる情報（email / sub / token_use など）</td>
</tr>
<tr>
<td><strong>DefaultAuthorizer</strong></td>
<td>全エンドポイントに一括でオーソライザーを適用する SAM の設定。個別に <code>Authorizer: NONE</code> で除外できる</td>
</tr>
</tbody>
</table>
<hr>
<h2><span id="toc4">前提条件</span></h2>
<table>
<thead>
<tr>
<th>ツール</th>
<th>確認コマンド</th>
<th>最低バージョン目安</th>
</tr>
</thead>
<tbody>
<tr>
<td>AWS CLI v2</td>
<td><code>aws --version</code></td>
<td>2.x</td>
</tr>
<tr>
<td>AWS SAM CLI</td>
<td><code>sam --version</code></td>
<td>1.x</td>
</tr>
<tr>
<td>Python 3.12</td>
<td><code>python --version</code></td>
<td>3.12</td>
</tr>
</tbody>
</table>
<pre><code class="language-cmd">aws sts get-caller-identity</code></pre>
<p>アカウントIDが表示されれば認証設定済みです。</p>
<hr>
<h2><span id="toc5">使用するAWSサービス</span></h2>
<table>
<thead>
<tr>
<th>サービス</th>
<th>役割</th>
<th>料金</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Amazon Cognito</strong></td>
<td>ユーザー管理・認証・JWT発行</td>
<td>月5万MAUまで無料</td>
</tr>
<tr>
<td><strong>API Gateway</strong></td>
<td>REST API のエンドポイント管理・認可</td>
<td>月100万リクエストまで無料（無料期間12ヶ月）</td>
</tr>
<tr>
<td><strong>Lambda</strong></td>
<td>APIのビジネスロジック（1関数）</td>
<td>月100万リクエスト・400,000 GB-秒まで無料</td>
</tr>
<tr>
<td><strong>IAM</strong></td>
<td>Lambda の実行権限管理</td>
<td>無料</td>
</tr>
<tr>
<td><strong>S3</strong></td>
<td>SAM デプロイパッケージ置き場</td>
<td>少量のため実質無料</td>
</tr>
<tr>
<td><strong>CloudWatch Logs</strong></td>
<td>Lambda の実行ログ</td>
<td>月5GBまで無料</td>
</tr>
</tbody>
</table>
<hr>
<h2><span id="toc6">Step 1: プロジェクトフォルダを開く</span></h2>
<pre><code class="language-cmd">cd C:\my-aws\aws-learning-projects\cognito-api-lambda</code></pre>
<h3><span id="toc7">フォルダ構造</span></h3>
<pre><code class="language-plaintext">cognito-api-lambda/
├── template.yaml       # SAMテンプレート（Cognito + API Gateway + Lambda 定義）
├── samconfig.toml      # デプロイ設定（gitignore 対象・毎回手動作成が必要）
├── docs/
│   ├── 1_console.md    # AWSコンソール版手順
│   └── 2_sam.md        # SAM版手順
└── src/
    └── app.py          # Lambda 関数（/hello と /profile を処理）</code></pre>
<hr>
<h2><span id="toc8">Step 2: SAMテンプレートの確認（template.yaml）</span></h2>
<p><code>template.yaml</code> は全 AWSリソースの設計図です。ポイントを確認しておきます。</p>
<h3><span id="toc9">Cognito リソースの定義</span></h3>
<pre><code class="language-yaml">Resources:
  UserPool:
    Type: AWS::Cognito::UserPool
    Properties:
      UsernameAttributes: [email]     # メールアドレスでログイン
      Policies:
        PasswordPolicy:
          MinimumLength: 8            # 記号・大文字不要（テスト用に緩和）

  # アプリクライアント: CLI から initiate-auth で使う
  UserPoolClient:
    Type: AWS::Cognito::UserPoolClient
    Properties:
      GenerateSecret: false           # シークレットなし（CLI テスト用）
      ExplicitAuthFlows:
        - ALLOW_USER_PASSWORD_AUTH    # username/password で直接認証（テスト用）
        - ALLOW_REFRESH_TOKEN_AUTH</code></pre>
<h3><span id="toc10">API Gateway と Cognito Authorizer の定義</span></h3>
<pre><code class="language-yaml">  MyApi:
    Type: AWS::Serverless::Api
    Properties:
      StageName: Prod
      Auth:
        # DefaultAuthorizer を指定 → 全エンドポイントにデフォルトで認証が必要になる
        DefaultAuthorizer: CognitoAuthorizer
        Authorizers:
          CognitoAuthorizer:
            UserPoolArn: !GetAtt UserPool.Arn  # User Pool と自動的に紐付け
            Identity:
              Header: Authorization            # JWT を Authorization ヘッダーで受け取る</code></pre>
<h3><span id="toc11">Lambda 関数とエンドポイントの定義</span></h3>
<pre><code class="language-yaml">  ApiFunction:
    Type: AWS::Serverless::Function
    Properties:
      Events:
        PublicEndpoint:              # /hello: 公開エンドポイント
          Type: Api
          Properties:
            Path: /hello
            Method: get
            Auth:
              Authorizer: NONE       # DefaultAuthorizer を明示的に無効化

        PrivateEndpoint:             # /profile: 認証必須
          Type: Api
          Properties:
            Path: /profile
            Method: get
            # Auth 指定なし → DefaultAuthorizer（CognitoAuthorizer）が自動適用</code></pre>
<h3><span id="toc12">template.yaml のポイント解説</span></h3>
<table>
<thead>
<tr>
<th>ポイント</th>
<th>説明</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong><code>GenerateSecret: false</code></strong></td>
<td>CLI テスト用にシークレットなしのクライアントを定義。コンソール版では SPA タイプのクライアントを手動作成</td>
</tr>
<tr>
<td><strong><code>DefaultAuthorizer</code></strong></td>
<td>全エンドポイントに Cognito 認証をデフォルト適用。コンソール版ではエンドポイントごとに手動設定</td>
</tr>
<tr>
<td><strong><code>Authorizer: NONE</code></strong></td>
<td>/hello など特定エンドポイントの認証を除外。コンソール版では /hello に Authorizer を設定しないことに対応</td>
</tr>
<tr>
<td><strong><code>UserPoolArn: !GetAtt UserPool.Arn</code></strong></td>
<td>Cognito Authorizer と User Pool を自動的に紐付け。コンソール版では手動でドロップダウン選択が必要</td>
</tr>
</tbody>
</table>
<hr>
<h2><span id="toc13">Step 3: Lambda コードの確認（src/app.py）</span></h2>
<p><code>src/app.py</code> の構造を把握しておきます。</p>
<pre><code class="language-python">import json


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

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

    if resource == "/profile":
        # Cognito Authorizer が JWT を検証済み
        # JWT ペイロードが event["requestContext"]["authorizer"]["claims"] に格納される
        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, "body": json.dumps({"message": "Not Found"})}</code></pre>
<p><strong>app.py のポイント：</strong></p>
<ul>
<li>Lambda 側でトークン検証は一切不要。Cognito Authorizer が自動で行う</li>
<li><code>claims</code> には email / sub / token_use など JWT ペイロードの全フィールドが格納される</li>
<li><code>/hello</code> への呼び出しでは <code>claims</code> は空（Authorizer が動作しないため）</li>
</ul>
<blockquote>
<p><strong>各コードの全文はコンソール版記事を参照してください。</strong><br />SAM版・コンソール版で使用する Lambda コードは共通です。コンソール版では手順とあわせてコードを全文掲載しています。</p>
<p>→ <a href="/aws-handson-console-cognito-api-gateway-lambda/">AWSコンソールだけでCognito + API Gateway + Lambda の認証付きAPIを構築する手順</a></p>
</blockquote>
<hr>
<h2><span id="toc14">Step 4: samconfig.toml を作成する</span></h2>
<p><code>samconfig.toml</code> は <code>.gitignore</code> で管理外のため、<strong>毎回手動で作成</strong>する必要があります。</p>
<p><code>cognito-api-lambda/samconfig.toml</code> を新規作成して以下を貼り付けます。</p>
<pre><code class="language-toml">version = 0.1

[default.deploy.parameters]
stack_name = "cognito-api-lambda-stack"
resolve_s3 = true
s3_prefix = "cognito-api-lambda-stack"
region = "ap-northeast-1"
confirm_changeset = true
capabilities = "CAPABILITY_IAM"
disable_rollback = true
image_repositories = []

[default.global.parameters]
region = "ap-northeast-1"</code></pre>
<blockquote>
<p><strong><code>samconfig.toml</code> の置き場所：</strong><br /><code>cognito-api-lambda/</code> フォルダの<strong>直下</strong>に置く必要があります。</p>
</blockquote>
<hr>
<h2><span id="toc15">Step 5: sam build（ビルド）</span></h2>
<pre><code class="language-cmd">cd C:\my-aws\aws-learning-projects\cognito-api-lambda
sam build</code></pre>
<p>成功すると以下のように表示されます。</p>
<pre><code class="language-plaintext">Build Succeeded

Built Artifacts  : .aws-sam/build
Built Template   : .aws-sam/build/template.yaml</code></pre>
<blockquote>
<p><strong><code>sam build</code> が行っていること：</strong></p>
<ul>
<li><code>src/</code> フォルダを ZIP パッケージ化して <code>.aws-sam/build/</code> に配置</li>
<li><code>template.yaml</code> を <code>.aws-sam/build/template.yaml</code> にコピー</li>
<li>Lambda デプロイの準備を整える</li>
</ul>
</blockquote>
<hr>
<h2><span id="toc16">Step 6: sam deploy（デプロイ）</span></h2>
<pre><code class="language-cmd">sam deploy</code></pre>
<p>変更内容が表示されて確認を求められます。</p>
<pre><code class="language-plaintext">Deploy this changeset? [y/N]: y</code></pre>
<p><code>y</code> を入力して進めます。数分でデプロイが完了します。</p>
<h3><span id="toc17">デプロイ完了の確認</span></h3>
<p>ターミナルに <strong>Outputs</strong> が表示されます。</p>
<pre><code class="language-plaintext">Outputs
----------------------------------------------------------------------
Key    ApiUrl
Value  https://XXXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/Prod

Key    UserPoolId
Value  ap-northeast-1_XXXXXXXX

Key    UserPoolClientId
Value  XXXXXXXXXXXXXXXXXXXXXXXXXX
----------------------------------------------------------------------</code></pre>
<p><strong>3つの値を全て控えておきます。</strong>（テスト実行コマンドで使用）</p>
<h3><span id="toc18">デプロイされるリソース一覧</span></h3>
<pre><code class="language-plaintext">Cognito User Pool × 1              : cognito-api-lambda-stack-user-pool
Cognito User Pool Client × 1       : シークレットなし（ALLOW_USER_PASSWORD_AUTH 有効）
API Gateway REST API × 1           : cognito-api-lambda-stack + Prod ステージ
Lambda 関数 × 1                    : cognito-api-lambda-stack-ApiFunction-XXXX
IAM ロール × 1                     : Lambda 実行ロール
S3                                 : SAM デプロイパッケージ
CloudWatch Logs                    : Lambda 自動生成ログ × 1</code></pre>
<hr>
<h2><span id="toc19">Step 7: 動作テスト</span></h2>
<h3><span id="toc20">事前準備: 変数を設定する</span></h3>
<pre><code class="language-cmd">set API_URL=https://XXXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/Prod
set USER_POOL_ID=ap-northeast-1_XXXXXXXX
set CLIENT_ID=XXXXXXXXXXXXXXXXXXXXXXXXXX</code></pre>
<hr>
<h3><span id="toc21">テスト1: テストユーザーを作成する</span></h3>
<pre><code class="language-cmd">aws cognito-idp admin-create-user ^
  --user-pool-id %USER_POOL_ID% ^
  --username test@example.com ^
  --region ap-northeast-1</code></pre>
<p>ユーザーが FORCE_CHANGE_PASSWORD 状態で作成されます。次のコマンドで永続パスワードを設定して CONFIRMED 状態にします。</p>
<pre><code class="language-cmd">aws cognito-idp admin-set-user-password ^
  --user-pool-id %USER_POOL_ID% ^
  --username test@example.com ^
  --password TestPass1 ^
  --permanent ^
  --region ap-northeast-1</code></pre>
<p>レスポンスなし（エラーが出なければ成功）。</p>
<blockquote>
<p><strong>FORCE_CHANGE_PASSWORD 状態とは：</strong><br />Cognito で管理者が作成したユーザーの初期状態です。この状態で <code>initiate-auth</code> を実行すると <code>NEW_PASSWORD_REQUIRED</code> チャレンジが返されてトークンが取得できません。<code>--permanent</code> フラグを付けて <code>admin-set-user-password</code> を実行することで CONFIRMED（認証済み）状態に変えられます。</p>
</blockquote>
<hr>
<h3><span id="toc22">テスト2: 公開エンドポイントのテスト（/hello）→ 200</span></h3>
<pre><code class="language-cmd">curl %API_URL%/hello</code></pre>
<p>期待するレスポンス:</p>
<pre><code class="language-json">{"message": "Hello! This is a public endpoint."}</code></pre>
<hr>
<h3><span id="toc23">テスト3: 未認証でプライベートエンドポイント（/profile）→ 401</span></h3>
<pre><code class="language-cmd">curl %API_URL%/profile</code></pre>
<p>期待するレスポンス（API Gateway が返す。Lambda は呼ばれていない）:</p>
<pre><code class="language-json">{"message": "Unauthorized"}</code></pre>
<hr>
<h3><span id="toc24">テスト4: IDトークンを取得する</span></h3>
<pre><code class="language-cmd">aws cognito-idp initiate-auth ^
  --auth-flow USER_PASSWORD_AUTH ^
  --auth-parameters "USERNAME=test@example.com,PASSWORD=TestPass1" ^
  --client-id %CLIENT_ID% ^
  --region ap-northeast-1</code></pre>
<p>レスポンス例（抜粋）:</p>
<pre><code class="language-json">{
    "AuthenticationResult": {
        "IdToken": "eyJra...",
        "AccessToken": "eyJra...",
        "RefreshToken": "eyJjb...",
        "ExpiresIn": 3600,
        "TokenType": "Bearer"
    }
}</code></pre>
<p><strong><code>IdToken</code> の値をコピーします</strong>（次のテストで使用）。</p>
<blockquote>
<p><strong>IdToken と AccessToken の違い：</strong></p>
<table>
<thead>
<tr>
<th>トークン</th>
<th>用途</th>
<th>JWT ペイロード</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>IdToken</strong></td>
<td>ユーザー認証（今回使用）</td>
<td>email / sub など</td>
</tr>
<tr>
<td>AccessToken</td>
<td>Cognito API へのアクセス</td>
<td>sub / scope など</td>
</tr>
</tbody>
</table>
<p>API Gateway の Cognito Authorizer に渡すのは <strong>IdToken</strong>。AccessToken を渡すと 403 になります。</p>
</blockquote>
<hr>
<h3><span id="toc25">テスト5: 認証ありでプライベートエンドポイント（/profile）→ 200</span></h3>
<pre><code class="language-cmd">set ID_TOKEN=eyJra...（上記で取得した IdToken の値）</code></pre>
<pre><code class="language-cmd">curl -H "Authorization: %ID_TOKEN%" %API_URL%/profile</code></pre>
<blockquote>
<p><strong>重要：</strong> <code>Bearer</code> プレフィックスは不要です。raw JWT（<code>eyJra...</code>）をそのまま Authorization ヘッダーに指定してください。</p>
</blockquote>
<p>期待するレスポンス:</p>
<pre><code class="language-json">{
  "message": "認証成功",
  "email": "test@example.com",
  "sub": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "token_use": "id"
}</code></pre>
<p><!-- ![認証成功レスポンス（SAM版）](images/cognito-sam-auth-success.jpg) --></p>
<hr>
<h2><span id="toc26">Step 8: AWSコンソールで確認（任意）</span></h2>
<p>SAM でデプロイしたリソースはコンソールでも確認できます。</p>
<ul>
<li><strong>API Gateway</strong>: APIs → <code>cognito-api-lambda-stack</code> → オーソライザー → <code>CognitoAuthorizer</code> が作成されていることを確認</li>
<li><strong>Cognito</strong>: ユーザープール → 作成された User Pool → ユーザー一覧で <code>test@example.com</code> が「確認済み」になっていることを確認</li>
<li><strong>Lambda</strong>: Lambda → 関数 → <code>cognito-api-lambda-stack-ApiFunction-XXXX</code> → 「モニタリング」タブ → テスト5実行後に呼び出し回数が増加していることを確認</li>
</ul>
<hr>
<h2><span id="toc27">Step 9: リソースの削除</span></h2>
<p><strong>課金を止めるために、ハンズオン完了後は必ずリソースを削除してください。</strong></p>
<pre><code class="language-cmd">sam delete --stack-name cognito-api-lambda-stack --region ap-northeast-1</code></pre>
<p>対話式で確認が入ります。両方 <code>y</code> で進めます。</p>
<pre><code class="language-plaintext">Are you sure you want to delete the stack cognito-api-lambda-stack? [y/N]: y
Are you sure you want to delete the folder cognito-api-lambda-stack in S3? [y/N]: y</code></pre>
<h3><span id="toc28">削除完了の確認</span></h3>
<pre><code class="language-cmd">aws cloudformation describe-stacks --stack-name cognito-api-lambda-stack --region ap-northeast-1</code></pre>
<pre><code class="language-plaintext">An error occurred (ValidationError): Stack with id cognito-api-lambda-stack does not exist</code></pre>
<p>このメッセージが表示されれば削除完了です。</p>
<h3><span id="toc29">sam delete で削除されるリソース一覧</span></h3>
<table>
<thead>
<tr>
<th>リソース</th>
<th>数</th>
</tr>
</thead>
<tbody>
<tr>
<td>Cognito User Pool（ユーザーデータも削除される）</td>
<td>× 1</td>
</tr>
<tr>
<td>Cognito User Pool Client</td>
<td>× 1</td>
</tr>
<tr>
<td>API Gateway REST API（ステージ含む）</td>
<td>× 1</td>
</tr>
<tr>
<td>Lambda 関数</td>
<td>× 1</td>
</tr>
<tr>
<td>IAM ロール</td>
<td>× 1</td>
</tr>
<tr>
<td>Lambda デプロイパッケージ（S3）</td>
<td>× 1</td>
</tr>
<tr>
<td>CloudWatch Logs ロググループ</td>
<td>× 1</td>
</tr>
</tbody>
</table>
<blockquote>
<p><strong>コンソール版との大きな違い（SAMのメリット）：</strong><br />コンソール版では API Gateway / Lambda / Cognito / IAM ロール / ロググループを個別に削除する必要があります。<br /><strong>SAMでは <code>sam delete</code> 1コマンドで全リソースを一括削除できます。</strong></p>
</blockquote>
<hr>
<h2><span id="toc30">トラブルシューティング</span></h2>
<table>
<thead>
<tr>
<th>症状</th>
<th>原因</th>
<th>対処</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>sam build</code> が失敗する</td>
<td><code>src/app.py</code> が存在しない</td>
<td><code>src/</code> フォルダに <code>app.py</code> があるか確認</td>
</tr>
<tr>
<td><code>sam deploy</code> が <code>CAPABILITY_IAM</code> エラー</td>
<td><code>samconfig.toml</code> の設定漏れ</td>
<td><code>capabilities = &quot;CAPABILITY_IAM&quot;</code> が含まれているか確認</td>
</tr>
<tr>
<td><code>sam deploy</code> が <code>Missing --stack-name</code> エラー</td>
<td><code>samconfig.toml</code> がない、または場所が違う</td>
<td><code>cognito-api-lambda/</code> 直下に <code>samconfig.toml</code> を作成する</td>
</tr>
<tr>
<td><code>initiate-auth</code> で <code>NotAuthorizedException: Incorrect username or password</code></td>
<td>ユーザーが FORCE_CHANGE_PASSWORD 状態</td>
<td><code>admin-set-user-password --permanent</code> で CONFIRMED にする</td>
</tr>
<tr>
<td><code>initiate-auth</code> で <code>InvalidParameterException</code></td>
<td><code>ALLOW_USER_PASSWORD_AUTH</code> が無効</td>
<td><code>sam deploy</code> で <code>UserPoolClient</code> が正しく作成されているか確認</td>
</tr>
<tr>
<td><code>/profile</code> に IDトークンを送っても 401</td>
<td><code>Bearer TOKEN</code> 形式で送っている</td>
<td>raw JWT（<code>eyJra...</code>）をそのまま Authorization ヘッダーに指定する</td>
</tr>
<tr>
<td><code>/profile</code> に IDトークンを送っても 403</td>
<td>IDトークンが期限切れ（1時間で失効）</td>
<td><code>initiate-auth</code> で新しいトークンを取得し直す</td>
</tr>
<tr>
<td><code>/profile</code> に IDトークンを送っても 403</td>
<td>AccessToken を使っている（IdToken ではない）</td>
<td><code>AuthenticationResult.IdToken</code> を使用しているか確認</td>
</tr>
<tr>
<td>Lambda の <code>claims</code> が空</td>
<td>AccessToken を使っている</td>
<td><code>IdToken</code> を Authorization ヘッダーに指定する</td>
</tr>
<tr>
<td>テストで <code>executionArn</code> が同じ名前で失敗する</td>
<td><code>admin-create-user</code> で <code>UsernameExistsException</code></td>
<td>すでに作成済みのためスキップして問題なし</td>
</tr>
</tbody>
</table>
<hr>
<h2><span id="toc31">まとめ</span></h2>
<p>今回のハンズオンで実現したこと：</p>
<table>
<thead>
<tr>
<th>確認項目</th>
<th>内容</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>SAM での Cognito 定義</strong></td>
<td><code>UserPool</code> + <code>UserPoolClient</code>（シークレットなし）を template.yaml で管理</td>
</tr>
<tr>
<td><strong>DefaultAuthorizer</strong></td>
<td>全エンドポイントに Cognito 認証を一括適用。<code>Authorizer: NONE</code> で /hello を除外</td>
</tr>
<tr>
<td><strong>JWT 認証フロー</strong></td>
<td>CLI で IDトークンを取得 → Authorization ヘッダーに指定 → claims を返す</td>
</tr>
<tr>
<td><strong>一括削除</strong></td>
<td><code>sam delete</code> で Cognito / API Gateway / Lambda を全てクリーンアップ</td>
</tr>
</tbody>
</table>
<h3><span id="toc32">SAMのメリットを実感できたポイント</span></h3>
<ul>
<li><code>GenerateSecret: false</code> + <code>ExplicitAuthFlows</code> でシークレットなしクライアントを定義（コンソール版では SPA タイプのクライアントを別途手動作成）</li>
<li><code>DefaultAuthorizer</code> の1行で全エンドポイントに Cognito 認証を適用（コンソール版では各エンドポイントに手動設定）</li>
<li><code>UserPoolArn: !GetAtt UserPool.Arn</code> で Cognito Authorizer と User Pool を自動連携（コンソール版では手動選択 + トークンのソースを手入力）</li>
</ul>
<hr>
<h2><span id="toc33">コンソール版と比較してみる</span></h2>
<p>SAMが裏で何をやっているか、同じ構成をAWSコンソールのみで構築する手順をまとめました。Cognitoの新UIで変わった操作（「アプリケーションを作成」からのウィザード、シークレットなしクライアントの作成方法、Authorizer のトークンソース設定）など、コンソール版ならではのつまずきポイントを解説しています。</p>
<p><!-- TODO: コンソール版記事へのリンクを追加 --></p>
<hr>
<h2><span id="toc34">関連記事</span></h2>
<p><a rel="nofollow" href="//af.moshimo.com/af/c/click?a_id=1384942&p_id=170&pc_id=185&pl_id=4062&url=https%3A%2F%2Fwww.amazon.co.jp%2Fs%3Fk%3D%25E6%259C%25AC%2BAWS%2B%25E9%2596%258B%25E7%2599%25BA%26__mk_ja_JP%3D%25E3%2582%25AB%25E3%2582%25BF%25E3%2582%25AB%25E3%2583%258A%26crid%3D1DE63UBHFOR4K%26sprefix%3D%25E6%259C%25AC%2Baws%2B%25E9%2596%258B%25E7%2599%25BA%252Caps%252C167%26ref%3Dnb_sb_noss" referrerpolicy="no-referrer-when-downgrade" attributionsrc>Amazon検索[本 AWS 開発]</a><img decoding="async" src="//i.moshimo.com/af/i/impression?a_id=1384942&p_id=170&pc_id=185&pl_id=4062" width="1" height="1" style="border:none;" alt="" loading="lazy"></p>
<p><!-- START MoshimoAffiliateEasyLink --><script type="text/javascript">(function(b,c,f,g,a,d,e){b.MoshimoAffiliateObject=a;b[a]=b[a]||function(){arguments.currentScript=c.currentScript||c.scripts[c.scripts.length-2];(b[a].q=b[a].q||[]).push(arguments)};c.getElementById(a)||(d=c.createElement(f),d.src=g,d.id=a,e=c.getElementsByTagName("body")[0],e.appendChild(d))})(window,document,"script","//dn.msmstatic.com/site/cardlink/bundle.js?20220329","msmaflink");msmaflink({"n":"AWS運用入門 改訂第2版 押さえておきたいAWSの基本と運用ノウハウ [AWS深掘りガイド]","b":"SBクリエイティブ","t":"","d":"https:\/\/m.media-amazon.com","c_p":"\/images\/I","p":["\/51AAOubymTL._SL500_.jpg","\/51VMG6YKHdL._SL500_.jpg","\/41EdPB8azAL._SL500_.jpg","\/41v2JFE-9jL._SL500_.jpg","\/41FEEqR-yDL._SL500_.jpg","\/41JfZAdnTPL._SL500_.jpg","\/41vGK0czQrL._SL500_.jpg","\/41-SnYtz2aL._SL500_.jpg","\/41sPrV5fi3L._SL500_.jpg","\/41p7JtvYJ1L._SL500_.jpg","\/4169GVNTs8L._SL500_.jpg","\/41BPI5HP3zL._SL500_.jpg","\/41QOyk60CYL._SL500_.jpg","\/41APjk6FphL._SL500_.jpg","\/41ezKUu7VRL._SL500_.jpg","\/41A1n3K+r5L._SL500_.jpg","\/41aY2T8lEOL._SL500_.jpg","\/419Ca1V6HZL._SL500_.jpg","\/41zQkYyLPzL._SL500_.jpg","\/41YpHcyxiTL._SL500_.jpg","\/41-tKN5mt6L._SL500_.jpg","\/419Mv6m55IL._SL500_.jpg"],"u":{"u":"https:\/\/www.amazon.co.jp\/dp\/4815631085","t":"amazon","r_v":""},"v":"2.1","b_l":[{"id":1,"u_tx":"Amazonで見る","u_bc":"#f79256","u_url":"https:\/\/www.amazon.co.jp\/dp\/4815631085","a_id":1384942,"p_id":170,"pl_id":27060,"pc_id":185,"s_n":"amazon","u_so":1},{"id":2,"u_tx":"楽天市場で見る","u_bc":"#f76956","u_url":"https:\/\/search.rakuten.co.jp\/search\/mall\/AWS%E9%81%8B%E7%94%A8%E5%85%A5%E9%96%80%20%E6%94%B9%E8%A8%82%E7%AC%AC2%E7%89%88%20%E6%8A%BC%E3%81%95%E3%81%88%E3%81%A6%E3%81%8A%E3%81%8D%E3%81%9F%E3%81%84AWS%E3%81%AE%E5%9F%BA%E6%9C%AC%E3%81%A8%E9%81%8B%E7%94%A8%E3%83%8E%E3%82%A6%E3%83%8F%E3%82%A6%20%5BAWS%E6%B7%B1%E6%8E%98%E3%82%8A%E3%82%AC%E3%82%A4%E3%83%89%5D\/","a_id":1384917,"p_id":54,"pl_id":27059,"pc_id":54,"s_n":"rakuten","u_so":2},{"id":3,"u_tx":"Yahoo!ショッピングで見る","u_bc":"#66a7ff","u_url":"https:\/\/shopping.yahoo.co.jp\/search?first=1\u0026p=AWS%E9%81%8B%E7%94%A8%E5%85%A5%E9%96%80%20%E6%94%B9%E8%A8%82%E7%AC%AC2%E7%89%88%20%E6%8A%BC%E3%81%95%E3%81%88%E3%81%A6%E3%81%8A%E3%81%8D%E3%81%9F%E3%81%84AWS%E3%81%AE%E5%9F%BA%E6%9C%AC%E3%81%A8%E9%81%8B%E7%94%A8%E3%83%8E%E3%82%A6%E3%83%8F%E3%82%A6%20%5BAWS%E6%B7%B1%E6%8E%98%E3%82%8A%E3%82%AC%E3%82%A4%E3%83%89%5D","a_id":1466950,"p_id":1225,"pl_id":27061,"pc_id":1925,"s_n":"yahoo","u_so":3}],"eid":"E8MM1","s":"s"});</script></p>
<div id="msmaflink-E8MM1">リンク</div>
<p><!-- MoshimoAffiliateEasyLink END --></p><p>The post <a href="https://caymezon.com/aws-handson-cognito-api-gateway-lambda/">AWSハンズオン - Cognito + API Gateway + Lambda で認証付きAPIをSAMで構築しよう【コンソール版との比較付き】</a> first appeared on <a href="https://caymezon.com">CayTech Lab</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://caymezon.com/aws-handson-cognito-api-gateway-lambda/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
