LoginSignup
0
0

More than 3 years have passed since last update.

Amazon API GatewayのLambda Authorizerのレスポンスに注意

Last updated at Posted at 2021-02-17

API GatewayのLambda Authorizerでハマったので、原因調査の覚書。

症状

Lambda Authorizerで認証すると、アクセス許可しているはずなのに、認証失敗する。
サーバーからは500番のステータスコードが返される。
サーバー側のログを見る限り、リクエストはLambda AuthorizerのLambdaまでしか到達できていない。

AuthorizerのLambda関数から返しているポリシーは下記のとおりであった。

Authorizerのレスポンス
{
    "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

Authorizerのレスポンス(修正版)
{
    "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エラーが出るようになる。
型定義を信じよう。

コード例.ts
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(),
        }
    };
}

以上。

0
0
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
0
0