🔒
API Gateway x Cognito で client id 変更したら認証が通らなくなったので解消した
事象
- AWS Cognito の認証と連携させて API Gateway を使っていた。
- curl で Cognito の認証トークン発行APIを直接叩くことでトークンを取得し、それを載せて直接API Gateway にリクエスト送信していた。
$ cat auth.json
{
"ClientId": "piyopiyo",
"AuthFlow": "USER_PASSWORD_AUTH",
"AuthParameters": {
"USERNAME": "peroper@hoge.com",
"PASSWORD": "munyamunya",
"SECRET_HASH": "amoamo"
}
}
$ IdToken=$(curl -s -X POST \
-H 'X-Amz-Target: AWSCognitoIdentityProviderService.InitiateAuth' \
-H 'Content-Type: application/x-amz-json-1.1' \
--data @auth.json \
https://cognito-idp.us-east-1.amazonaws.com/ | jq -r .AuthenticationResult.IdToken)
$ curl \
-H "Authorization: Bearer ${IdToken}" \
"https://XXXX.execute-api.us-east-1.amazonaws.com/mogemoge" | jq .
- API Gateway にセットしていた Cognito の client_id(old) を clinet_id(new) に差し替えたところ、認証が通らなくなった。
原因
- client_id(new)はCognitoのマネージドログイン画面からログインできるようにするために新規に発行した client_id だった。
- したがってclinet_idと認証方式が異なっていたため、アクセスできないようになっていた。
対応策
- client_id を (new) と (old) 二つセットする。
- serverless framework を使って管理しているため、このようなセットになる。
provider:
name: aws
architecture: arm64
runtime: provided.al2
stage: ${opt:stage, self:custom.defaultStage}
region: us-east-1
httpApi:
authorizers:
cognitoAuthorizer:
type: jwt
identitySource: $request.header.Authorization
issuerUrl: https://cognito-idp.us-east-1.amazonaws.com/${ssm:/cognito/user-pool-id/${self:provider.stage}}
audience:
- ${ssm:/cognito/client-id/${self:provider.stage}}
- ${ssm:/cognito/client-id-backend/${self:provider.stage}} # ←ここ
cors: true
詳細説明
Cognitoの認証フローには以下がある。
- USER_SRP_AUTH
- USER_PASSWORD_AUTH
- ADMIN_USER_PASSWORD_AUTH
- REFRESH_TOKEN_AUTH
- CUSTOM_AUTH
- USER_PASSWORD_AUTH_WITH_MFA
- ADMIN_NO_SRP_AUTH
このうち、Cognitoのホスト型UI(マネージドログイン画面)で利用可能な認証フローは以下
- USER_SRP_AUTH
マネージドUI用の標準的な認証フロー。デフォルトで有効で最もセキュアな方式。 - REFRESH_TOKEN_AUTH
デフォルトで有効。セッション維持やマネージドUIでの自動更新に使用。 - USER_PASSWORD_AUTH_WITH_MFA
MFAが有効な場合に使用。マネージドUIでMFA画面を表示。
一方、最初に発行した client_id(old) に設定されていた認証フローはUSER_PASSWORD_AUTH。異なるものだったのでそりゃあ通らない。
感想(反省点)
生成AIに対応策を聞いてみたら強引にUSER_SRP_AUTHを乗り越える長いスクリプトを書いたりして大変だった...。
そもそも一つのuser_poolに複数のclient_idが発行できる=複数のアプリを管理できるということは、API Gatewayにも複数のclient_idがセットできるのは自然な発想。これに早く気づけばよかった...。
Discussion