1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

API GatewayにCognitoを連携して認証機能を付ける

Posted at

こんにちは。
株式会社クラスアクト インフラストラクチャ事業部の大塚です。

今回は以前作成したAPI Gateway + Lambda環境にCognitoを連携します。
こうすることで認証無くしてAPIを叩けないようにします。

環境イメージ

growi-ページ38.drawio.png

動作フロー

① クライアント → Cognito : ユーザー認証リクエスト
クライアントは、Cognitoユーザープールに対して認証リクエストを送信します。この際、ユーザー名とパスワードを使用して認証を行います。

  • 認証フロー:
  • Cognitoは、ユーザー名とパスワードを受け取り、認証を試みます。
  • 認証フローには、USER_PASSWORD_AUTHやUSER_SRP_AUTHなどのオプションがあります。

② Cognito → クライアント : トークン発行
認証が成功すると、Cognitoは以下のトークンをクライアントに返します。

  • IDトークン: ユーザーの身元情報(例: ユーザー名、メールアドレスなど)を含む。
  • アクセス トークン: APIへのアクセス権を制御するために使用。
  • リフレッシュ トークン: トークンの有効期限が切れた際に新しいトークンを取得するために使用。

③ クライアント → API Gateway : IDトークンを付けてAPIリクエスト
クライアントは、Cognitoから取得したIDトークンを使用してAPI Gatewayにリクエストを送信します。

  • リクエスト例:
    GET /protected-resource HTTP/1.1
    Host: api.example.com
    Authorization: Bearer
  • AuthorizationヘッダーにIDトークンを設定することで、認証済みのリクエストとして扱われます。

④ API Gateway → Cognito : トークンの検証
API Gatewayは、Cognitoユーザープールをオーソライザーとして設定しています。このため、受け取ったIDトークンの有効性をCognitoに確認します。

  • 検証内容:
  • トークンの署名が正しいか。
  • トークンの発行元(Issuer)が正しいか。
  • トークンの有効期限が切れていないか。

⑤ Cognito → API Gateway : トークンの判定
Cognitoがトークンを検証し、結果をAPI Gatewayに返します。

  • 有効な場合:
  • API Gatewayはリクエストをバックエンド(Lambdaなど)に転送します。
  • 無効な場合:
  • API Gatewayは「401 Unauthorized」エラーをクライアントに返します。

⑥ API Gateway → Lambda : ユーザー情報付きでリクエスト転送
トークンが有効である場合、API GatewayはリクエストをLambdaに転送します。この際、トークン内のユーザー情報(例: sub, email, cognito:groupsなど)を含めます。

  • ユーザー情報の利用例:
  • Lambdaでユーザーのグループ情報を参照し、アクセス権を制御する。

⑦ Lambda → API Gateway : APIレスポンスを返す
Lambdaはリクエストを処理し、結果をAPI Gatewayに返します。

  • レスポンス例:
  • 成功時: HTTPステータスコード200とデータ。
  • エラー時: 適切なエラーメッセージとステータスコード。

⑧ API Gateway → クライアント : HTTPレスポンスを返す
API Gatewayは、Lambdaから受け取ったレスポンスをクライアントに返します。

  • クライアント側の動作:
  • レスポンスを受け取り、画面表示やデータ処理を行います。

構築

Cognitoでユーザプールを作成する
image.png
API GatewayなのでSPA用のもので良い。
リターンURLはAPIにアクセスするためのものを選択。
screencapture-ap-northeast-1-console-aws-amazon-cognito-v2-idp-set-up-your-application-2025-05-31-12_42_04.png
作成出来るとこんな感じの画面が表示される。今回の要件ではこれは使わない。
左のユーザプールを押下する。
screencapture-ap-northeast-1-console-aws-amazon-cognito-v2-idp-set-up-your-application-2025-05-31-12_42_21.png

