3
votes

I am using AWS API GAteway's Custom Authorizer to validate an application's token,
I am able to work with the Custom Authorizer properly,
ie. able to validate the token and return an IAM policy,
Which decides whether to allow the request to be forwarded to a Business logic Lambda function.

I now need to send additional data from the Custom Authorizer to the Business logic Lambda,

I have so far found out that there are two way's to achieve this -
1. Stringify data as Principal Id in the Policy to be returned.
2. Set data in Context object of the policy, which can be retrieved as $context.authorizer.<key> as per the code

I am trying the 2nd method, but unable to retrieve the data which was set in the context, in the Business logic Lambda.

I am using the NodeJs code from this GitHub Repo -
https://github.com/awslabs/aws-apigateway-lambda-authorizer-blueprints/blob/master/blueprints/nodejs/index.js

I am unable to view the default context set the Code -

authResponse.context = {
    key : 'value', // $context.authorizer.key -> value
    number : 1,
    bool: true
};

Following is the Event Object log in the Business Logic Lambda Function -

Event: {
    type: 'REQUEST',
    methodArn: 'someARN',
    resource: 'somePath',
    path: 'somePath',
    httpMethod: 'GET',
    headers: {
        accept: '*/*',
        'accept-encoding': 'gzip, deflate, br',
        'accept-language': 'en-US,en;q=0.9',
        authorization: 'someToken',
        'cache-control': 'no-cache',
        'content-type': 'application/json',
        Host: 'someAPI.execute-api.us-east-1.amazonaws.com',
        partner: 'php',
        'postman-token': 'someToken',
        timestamp: '1555034345',
        'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/someIP Safari/537.36',
        'X-Amzn-Trace-Id': 'Root=1-someId',
        'X-Forwarded-For': 'someIP',
        'X-Forwarded-Port': '443',
        'X-Forwarded-Proto': 'https'
    },
    multiValueHeaders: {
        accept: ['*/*'],
        'accept-encoding': ['gzip, deflate, br'],
        'accept-language': ['en-US,en;q=0.9'],
        authorization: ['someToken'],
        'cache-control': ['no-cache'],
        'content-type': ['application/json'],
        Host: ['someAPI.execute-api.us-east-1.amazonaws.com'],
        partner: ['php'],
        'postman-token': ['someToken'],
        timestamp: ['1555034345'],
        'user-agent': ['Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/someIP Safari/537.36'],
        'X-Amzn-Trace-Id': ['Root=1-someId'],
        'X-Forwarded-For': ['someIP'],
        'X-Forwarded-Port': ['443'],
        'X-Forwarded-Proto': ['https']
    },
    queryStringParameters: {
        user_id: '4'
    },
    multiValueQueryStringParameters: {
        user_id: ['4']
    },
    pathParameters: {},
    stageVariables: {
        someVariable: 'someValue',
    },
    requestContext: {
        resourceId: 'someId',
        resourcePath: 'somePath',
        httpMethod: 'GET',
        extendedRequestId: 'someId',
        requestTime: '12/May/2019:12:05:51 +0000',
        path: 'somePath',
        accountId: 'someId',
        protocol: 'HTTP/1.1',
        stage: 'dev',
        domainPrefix: 'someAPIDomain',
        requestTimeEpoch: 1557662751493,
        requestId: 'someId',
        identity: {
            cognitoIdentityPoolId: null,
            accountId: null,
            cognitoIdentityId: null,
            caller: null,
            sourceIp: 'someIP',
            principalOrgId: null,
            accessKey: null,
            cognitoAuthenticationType: null,
            cognitoAuthenticationProvider: null,
            userArn: null,
            userAgent: 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/someIP Safari/537.36',
            user: null
        },
        domainName: 'someAPI.execute-api.us-east-1.amazonaws.com',
        apiId: 'someId'
    }
}

I am using the default, Method Request Passthrough -

##  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",
    "api-key" : "$context.identity.apiKey",
    "authorizer-principal-id" : "$context.authorizer.principalId",
    "caller" : "$context.identity.caller",
    "cognito-authentication-provider" : "$context.identity.cognitoAuthenticationProvider",
    "cognito-authentication-type" : "$context.identity.cognitoAuthenticationType",
    "cognito-identity-id" : "$context.identity.cognitoIdentityId",
    "cognito-identity-pool-id" : "$context.identity.cognitoIdentityPoolId",
    "http-method" : "$context.httpMethod",
    "stage" : "$context.stage",
    "source-ip" : "$context.identity.sourceIp",
    "user" : "$context.identity.user",
    "user-agent" : "$context.identity.userAgent",
    "user-arn" : "$context.identity.userArn",
    "request-id" : "$context.requestId",
    "resource-id" : "$context.resourceId",
    "resource-path" : "$context.resourcePath"
    }
}
1

1 Answers

3
votes

Was able to receive the values on the Business Lambda function,
by modifying the Mapping Template, under the API's Integration Request -

"context" : {
    .
    .
    .
    myKey : $context.authorizer.key,
    myNum : $context.authorizer.number,
    myBool : $context.authorizer.bool
}

Data was received under event.context object on the function as myKey, myNum and myBool.
For those using API Gateway's Integration Request's Lambda Proxy setting,
don't need to anything, values set on context in the Authorizer function get passed directly.
And should receive under -

event.requestContext.authorizer