---
title: "API Gatewayの認証：Cognito・JWT・Lambdaオーソライザー・IAM認可の使い分けと設定例"
url: "https://www.issoh.co.jp/tech/details/18493/"
published: 2026-10-18
updated: 2026-10-18
categories: ["AWS"]
publisher: "株式会社一創"
---

# API Gatewayの認証：Cognito・JWT・Lambdaオーソライザー・IAM認可の使い分けと設定例

Amazon API Gatewayで「認証付きのAPI」を作る方法は、Cognitoオーソライザー、JWTオーソライザー、Lambdaオーソライザー、IAM認可の4つです。どれが使えるかはREST APIかHTTP APIかで変わり、同じCognitoのトークンでもIDトークンとアクセストークンでは判定の仕方が異なる仕様です。本記事では、4方式の対応範囲を表で整理し、CLIとPythonの設定例で動かすところまで示したうえで、認可キャッシュで別のメソッドが403になる落とし穴と、方式を選ぶ条件を言い切ります。API Gateway自体の役割は[APIゲートウェイの役割と導入判断](https://www.issoh.co.jp/tech/details/13210/)で整理しています。

## まとめ：利用者向けはCognitoかJWT、システム間はIAM、例外だけLambda

ブラウザやスマートフォンアプリから一般利用者が呼ぶAPIなら、REST APIはCognitoオーソライザー、HTTP APIはJWTオーソライザーで足ります。どちらもトークンの署名と有効期限をAPI Gatewayが検証し、無効なリクエストはバックエンドに届く前に401で返ります。社内システムやLambda同士の呼び出しは、IAMロールで署名するIAM認可が手間もコストも小さい方式です。

Lambdaオーソライザーは、Cognito以外のIdPをREST APIで使う、ヘッダーとパスの組み合わせで判定する、といった上の3方式で表せない条件のときに限って選びます。自前で書く分だけ、キャッシュの設計と500エラーの切り分けを背負うからです。どの方式でも、オーソライザーが判定するのは「正しい利用者か」までです。そのユーザーが当該データを読んでよいかは、アプリケーション側で確かめる必要があります。

## API Gatewayの認証方式4種と、REST API・HTTP APIごとの対応範囲

最初に、どのAPI種別でどの方式が使えるかを確定させます。ここを間違えると、設定画面に目当ての項目が出てきません。

### 4方式が受け取るもの・判定する主体・対応API種別を1つの表で比較

[REST APIとHTTP APIの比較表（公式）](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-vs-rest.html)の認可オプションを、クライアントが送るものと合わせて並べると次のとおりです（2026年10月時点）。

| 方式             | REST API | HTTP API     | クライアントが送るもの             | 向く呼び出し元               |
| -------------- | -------- | ------------ | ----------------------- | --------------------- |
| Cognitoオーソライザー | 対応       | JWTオーソライザー経由 | CognitoのIDトークンかアクセストークン | 一般利用者のWeb・アプリ         |
| JWTオーソライザー     | 非対応      | 対応           | OIDC・OAuth 2.0のJWT      | Cognito・Entra ID等の利用者 |
| Lambdaオーソライザー  | 対応       | 対応           | 任意のトークンやヘッダー            | 独自の判定条件がある場合          |
| IAM認可          | 対応       | 対応           | SigV4署名付きリクエスト          | AWS内のシステム間            |

読み取るべきは2点です。REST APIにはJWTオーソライザーが無く、Cognito以外のIdPのJWTを検証するにはLambdaオーソライザーを書くことになります。逆にHTTP APIには「Cognito」という種別が無く、CognitoのIssuer URLをJWTオーソライザーに登録して使います。

### APIキーとリソースポリシーを認証方式に数えないほうがよい理由

設定画面で隣に並ぶAPIキーは、呼び出し量を数えて制限するための識別子です。同じ使用量プランに入った別のAPIまで呼べてしまうため、認可の手段にはなりません。詳細は[API GatewayのAPIキーと使用量プランの設定](https://www.issoh.co.jp/tech/details/18491/)で解説しています。

リソースポリシーはREST API限定で、送信元のIPアドレスやVPCエンドポイントで絞る仕組みです。「どこから来たか」は判定できても「誰か」は判定しません。IP制限の組み方は[API GatewayのIP制限の手順と使い分け](https://www.issoh.co.jp/tech/details/18487/)にまとめています。どちらも、本記事の4方式に重ねて使う前提の部品です。

## CognitoオーソライザーをREST APIのメソッドに付け、IDトークンで呼び出す手順

ユーザープールとアプリクライアントは作成済みとして進めます。まだの場合は[Cognitoのユーザープール構築からJWT検証までの手順](https://www.issoh.co.jp/tech/details/17445/)で用意し、同記事にある`create-authorizer`でオーソライザーを作っておいてください。

### update-methodで認証を設定し再デプロイ後にcurlで401と200を確認

オーソライザーは作っただけでは効きません。メソッドの`authorizationType`と`authorizerId`を書き換え、ステージへ再デプロイして初めて反映されます。[Cognitoオーソライザーの公式手順](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-enable-cognito-user-pool.html)も、変更後の再デプロイを必須としています。

```
# GET /orders に Cognito オーソライザー（ID: abc123）を付ける
aws apigateway update-method --region ap-northeast-1 \
  --rest-api-id abcde12345 --resource-id r1s2t3 --http-method GET \
  --patch-operations \
    op=replace,path=/authorizationType,value=COGNITO_USER_POOLS \
    op=replace,path=/authorizerId,value=abc123

# 変更をステージに反映する（ここを忘れると認証なしで通り続ける）
aws apigateway create-deployment --region ap-northeast-1 \
  --rest-api-id abcde12345 --stage-name prod

# トークンなしは 401、IDトークン付きは 200 になることを確かめる
URL=https://abcde12345.execute-api.ap-northeast-1.amazonaws.com/prod/orders
curl -s -o /dev/null -w "%{http_code}\n" "$URL"
curl -s -o /dev/null -w "%{http_code}\n" -H "Authorization: $ID_TOKEN" "$URL"
```

Cognitoオーソライザーのトークンの読み取り元は、作成時の`--identity-source`で指定したヘッダー（通常は`Authorization`）です。1つのオーソライザーに登録できるユーザープールは最大1,000で、この上限は引き上げられません。

### スコープを指定するとアクセストークン判定に切り替わる仕様と401の原因

Cognitoオーソライザーは、メソッドに認可スコープを設定したかどうかで、受け取ったトークンの扱いを変えます。スコープが空ならIDトークンとして検証し、スコープを設定するとアクセストークンとして扱い、トークン内のスコープがメソッドのスコープのどれかと一致しなければ401を返します。

```
# アクセストークンの orders/read スコープを要求する（設定後は再デプロイ）
aws apigateway update-method --region ap-northeast-1 \
  --rest-api-id abcde12345 --resource-id r1s2t3 --http-method GET \
  --patch-operations op=add,path=/authorizationScopes,value=orders/read
```

この仕様が原因の401は3パターンに分かれます。スコープ未設定のメソッドにアクセストークンを送る、トークン検証欄に`aud`の正規表現を入れたままアクセストークンを送る（アクセストークンには`aud`が無いため拒否される）、コンソールのテスト呼び出しにアクセストークンを使う（テストはIDトークンのみ対応）、の3つです。外部のバックエンドへ委譲する権限を表すならアクセストークンとスコープ、画面に名前を出す程度ならIDトークン、と役割で分けてください。トークンの構造は[JWTの構造と署名検証の仕組み](https://www.issoh.co.jp/tech/details/13453/)で確認できます。

## HTTP APIのJWTオーソライザーをCognitoや外部IdPのトークンで設定する手順

HTTP APIでは、IdPの種類を問わずJWTオーソライザーを使います。登録するのは発行者（Issuer）と受け手（Audience）の2つだけです。

### IssuerとAudienceを指定してJWT認証をルートに設定するCLIの実行例

CLIでは`create-authorizer`にIssuerとAudienceを渡し、続いて`update-route`で作成したオーソライザーをルートに設定します。

[JWTオーソライザーの公式解説](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-jwt-authorizer.html)によると、Cognitoを使う場合のIssuerは`https://cognito-idp.<リージョン>.amazonaws.com/<ユーザープールID>`の形式です。

```
# Cognito ユーザープールを発行者、アプリクライアントIDを受け手として登録する
aws apigatewayv2 create-authorizer --region ap-northeast-1 \
  --api-id a1b2c3d4e5 --name cognito-jwt \
  --authorizer-type JWT \
  --identity-source '$request.header.Authorization' \
  --jwt-configuration Audience=1example23456789,Issuer=https://cognito-idp.ap-northeast-1.amazonaws.com/ap-northeast-1_EXAMPLE

# ルートに付け、アクセストークンの orders/read スコープを必須にする
aws apigatewayv2 update-route --region ap-northeast-1 \
  --api-id a1b2c3d4e5 --route-id xyz789 \
  --authorization-type JWT --authorizer-id def456 \
  --authorization-scopes orders/read
```

HTTP APIは自動デプロイを有効にしたステージなら再デプロイが要りません。トークンは`Bearer `を付けても付けなくても受け付けられます。CognitoのアクセストークンにはAudienceを表す`aud`が無く`client_id`が入っていますが、JWTオーソライザーは`aud`が無いときに`client_id`を照合するため、アプリクライアントIDをAudienceに登録すれば通ります。

### JWTオーソライザーが検証する7クレームと公開鍵キャッシュ最大2時間の影響

JWTオーソライザーは、署名の検証に加えて`kid`、`iss`、`aud`（無ければ`client_id`）、`exp`、`nbf`、`iat`、`scope`（または`scp`）の7項目を確かめ、1つでも外れれば拒否します。署名アルゴリズムはRSA系のみの対応で、HS256で署名する自前のIdPはそのままでは使えません。

運用で効いてくるのは公開鍵のキャッシュです。API GatewayはIssuerの`jwks_uri`から取った公開鍵をベストエフォートで最大2時間保持します。IdP側で署名鍵を入れ替えるときは、新旧の鍵がどちらも有効な期間を2時間以上取ってください。呼び出し頻度の低いAPIほどキャッシュが切れやすく、その都度の鍵の取得が初回リクエストの遅延になります。

公式は、IDトークンとアクセストークンを見分ける標準の仕組みが無いことから、IDトークンでの認可が必要な場合を除き、ルートにスコープを必須にするよう推奨しています。スコープを付けないルートでは、同じIssuerとAudienceのIDトークンでも通る点を覚えておいてください。

## Lambdaオーソライザーの自前実装でのTOKEN・REQUEST選択とキャッシュ設計

Lambdaオーソライザーは、API Gatewayが呼び出し元の情報を関数に渡し、関数が返したIAMポリシーで許可か拒否かを決める方式です。自由度と引き換えに、設計を誤ったときの症状が分かりにくくなります。

### 外部IdPのJWTをREST APIで検証するPythonのREQUEST認証実装例

種類はトークン1つを受け取る`TOKEN`と、ヘッダー・クエリ文字列・ステージ変数・コンテキスト変数を組み合わせて受け取る`REQUEST`の2つです。[Lambdaオーソライザーの公式解説](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-use-lambda-authorizer.html)は、複数の識別ソースでキャッシュキーを分けられる`REQUEST`を推奨しています。次の例は、Auth0やEntra IDなど外部IdPのJWTを[PyJWTのPyJWKClient](https://pyjwt.readthedocs.io/en/stable/usage.html)で検証します。

```
import os

import jwt
from jwt import PyJWKClient

# IdP の JWKS エンドポイントから公開鍵を取得・キャッシュする（コールドスタート時に1回生成）
JWKS = PyJWKClient(os.environ["JWKS_URL"])
ISSUER = os.environ["ISSUER"]
AUDIENCE = os.environ["AUDIENCE"]


def lambda_handler(event, context):
    headers = {k.lower(): v for k, v in (event.get("headers") or {}).items()}
    token = headers.get("authorization", "").removeprefix("Bearer ")
    try:
        key = JWKS.get_signing_key_from_jwt(token)
        claims = jwt.decode(token, key.key, algorithms=["RS256"],
                            audience=AUDIENCE, issuer=ISSUER)
    except jwt.PyJWTError:
        raise Exception("Unauthorized")  # API Gateway は 401 を返す

    # methodArn = arn:aws:execute-api:リージョン:アカウント:APIID/ステージ/メソッド/パス
    api_arn, stage = event["methodArn"].split("/")[:2]
    return {
        "principalId": claims["sub"],
        "policyDocument": {
            "Version": "2012-10-17",
            "Statement": [{
                "Action": "execute-api:Invoke",
                "Effect": "Allow",
                # キャッシュを効かせるため、このステージの全メソッドを許可する
                "Resource": f"{api_arn}/{stage}/*/*",
            }],
        },
        # 値は文字列化されてバックエンドに渡る（オブジェクトや配列は不可）
        "context": {"tenant": str(claims.get("tenant_id", ""))},
    }
```

関数を作ったら、`aws apigateway create-authorizer --type REQUEST --identity-source method.request.header.Authorization --authorizer-result-ttl-in-seconds 300`でオーソライザーとして登録し、`aws lambda add-permission`でAPI Gatewayからの呼び出しを許可します。この許可が無いと、利用者には500が返ります。

### 認可キャッシュTTL既定300秒・最大3600秒とmethodArn限定許可の落とし穴

認可キャッシュのTTLは[CreateAuthorizerのAPIリファレンス](https://docs.aws.amazon.com/apigateway/latest/api/API%5FCreateAuthorizer.html)で既定300秒、最大3600秒（1時間）、0で無効と定められています。キャッシュが効くと、同じトークンの2回目以降は関数が呼ばれず、保存済みのポリシーで判定されます。

典型的な失敗は、公式サンプルのとおりポリシーの`Resource`に`event["methodArn"]`だけを入れることです。最初に`GET /orders`を呼ぶと「`GET /orders`だけ許可」のポリシーがキャッシュされ、同じトークンで続けて`GET /users`を呼ぶと、関数が呼ばれないまま403になります。公式も、キャッシュを有効にするならAPI全体のメソッドに通用するポリシーを返し、メソッドごとに変えたいならキャッシュを切るよう書いています。上の例でワイルドカードを返しているのはこのためです。HTTP APIでルートごとにキャッシュを分けたい場合は、識別ソースに`$context.routeKey`を足します。

### 401・403・500の応答とLambdaオーソライザーのエラーログによる原因調査

エラーログには`$context.authorizer.error`を使い、応答コードと照合して原因を調べます。

Lambdaオーソライザーのステータスコードは、関数の終わり方で決まります。実務ではまず500を疑うと早く片付きます。

- 500：関数が`Unauthorized`以外の例外で終わった、戻り値の形式が不正、API Gatewayに関数の呼び出し権限が無い
- 401：関数が`Unauthorized`で終わった、またはキャッシュ有効時に識別ソースのヘッダーが欠けていて関数自体が呼ばれていない
- 403：関数が`Deny`のポリシーを返した、またはキャッシュ済みのポリシーが今回のメソッドを含んでいない

500の原因は、アクセスログの書式に`$context.authorizer.error`を加えると記録されます。アクセスログの設定手順は[API Gatewayのログ設定とX-Rayでの障害調査](https://www.issoh.co.jp/tech/details/18485/)を参照してください。401なのに関数のログが1行も無い場合は、識別ソースのヘッダー名の綴りを最初に確認します。

## IAM認可でSigV4署名を付け、社内システムやLambdaからAPIを呼び出す設定

呼び出し元がAWS上のLambdaやECSタスクなら、トークンを発行する仕組み自体が要りません。呼び出し元のIAMロールでリクエストに署名し、API GatewayがIAMで権限を確かめます。

### AWS\_IAMを付けたメソッドとexecute-api:Invokeで許可するポリシー例

メソッド側は`authorizationType`を`AWS_IAM`にし、再デプロイします（HTTP APIなら`aws apigatewayv2 update-route --authorization-type AWS_IAM`）。呼び出し元のロールには、[API呼び出しのIAMポリシー形式](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-control-access-using-iam-policies-to-invoke-api.html)に沿って`execute-api:Invoke`を付けます。

```
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Action": "execute-api:Invoke",
    "Resource": "arn:aws:execute-api:ap-northeast-1:123456789012:abcde12345/prod/GET/orders"
  }]
}
```

公式は、メソッドに`AWS_IAM`を設定しなければIAMポリシーは効かず、そのメソッドは公開状態になると注意しています。ポリシーを作っただけで守った気にならないよう、未署名のcurlが403になることを必ず確認してください。

### boto3の認証情報とbotocoreのSigV4Authで署名するPython例

署名の方式は[AWS Signature Version 4（公式）](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference%5Fsigv.html)で、サービス名には`execute-api`を指定します。Lambda上なら実行ロールの認証情報がそのまま使えます。

```
import urllib.request

import boto3
from botocore.auth import SigV4Auth
from botocore.awsrequest import AWSRequest

URL = "https://abcde12345.execute-api.ap-northeast-1.amazonaws.com/prod/orders"

# 実行ロール（またはローカルのプロファイル）の認証情報で署名ヘッダーを付ける
creds = boto3.Session().get_credentials()
req = AWSRequest(method="GET", url=URL)
SigV4Auth(creds, "execute-api", "ap-northeast-1").add_auth(req)

with urllib.request.urlopen(urllib.request.Request(URL, headers=dict(req.headers))) as res:
    print(res.status, res.read().decode())
```

キーの配布も失効の運用も不要で、権限の付け外しはIAMロールのポリシー変更だけで済みます。一方、ブラウザから直接呼ぶ構成ではAWSの認証情報を利用者に渡すことになるため、この方式は選びません。

## API Gatewayの認証方式を選ぶ条件と、オーソライザーを足さないほうがよい場面

ここまでの仕様を踏まえ、方式の選び方を条件で言い切ります。

### 呼び出し元が人かシステムか、IdPがCognitoかで決める判断の順番

1. 呼び出し元がAWS上のシステムなら、IAM認可にする。
2. 人が使う画面からの呼び出しで、IdPがCognitoなら、REST APIはCognitoオーソライザー、HTTP APIはJWTオーソライザーにする。
3. IdPがEntra IDやAuth0などのOIDC準拠で、RSA署名なら、HTTP APIのJWTオーソライザーにする。REST APIでしか使えない機能（WAFやAPIキー）が要るときだけ、REST APIとLambdaオーソライザーの組み合わせにする。
4. どれにも当てはまらない独自トークンや、ヘッダーとパスの組み合わせによる判定が必要なら、Lambdaオーソライザーを書く。

上から順に当てはめれば、ほとんどのAPIで選ぶ方式は1〜3のいずれかです。既存の社内IdPとのフェデレーションや、複数システムのID統合まで含めて設計する場合は、[認証基盤・ID管理システム開発](https://www.issoh.co.jp/service/system/identity/)でご相談いただけます。製品に依存しない方式選定やトークン寿命の決め方は[API認証の設計と方式選定マトリクス](https://www.issoh.co.jp/tech/details/17232/)にまとめています。

### Lambdaオーソライザーを見送る条件と、データ単位の認可をアプリに残す範囲

CognitoかJWTオーソライザーで済む要件に、Lambdaオーソライザーを選ぶのは過剰です。関数の実行時間とコールドスタートが認証の待ち時間に加わり、JWKSの取得やキャッシュ設計、500の切り分けまで自前で抱えます。「将来の要件に備えて」という理由だけでは選びません。

どの方式を選んでも、オーソライザーに任せられるのは「有効な利用者か」「このメソッドを呼べるロールか」までです。注文IDを書き換えて他人の注文を読む、といったデータ単位の認可は、トークンの`sub`や受け渡した`context`をバックエンドで照合しなければ防げません。オーソライザーに業務ルールまで詰め込むと、キャッシュとの整合が崩れて403が散発します。認証はゲートウェイ、データ単位の認可はアプリ、と線を引いてください。

## よくある質問

API Gatewayの認証設定で、よく出る疑問をまとめました。

### CognitoオーソライザーとJWTオーソライザーは何が違いますか？

CognitoオーソライザーはREST API専用で、Cognitoのユーザープールしか登録できません。JWTオーソライザーはHTTP API専用で、Cognitoを含むOIDC・OAuth 2.0準拠のIdPのIssuerを登録できます。挙動の差として、Cognitoオーソライザーはスコープ未設定ならIDトークンとして扱い、JWTオーソライザーはIssuerとAudienceが合えばトークンの種類を区別しません。どちらを使うかは、APIをRESTとHTTPのどちらで作るかで自動的に決まります。

### ログインできているのにアクセストークンで呼ぶと401になるのはなぜですか？

REST APIのCognitoオーソライザーで、メソッドに認可スコープを設定していないのが最も多い原因です。スコープ未設定のメソッドは受け取ったトークンをIDトークンとして検証するため、アクセストークンは通りません。アクセストークンで呼ぶならメソッドにスコープを設定して再デプロイし、トークン検証欄に`aud`の正規表現を入れている場合は外してください。

### 1つのAPIで認証が必要なルートと不要なルートを分けられますか？

認証が必要なルートと不要なルートは分離可能です。オーソライザーはREST APIならメソッド単位、HTTP APIならルート単位で付け外しするため、ヘルスチェック用のルートだけ認証なしにする構成は普通に組めます。REST APIでCORSの事前確認（`OPTIONS`）を受けるメソッドにオーソライザーを付けると、ブラウザの事前確認が401で失敗するので外しておきます。認証なしのルートを作るときは、意図せず公開していないかを一覧で確認してください。

### オーソライザーが検証した利用者の情報をバックエンドで受け取るには？

REST APIのCognitoオーソライザーは`$context.authorizer.claims`でトークンのクレームをマッピングテンプレートに渡せます。HTTP APIのJWTオーソライザーなら、Lambda統合のイベントの`requestContext.authorizer.jwt.claims`に入ります。Lambdaオーソライザーは返した`context`がプロキシ統合のイベントに渡りますが、値はすべて文字列化され、オブジェクトや配列は入れられません。

### オーソライザーを付けると追加料金はかかりますか？

API Gatewayの公式料金ページに、オーソライザー単体の課金項目は載っていません（2026年10月時点）。Lambdaオーソライザーは関数の実行としてLambdaの料金が掛かり、認可キャッシュを有効にすれば実行回数を減らせます。Cognitoは利用者数に応じた料金が別途必要です。API Gateway本体の単価差は[API Gatewayの料金を東京リージョンの実額で計算する記事](https://www.issoh.co.jp/tech/details/18477/)で比較しています。

## 関連記事

- [Cognitoで認証基盤を実装する手順：ユーザープール構築からJWT検証まで](https://www.issoh.co.jp/tech/details/17445/)：オーソライザーに登録するユーザープールとアプリクライアントの作り方。
- [APIゲートウェイとは？役割・機能とリバースプロキシ／サービスメッシュとの違い・導入判断を解説](https://www.issoh.co.jp/tech/details/13210/)：認証をゲートウェイに寄せる理由と導入判断。
- [API認証の設計｜方式選定マトリクスとトークン寿命・監査ログの決め方](https://www.issoh.co.jp/tech/details/17232/)：製品に依存しない方式選定とトークン寿命の決め方。
- [JWTとは？構造・署名検証の仕組みとセッション・OAuth/OIDCとの違いを実装視点で解説](https://www.issoh.co.jp/tech/details/13453/)：オーソライザーが検証するクレームと署名の仕組み。
- [API GatewayのAPIキー：使用量プランでスロットリングとクォータを設定する手順と認可に使わない理由](https://www.issoh.co.jp/tech/details/18491/)：認証の後段で呼び出し量を制限する設定。

---

出典: [API Gatewayの認証：Cognito・JWT・Lambdaオーソライザー・IAM認可の使い分けと設定例](<https://www.issoh.co.jp/tech/details/18493/>)（株式会社一創）