作成したユーザプール名を押下して、左にあるアプリケーションクライアントを押下して、
編集ボタンを押下すると以下のような画面になる。
"ユーザー名とパスワード (ALLOW_USER_PASSWORD_AUTH) を使用してサインインします"にチェックを付けて変更を保存を押下する。
screencapture-ap-northeast-1-console-aws-amazon-cognito-v2-idp-user-pools-ap-northeast-1-pDwtyMhPe-applications-app-clients-6eb4ji0thnlms9ipijauo7fk5s-login-pages-edit-basic-settings-2025-05-31-12_46_46.png
変更が反映されていることを確認する。
認証フローのところにユーザー名とパスワードと表示されていることを確認する。
image (1).png

ユーザを作成する。
画面左のユーザ管理からユーザを押下すると以下のような画面が表示され、ここで作成することが出来る。
image (2).png
screencapture-ap-northeast-1-console-aws-amazon-cognito-v2-idp-user-pools-ap-northeast-1-pDwtyMhPe-user-management-users-create-user-2025-05-31-12_43_18.png

作成されたことを確認する。
確認ステータスを確認済みに変更するために対応を続ける
image (3).png
AWSマネコンからCloudShellを起動して以下のようなコマンドを実行する

aws cognito-idp admin-set-user-password \
    --region ap-northeast-1 \
    --user-pool-id ap-northeast-1_pDwtyMhPe \
    --username ohtsuka-shota \
    --password P@ssword123 \
    --permanent

解説
aws cognito-idp admin-set-user-password \
    --region <リージョン> \
    --user-pool-id <ユーザプールID> \
    --username <ユーザプールに登録したユーザ名> \
    --password <ユーザプールに登録したユーザのパスワード> \
    --permanent

image (4).png
確認ステータスが確認済みになっていることを確認する。
image (5).png
API Gatewayの管理画面からオーソライザータブを押下する。
オーソライザーを作成を押下する
image (6).png
名前は任意のもの
オーソライザーのタイプはCognitoを選択して、ユーザプールは先ほど作成したものを。
トークンのソースはAuthorizationを入力。
image (7).png
作成出来たことを確認する。
image (8).png
このオーソライザが機能しているか確認するため、Cognitoからトークンを取得する。
CloudShellで以下を入力。IdTokenの値を控える。

