はじめに
Amazon API Gatewayは複数の認証方式をサポートしています。
実際の開発では、
- フロントエンドなら、Cognito認証
- AWSサービス間通信なら、IAM認証(SigV4)
- 外部システム連携なら、API Key認証
のような使い分けをするケースが多いです。
この記事では、TypeScriptからAPI Gatewayを呼び出す方法を認証方式ごとに整理します。
前提
API Gatewayのエンドポイント
https://xxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/prod/users
1. Cognito認証
API Gatewayでは Cognito User Pool Authorizer を設定できます。
クライアントはCognitoへサインインし、
- ID Token
- Access Token
を取得し、Authorizationヘッダーへ設定してAPIを呼び出します。API Gatewayはトークンを検証し、有効な場合のみアクセスを許可します。
SDKインストール
npm install aws-amplify
サインイン
import { signIn } from "aws-amplify/auth";
await signIn({
username: "user@example.com",
password: "password"
});
トークン取得
import { fetchAuthSession } from "aws-amplify/auth";
const session = await fetchAuthSession();
const accessToken =
session.tokens?.accessToken?.toString();
API Gateway呼び出し
const response = await fetch(
"https://xxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/prod/users",
{
headers: {
Authorization: `Bearer ${accessToken}`
}
}
);
const data = await response.json();
メリット
- 実装がシンプル
- SPAとの相性が良い
- OAuth2/OpenID Connect準拠
- ユーザー単位の認可が可能
デメリット
- Cognito構築が必要
- サービス間通信には向かない
2. IAM認証(SigV4)
API Gatewayの認可方式をAWS_IAMに設定すると、リクエストへSignature Version 4(SigV4)署名が必要になります。API Gatewayは署名とIAM権限(execute-api:Invoke)を検証し、許可された主体のみ呼び出せます。
SDKインストール
npm install \
@aws-sdk/protocol-http \
@aws-sdk/signature-v4 \
@aws-sdk/credential-provider-node \
@aws-crypto/sha256-js
サンプルコード
import { HttpRequest } from "@aws-sdk/protocol-http";
import { SignatureV4 } from "@aws-sdk/signature-v4";
import { defaultProvider } from "@aws-sdk/credential-provider-node";
import { Sha256 } from "@aws-crypto/sha256-js";
const signer = new SignatureV4({
credentials: defaultProvider(),
region: "ap-northeast-1",
service: "execute-api",
sha256: Sha256,
});
const request = new HttpRequest({
protocol: "https:",
hostname:
"xxxxxxxx.execute-api.ap-northeast-1.amazonaws.com",
method: "GET",
path: "/prod/users",
headers: {
host:
"xxxxxxxx.execute-api.ap-northeast-1.amazonaws.com",
},
});
const signedRequest =
await signer.sign(request);
const response = await fetch(
`https://${signedRequest.hostname}${signedRequest.path}`,
{
method: signedRequest.method,
headers: signedRequest.headers,
}
);
const data = await response.json();
IAMポリシー例
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"execute-api:Invoke"
],
"Resource": [
"arn:aws:execute-api:ap-northeast-1:*:*"
]
}
]
}
メリット
- AWSネイティブ
- IAMで細かく制御可能
- Lambda/ECS/EC2との相性が良い
- トークン管理が不要
デメリット
- フロントエンドには不向き
- SigV4署名が必要
3. API Key認証
API GatewayではAPI KeyとUsage Planを利用できます。
クライアントは発行されたAPI Keyをx-api-keyヘッダーへ設定してアクセスします。API Keyは利用者識別やレート制限用途であり、認証・認可そのものとして使うべきではありません。AWS公式でも、アクセス制御にはIAM・Lambda Authorizer・Cognitoの利用が推奨されています。
呼び出し
const response = await fetch(
"https://xxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/prod/users",
{
headers: {
"x-api-key":
"xxxxxxxxxxxxxxxxxxxxxxxx"
}
}
);
const users = await response.json();
axios版
import axios from "axios";
const response = await axios.get(
"https://xxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/prod/users",
{
headers: {
"x-api-key":
process.env.API_KEY
}
}
);
console.log(response.data);
メリット
- 実装が最も簡単
- 外部連携に向いている
- Usage Planで利用状況管理可能
- レート制御できる
デメリット
- Key漏洩リスク
- ユーザー認証ではない
- 単独利用はセキュリティが弱い
認証方式の比較
| 項目 | Cognito | IAM(SigV4) | API Key |
|---|---|---|---|
| ユーザー認証 | ○ | △ | × |
| AWSサービス間 | △ | ◎ | △ |
| フロントエンド | ◎ | △ | ○ |
| 実装難易度 | ○ | △ | ◎ |
| セキュリティ | ◎ | ◎ | △ |
| レート制限 | ○ | ○ | ◎ |
まとめ
エンドユーザー向け → Cognito
AWSサービス間通信 → IAM(SigV4)
外部公開API → API Key
本番運用ではAPI Key単独利用は避ける
個人的には、AWS環境内の連携であれば IAM認証、フロントエンドからのアクセスであれば Cognito認証 を第一候補にすることが多いです。API Keyは利用量制御の目的で併用するのがおすすめです。