API GatewayのLambda Authorizerでハマったので、原因調査の覚書。
症状
Lambda Authorizerで認証すると、アクセス許可しているはずなのに、認証失敗する。
サーバーからは500番のステータスコードが返される。
サーバー側のログを見る限り、リクエストはLambda AuthorizerのLambdaまでしか到達できていない。
AuthorizerのLambda関数から返しているポリシーは下記のとおりであった。
{
"principalId": "52e60f29-a7c8-4665-99ea-1ec8f7fecb81",
"policyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Action": "execute-api:Invoke",
"Effect": "Allow",
"Resource": "arn:aws:execute-api:ap-northeast-1:012345678901:hogehoge/prod/$connect"
}
]
},
"context": {
"userId": "52e60f29-a7c8-4665-99ea-1ec8f7fecb81",
"group": [ "student" ]
}
}
原因
context
で渡す値にはArrayを入れることが禁止されていた。
下記のようにポリシーを修正すると、無事リクエストが通った。
Notice that you cannot set a JSON object or array as a valid value of any key in the context map.
https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-lambda-authorizer-output.html
{
"principalId": "52e60f29-a7c8-4665-99ea-1ec8f7fecb81",
"policyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Action": "execute-api:Invoke",
"Effect": "Allow",
"Resource": "arn:aws:execute-api:ap-northeast-1:012345678901:hogehoge/prod/$connect"
}
]
},
"context": {
"userId": "52e60f29-a7c8-4665-99ea-1ec8f7fecb81",
"group": "student"
}
}
ちなみに
下記の可能性も探ったが、いずれも関係なかった。
- Node.js で
async/await
使っているからまずい?
Lambda Authorizerのサンプルコード ではCallbackを使っていたので、疑った。
結論としては、async/awaitで問題なく動作する。
2018年頃は本当に動作しなかったらしい。
-
principalId
がなにかおかしい?
いつもArnやAWSサービスのドメイン名を入れているイメージなので、疑った。
しかし、Lambda Authorizerで返すポリシーについては、このPrincipalIdは何を入れても良いらしい。
ただそのままバックエンドに context 経由で渡されるだけ。ユーザーIDとか入れておけば便利そう。
- ポリシーの返し方がまずい?
AuthorizerのLambdaは、下記のようなコードでポリシーを返していた。
JSONに変換しないとだめなのかと疑ったが、そのままで良かった。
逆に JSON.stringify
で文字列に変換して返すと、500エラーが出るようになる。
型定義を信じよう。
export const lambdaHandler: APIGatewayRequestAuthorizerHandler = async (event, context) => {
... // トークンverifyなどの処理
return {
principalId: idToken.sub,
policyDocument: {
Version: "2012-10-17",
Statement: [
{
Action: "execute-api:Invoke",
Effect: "Allow",
Resource: event.methodArn,
}
]
},
context: {
userId: idToken.sub,
group: idToken['cognito:groups']?.shift(),
}
};
}
以上。