6
votes

Calling the Lambda callback function from a Lambda Authorizer with the string Unauthorized in the error parameter returns a 401 response with the body:

{ "message": "Unauthorized" }

Trying to use any other string in the response results in the response:

{ "message": null }

If instead you return a Deny Policy Document in the result parameter of the callback, you'll get a 403 with the response something like:

{ "message": "Unable to access resource with an explicit deny" }

After looking around it seems you need to configure a Gateway Response to return a custom response from a Lambda Authorizer, which I have working for the 403 response, but can't figure out how to do this for a 401.

For the 403 I created a Gateway Response with the template:

{\"message\":\"$context.authorizer.stringKey\"}

Then on the result object I set the following

ResultObject.context.stringKey = 'My custom response'

This works and is documented here.

However, for the 401, because I am not returning a policy document I don't know how to use a custom response. I created the same Gateway Response as I did for the 403, but if I hit the callback with any string (other than 'Unauthorized') in the error param I get the null message. I can't return in the result param because this needs to be a response structure containing the Policy Document.

Any ideas on how I can return a custom response with a 401?

2
what are you trying to achieve in terms of business rule?Alessandro Oliveira
We want to return a different response messages depending on whether the AuthorizationToken is not the structure we expect, not signed by us, expired and so onSimian
then you should not do this! because you might be revealing important information for an attacker. In this scenario your app should redirect user for login screen and that's all. Then regenerate the token when the user logs in using another endpoint, this token generation endpoint could give more detailed messages if you want, but I would limit to user/password didn't match or something like it in any scenario.Alessandro Oliveira
Thank you for your advice, but should I want to return the same response for all scenarios with a different message other than ‘unauthorised’, is this possible?Simian
No, I think it is not possible.Alessandro Oliveira

2 Answers

6
votes

Sorry to not answer your direct question, but I do think people (like me) might encounter this thread when looking on how to implement the first part of your question (return a 401 response from the authorizer lambda). You can follow AWS example here.

TL;DR:

For async functions, throw an error whose message exactly match the string "Unauthorized":

exports.handler = async function (event) {
  ...
  throw Error("Unauthorized");
}

For sync. functions, call the callback function with its first parameter (the error response) exactly match the string "Unauthorized":

exports.handler =  function(event, context, callback) {
  ..
  callback("Unauthorized");  // Compared to a successful response `callback(null, ...)`
}

In both cases the response from the API gateway endpoint protected by your authorizer lambda would be:

401
{
  "message": "Unauthorized"
}
1
votes

You need to raise an exception, so when using node:

context.fail("Unauthorized");

For C# see http://yogivalani.com/aws-custom-lambda-authorizer-returns-401-unauthorized/