AWS Lambdaプロキシ統合のイベントからCognitoユーザープールの属性を取得 (Node.js)
- オーソライザーにCognitoユーザープールを設定していれば、
event.requestContext.authorizer.claims
に入ってくる。 - もしくは
event.headers.Authorization
から生のIDトークンを取得してパースする。
イベントの claims を使う方法
Node.jsの場合、Lambdaハンドラに渡されてきた event.requestContext.authorizer.claims
の中身は下記のような感じになってる。
{
"sub": "4216ac0c-b092-493a-8567-1fff71b4XXXX",
"aud": "s65q9nma0510d6h15g9t8XXXX",
"event_id": "afc54790-3048-4d50-b458-01f1dfbc7fc8",
"token_use": "id",
"auth_time": "1573022214",
"iss": "https://cognito-idp.ap-northeast-1.amazonaws.com/ap-northeast-1_XXXXXXXXX",
"cognito:username": "kiriukun",
"exp": "Wed Nov 06 07:36:54 UTC 2019",
"iat": "Wed Nov 06 06:36:54 UTC 2019"
}
ネットで見かけた限りでは、emailがある場合は同様に claims
に入ってる模様。それ以外のユーザー属性は調べてないので不明。ユーザー名は cognito:username
という風に不思議な感じなので注意。
auth_time
が数値ではなく文字列だったり、exp
はそもそもタイムスタンプじゃなかったりする。公式マニュアルでは数値のタイムスタンプなのに。
残り時間を確認するなら exp
をパースするより auth_time
に3600秒 (IDトークンの有効期限) を足して計算したほうが楽かと思ったけど、auth_time
はIDトークンをリフレッシュしても値が変化しないので、残り時間の算出には使えない。
exp
のパースが面倒なら、生のIDトークンをデコードして、マニュアル通りの exp
を取り出した方が楽かも。
生のIDトークンを使う方法
生のIDトークンを取得するなら event.headers
を見る。
const handler = async (event) => {
// Authorizationヘッダの名称が大文字始まりでも小文字始まりでも取得できるように
const authorization = event.headers.Authorization || event.headers.authorization;
if (authorization) {
const idToken = authorization.split('Bearer ')[1];
console.log('IDトークン', idToken);
}
};
module.exports = { handler };
IDトークンはJSON Web Tokenなので、Node.jsなら jsonwebtoken 等でデコードできる。
npm install jsonwebtoken
const jwt = require('jsonwebtoken');
const claims = jwt.decode('IDトークンの値');
これで取得できた claims
の中身を見ると、こちらは以下のようにマニュアル通りのフォーマットになっている。日付がタイムスタンプ形式で扱いやすい。
{
"sub": "aed7ad78-f440-47b3-ad9d-4af84f80XXXX",
"aud": "4lbri730rpvdagk74g1a3eXXXX",
"event_id": "f91fcfe0-3bbb-4db4-a834-c8e2051c0fb2",
"token_use": "id",
"auth_time": 1571809319,
"iss": "https://cognito-idp.ap-northeast-1.amazonaws.com/ap-northeast-1_XXXXXXXXX",
"cognito:username": "kiriukun",
"exp": 1571812919,
"iat": 1571809319
}
この方法でIDトークンの残り時間を算出するには以下の通り。
const jwt = require('jsonwebtoken');
const idToken = 'IDトークン';
const decodedIdToken = jwt.decode(idToken);
const expSec = decodedIdToken.exp;
const nowSec = Math.floor(Date.now() / 1000); // Date.now() はミリ秒だから秒にする
const remainSec = expSec - nowSec;
console.log('残り秒数', remainSec);