$ curl -X POST https://cognito-idp.ap-northeast-1.amazonaws.com \
>   -H "Content-Type: application/x-amz-json-1.1" \
>   -H "X-Amz-Target: AWSCognitoIdentityProviderService.InitiateAuth" \
>   -d '{
>     "AuthFlow": "USER_PASSWORD_AUTH",
>     "ClientId": "6eb4ji0thnlms9ipijauo7fk5s",
>     "AuthParameters": {
>       "USERNAME": "ohtsuka-shota",
>       "PASSWORD": "P@ssword123"
>     }
>   }' | jq
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  4137  100  3951  100   186  12054    567 --:--:-- --:--:-- --:--:-- 12612
{
  "AuthenticationResult": {
    "AccessToken": "eyJraWQiOiI0Y09zbUUxY1o4Q1dManM2WUZ4MitZcTRtbUVTZWRkRzc3TFRtQyt0YlNrPSIsImFsZyI6IlJTMjU2In0.eyJzdWIiOiI3NzA0MWFmOC1jMGQxLTcwYWEtYWQzZS1jZGEwYmVhZmE3NDgiLCJpc3MiOiJodHRwczpcL1wvY29nbml0by1pZHAuYXAtbm9ydGhlYXN0LTEuYW1hem9uYXdzLmNvbVwvYXAtbm9ydGhlYXN0LTFfcER3dHlNaFBlIiwiY2xpZW50X2lkIjoiNmViNGppMHRobmxtczlpcGlqYXVvN2ZrNXMiLCJvcmlnaW5fanRpIjoiM2M0YzQyYzktZDhjMC00M2VjLTg2ZjEtMTllNDZhNGY3MTRjIiwiZXZlbnRfaWQiOiJhY2Y3MWI2MC0yZWU5LTQ2MTEtYWNlOC1kYzU2NmU3MTEzNTciLCJ0b2tlbl91c2UiOiJhY2Nlc3MiLCJzY29wZSI6ImF3cy5jb2duaXRvLnNpZ25pbi51c2VyLmFkbWluIiwiYXV0aF90aW1lIjoxNzQ4NjYzNjI2LCJleHAiOjE3NDg2NjcyMjYsImlhdCI6MTc0ODY2MzYyNiwianRpIjoiNDQ5NWJiMzItMDIxMi00NDRiLWExYjYtNzczOGZkOTRkYmIzIiwidXNlcm5hbWUiOiJvaHRzdWthLXNob3RhIn0.CicH6mld8TGMLzumUE043RjqKjMEpiH6KWE3I1HH02yIZaG0iKaUlCRMEs_-udO3bioGhx4vsOrBT3o8bObeFsJlsjRtGskJs1rhPzw1w31bWYCK1eM15i47q2PSuS4SlpsnjCly14xCAKC5P86UrnoYNi2ktWsYUtzSakjz6SCJl1cbc5Ai_A2IKbI6dArHFHmAnStW0a5NXkYHQEw7e23v3KWSmapUEFJSPz-FwkCzQY3QakffDyOwORd3AaXcjyoc-NecF0C2-QrjIrrJYcsEhy4pLGxpEAi9dRx2DPJK_FgQ1Izfn41GJez3DjROK9WyZ-_ftBUTtu20cgbgHA",
    "ExpiresIn": 3600,
    "IdToken": "eyJraWQiOiJyYjd2VnAwU0VoemRuQWZ1YnlOeFZXSEZzU3FFS0VBSUMzWWo5eVE4b0Z3PSIsImFsZyI6IlJTMjU2In0.eyJvcmlnaW5fanRpIjoiM2M0YzQyYzktZDhjMC00M2VjLTg2ZjEtMTllNDZhNGY3MTRjIiwic3ViIjoiNzcwNDFhZjgtYzBkMS03MGFhLWFkM2UtY2RhMGJlYWZhNzQ4IiwiYXVkIjoiNmViNGppMHRobmxtczlpcGlqYXVvN2ZrNXMiLCJldmVudF9pZCI6ImFjZjcxYjYwLTJlZTktNDYxMS1hY2U4LWRjNTY2ZTcxMTM1NyIsInRva2VuX3VzZSI6ImlkIiwiYXV0aF90aW1lIjoxNzQ4NjYzNjI2LCJpc3MiOiJodHRwczpcL1wvY29nbml0by1pZHAuYXAtbm9ydGhlYXN0LTEuYW1hem9uYXdzLmNvbVwvYXAtbm9ydGhlYXN0LTFfcER3dHlNaFBlIiwiY29nbml0bzp1c2VybmFtZSI6Im9odHN1a2Etc2hvdGEiLCJleHAiOjE3NDg2NjcyMjYsImlhdCI6MTc0ODY2MzYyNiwianRpIjoiMzViYzlmMWEtZjVjZC00YWRkLTkwYzEtNzAwZWIxNzUzZWYwIn0.xZLWGTtuDobbETp4xuumgHjfsCfHC4UH3E1stiUw-L7s4j3VsKr8Ahcx78o4Qoak19jo-6DOTbspftaiGhNTCXm9qFAJcsz843NApa_IK16bB8v5AyXMs6P6n69cfj7NJG9Px-QWHM3ijbCS298EQG4dcSP-ZpIhH-WZAxWplZVOKWSaF_6beOxF8OoWABSQwie-684slWo53ymRVZsYVr_a4csKheBc7NQ9DtIIyvLZLUqY49zn5hhPC4Z6Otl8SwYAqgfw7KDY5cF8OPcSosnF_AbY09U82gQVUfEB3UBFrRcx0LqAwpyWTFmWuLv2vC-Ff7A-0txI_dDvjVEVXA",
    "RefreshToken": "eyJjdHkiOiJKV1QiLCJlbmMiOiJBMjU2R0NNIiwiYWxnIjoiUlNBLU9BRVAifQ.lpm_Ogn9Go7q0bIINHzh5GD3GqyQrfbMVGEqv8cqWA522PquiMzrmAgB-NBLhIESVSS7K_zQVCkDUZofZ38dav21utJomIsSDRoYMbi3hx_avQeCRhjwrmEiLtGC5Nx3mu-cArn88-p6c6129znYPJFDYsAuK9E7VGVHHaJYV1pItFC3fOmcJ7m5-ctY5clxidGCRHI_qR17MKBqeDs8fPZezx0f0PYzJT6yGLK3mQPfZ1GSXfR0Oq7CfVPWG55LJ9Uj4qQ_Kh-FSr0msIEZLwIGH0ajtDW7HWEtNIwtPPqGzHDmOhhpaf8yImp1zpdZXiJD3oolBoBpDCbaBvB5PA.zYVs35iKqANbTZKn.9JM3ku8m8hgczmpY1J4Gt_XyGXHr_PLViQAtnLqBbXhuXWVTznXVwMqEMTrxRbQzzBclMYfylXGLdNy17E6lWxYh25Fbuz1m9zZAtODugsCNFJ30Eto3kAxJ_hhJUrYADXhn7FYgRiJIR6g1RSr2J8PK7Wx5VnkEh0uLQAY89L7Iwx-sXkr0Jpj7jITN6M2opzabd0LIkiygzyL84yIdFzFTLXSdF4FitVeQeRXAdPVO7ym-e1FYSi9iGB_3dIrdBzMvP-NvNbafEteJ2MtkS6Nq5ACSTDWBJLLy0wjwxnS0oqwpVkpjYVoUwYicaV0PkOqtn80UaJrdM6mJEHouc22ysIOmDRlf36g_8irUUYQ3yTCqkO53tb-NtgxLSt0Uze-JihPFK5h70kiIjEY3yl24a-wI-fx_3pBpcVVVxCpuHwZKsZ-dzeCl8gZ2bT7fdXB5cXEtgk2dMcy_PbYypcd-nl6xDsiZVR-Rd7XBiwwRNEYgYioYJ4p-8MlPuyhu1UJHGYpfCKKhYlVVG1WJwwGXn2S9R_oAc4KUuxYzYDcv76uA1crqUq61cZhQEyqtB7byUx0yyJAE4Hsw9ug11B8WQLDY7Y-vYoCFfyeQ9gKFyAu6BMLuAWqlj0L-JM_cO77VljMRpY3RUIr2O10vkD6MCFpO3_-h-ngH0yQaLpT0T-hzSsLhz-RtuOTFdhKwezufA6YO5Jbw39ZLy0BJp0lvcI9vYVBtswV11iJYumyUpu-dhHG5UXaCOaFHs2p9mckOTXVk-Jcecq45ePAUik0eVCzAPj1wdY6_RdXSmZdpKubtgrWrTEMai1Kxi0zGZkmIn0DdWkVq-m7wyAClfNx1Gsl0enlNDY5crPoMZIJBet6h0xJrKMaPRZ-BN5C9JZWI1NdP2pWcsFspQRvJhGbqKVj9v_b75OhOzdxLMQty3Ept8VpRzyxAn6NMSHieqlqkGuqVr4bEGRkg5JUnp0f4yZAGqp-7hbUnAKO5oueohEmRD6w7sq1BYtJ4rQvoHLmxQ2AEE9UGcin71qvN_ueqBQIP5yoLLlf_APnAXH8cGA60yhbrg-anDXR9lLzxHziGykNLlK7bwTcLCAxbkpYUKBudlrLWok-w1uu_QNZ7gp10_cecm_xlr1X-58n4q_KFbxqiS2S7z8PzbuNoSM14RCwgXlkpgmPwUON8f5_0qjV8qnP2WiI4_uiT-e1hwSM-xzU9WiR7VwJm6Y_VPQTVSfpRCOJpl-AwbhcZboMz4ZmUI09gF6OVtaR5yrmdyTM9WSd4jr3k5qkhDijMd-aFx6Ah14zemZaz.46V8CStWHyKkoi_ZWGbiWg",
    "TokenType": "Bearer"
  },
  "ChallengeParameters": {}
}

