Amazon Cognito + API Gateway + Lambdaで構築するM2M(Client Credentials)認証ハンズオン
システム間の連携(Machine to Machine: M2M)で、APIを安全に保護するために OAuth 2.0のClient Credentials(クライアント資格情報)フロー を使用するケースが増えています。
今回は、Amazon Cognito でM2Mクライアント(ユーザープール)を作成してアクセストークンを取得し、それを API Gateway のCognitoオーソライザーで検証して AWS Lambda を安全に呼び出す構成をハンズオン形式で解説します。
全体構成図
構成は非常にシンプルです。
- クライアント(外部システム等)がCognitoの認可エンドポイントへ
client_idとclient_secretを送信。 - Cognitoから アクセストークン(JWT)が返却される。
- クライアントは
Authorizationヘッダーにトークンを含めてAPI Gatewayへリクエスト。 - API GatewayのCognitoオーソライザーがトークンを検証し、有効であれば後続のLambdaを実行。
Step 1: Amazon Cognito の設定
まずは認証基盤となるCognitoユーザープールと、M2M用のクライアントを設定します。
1.1 ユーザープールの作成
- AWSコンソールでCognitoを開き、「ユーザープールの作成」をクリック。
- 属性プロバイダーで 「ユーザー名」(デフォルト)を選択して次へ。
- パスワードポリシー等は検証用のためデフォルトのままで次へ。
- 「多要素認証 (MFA)」は 「MFA なし」 を選択して次へ。
- 「ユーザープール名」を入力(例:
m2m-test-pool)。
1.2 アプリクライアントの設定(ここが重要!)
「アプリケーション初期設定」のステップで、M2M用の設定を行います。
- アプリケーションタイプ: 「従来のWebアプリケーション」 or 「機密クライアント」 を選択。
- アプリケーションクライアント名:
m2m-client - 「クライアントシークレットを生成する」 にチェックが入っていることを確認。
1.3 認証フローとスコープの設定
ユーザープール作成後、作成したプールを開き、「アプリケーションの統合」 タブの一番下にある「アプリケーションクライアント」を開きます。
- ホストされたUI(Hosted UI) の設定で「編集」をクリック。
- 以下の通り設定します。
-
マネージド型ログイン(またはホストされたUI):
有効 - OAuth 2.0 の付与タイプ: 「クライアント資格情報 (Client credentials)」 にチェック(※他のチェックは外す)
-
カスタムスコープ / OAuthスコープ:
openidなどの標準スコープ、または必要に応じてカスタムスコープを指定。
-
マネージド型ログイン(またはホストされたUI):
-
「Cognito ドメイン」 を設定します(例:
https://m2m-test-auth.auth.ap-northeast-1.amazoncognito.com)。
Step 2: AWS Lambda の作成
API Gatewayから呼び出されるバックエンドのLambda関数を作成します。
- Lambdaコンソールから「関数の作成」をクリック。
- 関数名:
m2m-test-function - ランタイム:
Node.js(または任意の言語) - コードは以下のようなシンプルなレスポンスを返すようにします。
export const handler = async (event) => {
const response = {
statusCode: 200,
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
message: "Hello from M2M Protected Lambda!",
caller: event.requestContext.authorizer?.claims?.client_id || "Unknown"
}),
};
return response;
};
Step 3: Amazon API Gateway の設定
APIを作成し、Cognitoによる認証(オーソライザー)を設定します。
3.1 REST APIの作成
- API Gatewayコンソールで「APIを作成」> 「REST API」 を選択。
- API名:
m2m-protected-api
3.2 オーソライザーの作成
- 左メニューの 「オーソライザー」 を選択し、「新しいオーソライザーの作成」をクリック。
- 設定項目:
- 名前:
CognitoM2MAuthorizer - タイプ: 「Cognito」
- Cognitoユーザープール: Step 1で作成したプールを選択。
- トークンのソース:
Authorization
- 名前:
- 「作成」をクリック。
3.3 リソースとメソッドの作成
- 左メニューの 「リソース」 に戻り、「メソッドの作成」をクリック。
- メソッドタイプ:
GET - 統合タイプ:
Lambda 関数> Step 2で作成したm2m-test-functionを選択。 - 作成された
GETメソッドの画面で 「メソッドリクエスト」 の「編集」をクリック。 -
「認可」 で、先ほど作成した
CognitoM2MAuthorizerを選択して保存。
3.4 APIのデプロイ
- 「APIをデプロイ」をクリック。
- ステージ名:
prodを作成。 - 発行された 「URLの呼び出し」(例:
https://xxxxxx.execute-api.ap-northeast-1.amazonaws.com/prod)を控えておきます。
Step 4: 動作確認
それでは、実際にトークンを取得してAPIにアクセスしてみましょう。
1. トークンの取得 (Client Credentials Flow)
cURLを使って、Cognitoのドメインからアクセストークンを発行します。
YOUR_DOMAIN, CLIENT_ID, CLIENT_SECRET はご自身の環境に置き換えてください。
# クライアントIDとシークレットをBase64エンコードして渡すか、cURLの-uオプションを使用します
curl -X POST "https://<YOUR_COGNITO_DOMAIN>[.auth.ap-northeast-1.amazoncognito.com/oauth2/token](https://.auth.ap-northeast-1.amazoncognito.com/oauth2/token)" \
-H "Content-Type: application/x-www-form-urlencoded" \
-u "<CLIENT_ID>:<CLIENT_SECRET>" \
-d "grant_type=client_credentials"
レスポンス例:
成功すると、以下のように access_token が返ってきます。
{
"access_token": "eyJraWQiOi...",
"expires_in": 3600,
"token_type": "Bearer"
}
2. トークンなしでAPI Gatewayにアクセス(拒否されることを確認)
まずはヘッダーなしでAPIを叩いてみます。
curl -i https://<API_ID>[.execute-api.ap-northeast-1.amazonaws.com/prod/](https://.execute-api.ap-northeast-1.amazonaws.com/prod/)
レスポンス:
HTTP/1.1 401 Unauthorized
{"message":"Unauthorized"}
しっかりブロックされていますね。
3. トークン付きでAPI Gatewayにアクセス(成功)
先ほど取得した access_token を Authorization ヘッダーに付与してリクエストします。
curl -i -H "Authorization: Bearer <取得したaccess_token>" \
https://<API_ID>[.execute-api.ap-northeast-1.amazonaws.com/prod/](https://.execute-api.ap-northeast-1.amazonaws.com/prod/)
レスポンス:
HTTP/1.1 200 OK
{
"message": "Hello from M2M Protected Lambda!",
"caller": "xxxxxxxxxxxxxxxxxxxxxxxxxx"
}
無事にLambdaが実行され、呼び出し元のクライアントIDが取得できていることが確認できました!
まとめ
Amazon Cognitoの「クライアント資格情報 (Client credentials)」フローを活用することで、面倒なJWTの検証ロジックを自前で実装することなく、API Gatewayの標準機能だけで安全なM2M認証を実現できました。
システム間連携のAPIをAWS上で構築する際は、ぜひ参考にしてみてください。