I am using custom authentication (with custom authorizer) for accessing AWS lambda. The authorization process works fine. But I have a problem to transmit data (ex principalId) between the authorizer lambda and the business lambda. All my lambdas are developed in JS. As explain in AWS doc, in the authorizer lambda, I add few simple fields (principalId in the code below) in context field of the Auth response. But in my business lambda, I am not able to get these fields. The AWS documentation talks about $context variable.
First, could you explain me if the $context variable is another variable or the same variable than the context variable received in parameter of the JS function?
Second, could you explain me how to get in my business lambda the data field (ex: principalId) provided by the authorizer?
Seb
There is no in-built technique for sharing data between Lambda functions. Each function runs independently and there is no shared datastore. You will need to use an external datastore -- that is, something outside of Lambda that can persist the data.
If access is denied, API Gateway returns a suitable HTTP status code, such as 403 ACCESS_DENIED . If access is allowed, API Gateway executes the method. If caching is enabled in the authorizer settings, API Gateway also caches the policy so that the Lambda authorizer function doesn't need to be invoked again.
Best practices suggest that one separate the handler from the Lambda's core logic. Not only is it okay to add additional definitions, it can lead to more legible code and reduce waste--e.g. multiple API calls to S3.
You can use custom authorizers in API Gateway to support any bearer token. This allows you to authorize access to your APIs using tokens from an OAuth flow or SAML assertions. Further, you can leverage all of the variables available to IAM policies without setting up your API to use IAM authorization.
The policy document of the authorizer can be enriched with a context where you can put your custom data. That data will be provided to the business lambda via the event.
Here is an example of a policy document:
const policy = {
context: {
customKey: 'payload data',
},
policyDocument: {
Statement: [{
Action: 'execute-api:Invoke',
Effect: effect,
Resource: resource,
}],
Version: '2012-10-17',
},
principalId: sub,
};
The context contains a "customKey" with payload data as a string.
The mapping template for your API then should look like this:
{
"customKey": "$context.authorizer.customKey"
}
Finally in your business lambda you can access the value of your customKey via the event:
exports.handler = async (event, context) => {
console.log(event.customKey);
.
.
.
};
This should log "payload data" according to my example.
Notice that you cannot set a JSON object or array as a valid value of any key in the context map according to the documentation
I guess the $context
variable you are referring to is the one available in the API Gateway mapping template. It is not equivalent to the context
parameter of the business Lambda.
However, using the mapping template and its $context
variable, you can build the event
parameter of the business Lambda.
If the mapping template of your API endpoint looks like this:
{
"principalId" : "$context.authorizer.principalId"
}
You should retrieve the principalId
in the Lambda's event
parameter.
Using the passthrough option, principalId
should be available in event.context['authorizer-principal-id']
. This is the default behavior when you create an endpoint.
References about mapping templates in the doc:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With