解説
curl -X POST https://cognito-idp.ap-northeast-1.amazonaws.com \
>   -H "Content-Type: application/x-amz-json-1.1" \
>   -H "X-Amz-Target: AWSCognitoIdentityProviderService.InitiateAuth" \
>   -d '{
>     "AuthFlow": "USER_PASSWORD_AUTH",
>     "ClientId": "<ユーザプールID> ",
>     "AuthParameters": {
>       "USERNAME": " <ユーザプールに登録したユーザ名>",
>       "PASSWORD": "<ユーザプールに登録したユーザのパスワード>"
>     }
>   }' | jq

image (9).png
作成出来たオーソライザー名を選択すると、テストを行うことが出来る。
先程取得したIdTokenの値をトークンの値欄に入力してオーソライザのテストを押下
image (10).png
200が返ってくれば、APIからCognitoへの認証が上手くいっていることになります。
image (11).png
APIにオーソライザを紐づけます。
リソースからメソッドリクエストを押下し、編集をクリック。
image (12).png
認可に先ほど作成したオーソライザを選択して保存
screencapture-ap-northeast-1-console-aws-amazon-apigateway-main-apis-hc620f2cy5-resources-7gg27u-methods-POST-edit-method-request-2025-05-31-12_57_14.png
認可の欄にオーソライザの名前が表示されていることを確認する。
image (13).png
その後APIをデプロイ。
image (14).png

