API 网关映射模板未向 Lambda 函数发送 JWT 身份验证声明

API Gateway mapping template is not sending JWT auth claims to Lambda function

我无法将从请求的授权 header 派生的特定 JWT 授权声明信息发送到 API 网关 REST API 端点(使用 non-proxy Lambda一体化)。该端点由 Cognito 用户池授权方保护,并使用 Login with Amazon 作为身份提供者。从 API 网关的 Cloudwatch 执行日志中,我可以看到 JWT 授权方声明:

(***) Cognito User Pool Authorizer claims from JWT: {
    at_hash=***,
    sub=***,
    cognito:groups=us-east-1_***_LoginWithAmazon,
    email_verified=false,
    iss=https://cognito-idp.us-east-1.amazonaws.com/us-east-1_***,
    cognito:username=loginwithamazon_amzn1.account.***,
    nonce=***,
    origin_jti=***,
    aud=***,
    identities={
        "dateCreated":"***",
        "userId":"amzn1.account.***",
        "providerName":"LoginWithAmazon",
        "providerType":"LoginWithAmazon",
        "issuer":null,
        "primary":"true"
    },
    token_use=id,
    auth_time=***,
    name=***,
    exp=*** UTC 2022,
    iat=*** UTC 2022,
    jti=***,
    email=***
}

(***) Method request path: {}
(***) Method request query string: {}
(***) Method request headers: {Authorization=******[TRUNCATED]
(***) Method request body before transformations: 
(***) Endpoint request URI: https://lambda.us-east-1.amazonaws.com/2015-03-31/functions/arn:aws:lambda:us-east-1:***:function:***/invocations
(***) Endpoint request headers: {x-amzn-lambda-integration-tag=***, Authorization=***, X-Amz-Date=***, x-amzn-apigateway-api-id=***, X-Amz-Source-Arn=arn:aws:execute-api:us-east-1:***:***/***/GET/myapi, Accept=application/json, User-Agent=AmazonAPIGateway_***, X-Amz-Security-Token=*** [TRUNCATED]
(***) Method request body after transformations: 

我定义了以下映射模板来组成一个 Lambda 函数事件,其中包含 API 请求 body、参数、headers 以及包含来自JWT 声明 object:

##  See http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html
##  This template will pass through all parameters including path, querystring, header, stage variables, and context through to the integration endpoint via the body/payload
#set($allParams = $input.params())
{
"body-json" : $input.json('$'),
"params" : {
#foreach($type in $allParams.keySet())
    #set($params = $allParams.get($type))
"$type" : {
    #foreach($paramName in $params.keySet())
    "$paramName" : "$util.escapeJavaScript($params.get($paramName))"
        #if($foreach.hasNext),#end
    #end
}
    #if($foreach.hasNext),#end
#end
},
"stage-variables" : {
#foreach($key in $stageVariables.keySet())
"$key" : "$util.escapeJavaScript($stageVariables.get($key))"
    #if($foreach.hasNext),#end
#end
},
"context" : {
    "account-id" : "$context.identity.accountId",
    "api-id" : "$context.apiId",
    "caller" : "$context.identity.caller",
    "http-method" : "$context.httpMethod",
    "request-id" : "$context.requestId",
    "resource-id" : "$context.resourceId",
    "resource-path" : "$context.resourcePath",
    "userId": "$context.authorizer.claims.identities.userId",
    "name": "$context.authorizer.claims.name",
    "email": "$context.authorizer.claims.email",
    "email_verified": "$context.authorizer.claims.email_verified"
    }
}

当我将事件 object 的 JSON 转储记录到 Cloudwatch 时,我看到空的 JSON object {}。是我的映射模板有问题,还是我的 API 网关配置导致了此行为?

原来我应该在每次更改 VTL 映射模板时部署 API!仅在修改模板后点击 [保存] 按钮不会使更改生效。应更新 AWS 文档,因为 API 何时应为 re-deployed.

并不明显

此外,由于 JWT 授权方声明中 identities 键的值是一个字符串,因此我需要对 userId [=20= 上的上述映射模板进行轻微修改].

"userId": "$util.parseJson($context.authorizer.claims.identities).userId",