CognitoのIDトークンを簡単に検証したい。する。
やりたいこと
認証基盤としてCognitoを使う。サインインした時に発行されるIDトークンについて、できるだけ簡単に検証したい。
神ライブラリがあったので使ってみる。
やってみる
IDトークンを検証するだけのAPIを作る。
API Gateway → Lambda関数
APIはAuthorizationヘッダにBearerでIDトークンをのっけたリクエストを想定。
これをSAM使って作る。
ディレクトリ構造
SAMのテンプレートをベースにして作ったので無駄ファイルもありそう。
.
├── README.md
├── buildspec.yml
├── samconfig.toml
├── src
│ ├── handlers
│ │ └── handler.mjs
│ └── package.json
└── template.yaml
buildspec.yml
SAMのテンプレートそのまま流用したので変な感じだけどキニシナイ
version: 0.2
phases:
install:
commands:
# Install all dependencies (including dependencies for running tests)
- npm install
pre_build:
commands:
# Discover and run unit tests in the '__tests__' directory
- npm run test
# Remove all unit tests to reduce the size of the package that will be ultimately uploaded to Lambda
- rm -rf ./__tests__
# Remove all dependencies not needed for the Lambda deployment package (the packages from devDependencies in package.json)
- npm prune --production
build:
commands:
# Use AWS SAM to package the application by using AWS CloudFormation
- aws cloudformation package --template template.yaml --s3-bucket $S3_BUCKET --output-template template-export.yml
artifacts:
type: zip
files:
- template-export.yml
template.yaml
buildspecは.ymlなのにテンプレートファイルは.yamlだけどキニシナイ
AWSTemplateFormatVersion: 2010-09-09
Description: >-
cognitojwt
Transform:
- AWS::Serverless-2016-10-31
Globals:
Function:
Tracing: Active
Api:
TracingEnabled: True
Resources:
getAllItemsFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: src
Handler: handlers/handler.handler
Runtime: nodejs18.x
Architectures:
- x86_64
MemorySize: 128
Timeout: 100
Policies:
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
Description: "IdToken validation"
Events:
Api:
Type: Api
Properties:
Path: /
Method: GET
Outputs:
WebEndpoint:
Description: "API Gateway endpoint URL for Prod stage"
Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/"
samconfig.toml
samconfigは sam deploy --guidedで作ったほうが良いと思う。が、一応載せておく。
version = 0.1 [default] [default.deploy] [default.deploy.parameters] stack_name = "cognitojwt" s3_bucket = "バケット" s3_prefix = "cognitojwt" region = "ap-northeast-1" capabilities = "CAPABILITY_IAM" image_repositories = []
スタック名とバケット名をちゃんと書いたらとおるとは思う。
src/package.json
なんか明らかにいらんもんも入ってるのはご愛嬌。基本的には aws-jwt-verify さえ入れておけばOK。
{
"name": "delete-test-01",
"description": "delete-test-01-description",
"version": "0.0.1",
"private": true,
"dependencies": {
"aws-jwt-verify": "^3.2.0"
},
"devDependencies": {
"aws-sdk-client-mock": "^2.0.0",
"jest": "^29.2.1"
},
"scripts": {
"test": "node --experimental-vm-modules ./node_modules/jest/bin/jest.js"
}
}
src/handlers/handler.mjs
コードは以下。UserPoolIdとclientIdを埋めちゃってね。
import { CognitoJwtVerifier } from "aws-jwt-verify";
async function verifyJwt(jwt) {
const verifier = CognitoJwtVerifier.create({
userPoolId: "<ユーザプールID>",
tokenUse: "id", // アクセストークンの時は access
clientId: "<クライアントID>",
});
try {
const payload = await verifier.verify(jwt);
console.log("Token is valid. Payload: ", payload);
return payload;
} catch (err) {
console.error(err);
console.log("Token not valid!");
return {message: "Token not valid"};
}
}
export const handler = async (event) => {
console.info('received:', event);
const jwt = event.headers.Authorization.split(' ')[1];
const payload = await verifyJwt(jwt);
const response = {
statusCode: 200,
body: JSON.stringify(payload)
};
console.info(`response from: ${event.path} statusCode: ${response.statusCode} body: ${response.body}`);
return response;
}
入力として、API Gateway経由のBearerでIDトークンのっけたリクエストを想定している。
実行する
sam build --use-container からの sam deploy --guided(2回目以降、というかsamconfig.tomlがあれば--guidedなしで)。
curlで叩く。
curl --location --request GET 'エンドポイント' \
--header 'Authorization: Bearer ここにIDトークンいれる'
うまくいくと下記のようなレスポンスが返る。
{
"sub": "xxxx",
"aud": "クライアントIDっぽい",
"event_id": "xxxx",
"token_use": "id",
"auth_time": 1669872162,
"iss": "https://cognito-idp.ap-northeast-1.amazonaws.com/ユーザプールID",
"cognito:username": "サインインしたユーザ名",
"exp": 1669888765,
"iat": 1669885165
}
expもあるが、もし期限切れだったらライブラリのほうでちゃんとエラー返してくれる。
やってみたら忘れずにスタック削除する。
以上。
参考
自前でも頑張れるんだけれど、というか前にこのライブラリの存在知らず頑張った記憶があるんだが、たいへんだったのでライブラリ使いたい。
以下の記事助かりました。AWSの公式ドキュメントは闇だけどブログ記事は助かるの多い。
コメント