試験

CognitoとAPI+Lambdaが連携できていることを確認する。
まず、前の通りcurlしてみる。
結果として、{"message":"Unauthorized"}と出ていることから認証が働いている。

$ curl -X POST https://hc620f2cy5.execute-api.ap-northeast-1.amazonaws.com/dev/hello
{"message":"Unauthorized"}

image (15).png

先程取得したIdTokenを渡した上で再度実行する
{"statusCode": 200, "body": "{"message": "Hello AWS API Gateway!"}"}~と出力されており、
認証が通り、APIの裏側のLambdaが実行されていることがわかる。

curl -X POST https://hc620f2cy5.execute-api.ap-northeast-1.amazonaws.com/dev/hello -H "Authorization: Bearer eyJraWQiOiJyYjd2VnAwU0VoemRuQWZ1YnlOeFZXSEZzU3FFS0VBSUMzWWo5eVE4b0Z3PSIsImFsZyI6IlJTMjU2In0.eyJvcmlnaW5fanRpIjoiM2M0YzQyYzktZDhjMC00M2VjLTg2ZjEtMTllNDZhNGY3MTRjIiwic3ViIjoiNzcwNDFhZjgtYzBkMS03MGFhLWFkM2UtY2RhMGJlYWZhNzQ4IiwiYXVkIjoiNmViNGppMHRobmxtczlpcGlqYXVvN2ZrNXMiLCJldmVudF9pZCI6ImFjZjcxYjYwLTJlZTktNDYxMS1hY2U4LWRjNTY2ZTcxMTM1NyIsInRva2VuX3VzZSI6ImlkIiwiYXV0aF90aW1lIjoxNzQ4NjYzNjI2LCJpc3MiOiJodHRwczpcL1wvY29nbml0by1pZHAuYXAtbm9ydGhlYXN0LTEuYW1hem9uYXdzLmNvbVwvYXAtbm9ydGhlYXN0LTFfcER3dHlNaFBlIiwiY29nbml0bzp1c2VybmFtZSI6Im9odHN1a2Etc2hvdGEiLCJleHAiOjE3NDg2NjcyMjYsImlhdCI6MTc0ODY2MzYyNiwianRpIjoiMzViYzlmMWEtZjVjZC00YWRkLTkwYzEtNzAwZWIxNzUzZWYwIn0.xZLWGTtuDobbETp4xuumgHjfsCfHC4UH3E1stiUw-L7s4j3VsKr8Ahcx78o4Qoak19jo-6DOTbspftaiGhNTCXm9qFAJcsz843NApa_IK16bB8v5AyXMs6P6n69cfj7NJG9Px-QWHM3ijbCS298EQG4dcSP-ZpIhH-WZAxWplZVOKWSaF_6beOxF8OoWABSQwie-684slWo53ymRVZsYVr_a4csKheBc7NQ9DtIIyvLZLUqY49zn5hhPC4Z6Otl8SwYAqgfw7KDY5cF8OPcSosnF_AbY09U82gQVUfEB3UBFrRcx0LqAwpyWTFmWuLv2vC-Ff7A-0txI_dDvjVEVXA"
{"statusCode": 200, "body": "{\"message\": \"Hello AWS API Gateway!\"}"}~

image (16).png

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?