API Gateway と Cognito 認証の関係（メモ）

## ✨ はじめに
AWS で API を公開する際、**認証・認可の仕組み** をどのように構築するかは非常に重要です。
その中で **Amazon API Gateway** と **Amazon Cognito** を組み合わせることで、安全な認証機能を実現できます。

本記事では、API Gateway と Cognito 認証の関係について詳しく解説し、どのように連携するのかを明確にします。

---

## 🎯 API Gateway と Cognito 認証の関係
### ▶️ **結論：API Gateway が Cognito に紐づいている**
API Gateway は、Cognito ユーザープールを利用して認証を行い、
**Cognito の発行する JWT トークンを検証し、アクセスを許可・拒否する** 役割を持ちます。

つまり、 **Cognito は API Gateway に紐づいているのではなく、API Gateway が Cognito に紐づいている** 形となります。

| ※ 役割 | ※ 説明 |
|------------|------------|
| **Cognito ユーザープール** | ユーザーの認証を管理し、アクセストークン (`AccessToken`) を発行 |
| **API Gateway** | Cognito の発行したトークンを検証し、Lambda などのバックエンドへリクエストを転送 |


## 🔍 具体的な動作の流れ

1. **クライアントが Cognito にログイン**
   - ユーザーが Cognito に対してログインを行い、**アクセストークン (`AccessToken`)** を取得。

2. **API Gateway にリクエストを送信**
   - クライアントは API を呼び出す際に、HTTP ヘッダー `Authorization: Bearer <TOKEN>` を付与。

3. **API Gateway が Cognito にトークンの検証を依頼**
   - `AccessToken` が正しいかチェック。
   - **有効なトークン** なら、Lambda 関数などのバックエンドへリクエストを転送。
   - **無効なトークン** なら、`401 Unauthorized` を返す。

4. **Lambda 関数が処理を実行し、レスポンスを返す**

```
(1) クライアントが Cognito にログイン
    ┌──────────┐
    │ Cognito  │
    └────┬─────┘
         │ (2) JWT トークンを発行 (AccessToken)
         ▼
 ┌──────────────────┐
 │ クライアント (例: cURL, アプリ) │
 └──────────┬─────┘
            │ (3) API リクエスト時に `Authorization: Bearer <TOKEN>` を送信
            ▼
 ┌──────────────────┐
 │  API Gateway     │  ⇦ Cognito 認証に紐づいている
 └────┬───────────┘
      │ (4) トークンを検証 (Cognito)
      ▼
 ┌──────────────────┐
 │ Lambda 関数      │
 └──────────────────┘

```


## 🗃️ API Gateway で Cognito 認証を適用する設定
API Gateway に Cognito 認証 (`CognitoAuthorizer`) を適用するには、
`template.yaml` に次のような設定を追加します。

```yaml
ShitadanApi:
  Type: AWS::Serverless::Api
  Properties:
    Name: ShitadanApi
    StageName: Prod
    Cors:
      AllowMethods: "'POST,OPTIONS'"
      AllowHeaders: "'Content-Type,Authorization'"
      AllowOrigin: "'*'"
    Auth:
      DefaultAuthorizer: CognitoAuthorizer
      Authorizers:
        CognitoAuthorizer:
          UserPoolArn: !Sub "arn:aws:cognito-idp:${AWS::Region}:${AWS::AccountId}:userpool/YOUR_USER_POOL_ID"
```

### **この設定のポイント**
✅ **API Gateway に Cognito 認証 (`CognitoAuthorizer`) を設定**
✅ **トークンを持っていないリクエストは `401 Unauthorized` で拒否**
✅ **適切なトークンを持つユーザーだけが API を利用可能**


## 🛠️ クライアント側のトークン取得 & API 呼び出し
### **1. Cognito から `AccessToken` を取得**

```sh
ACCESS_TOKEN=$(curl -X POST \
    -H "Content-Type: application/x-amz-json-1.1" \
    -H "X-Amz-Target: AWSCognitoIdentityProviderService.InitiateAuth" \
    --data @- https://cognito-idp.ap-northeast-1.amazonaws.com/ <<EOF | jq -r '.AuthenticationResult.AccessToken'
{
    "AuthFlow": "USER_PASSWORD_AUTH",
    "ClientId": "your-app-client-id",
    "AuthParameters": {
        "USERNAME": "your_username",
        "PASSWORD": "your_password"
    }
}
EOF
)
```

### **2. API Gateway にリクエストを送信**

```sh
curl -X POST \
    -H "Authorization: Bearer $ACCESS_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{"source_bucket": "shitadan", "pdf_prefix": "api/receipts/r6/pdf/", "upload_prefix": "api/receipts/r6/jpeg/"}' \
    https://your-api-id.execute-api.ap-northeast-1.amazonaws.com/Prod/convert
```


## 📊 まとめ
✅ **API Gateway が Cognito に紐づいている (Cognito は API Gateway に依存しない)**  
✅ **API Gateway は Cognito の `AccessToken` を検証し、正当なリクエストのみ処理を転送**  
✅ **適切な `template.yaml` の設定で Cognito 認証を簡単に適用可能**  
✅ **トークンを取得 → API に `Authorization` ヘッダーを付けてリクエストを送信する仕組み**  

この構成を利用することで、**安全でスケーラブルな API 認証基盤** を構築できます！ 🚀