I have a couple of days trying to secure my API Gateway using custom authorizers with the auth0 service. I have my lambda which validates my bearer token, the Lambda does work if I invoke it inside the AWS console and when I create a custom authorizer I can successfully tested with a Bearer token.
When I try to attach the authorizer to my API Gateway methods and test the request with postman and the token provided by auth0 it always returns a 401 status code. I read my logs in CloudWatch and the authorization Lambda it's never triggered whenever I make the HTTP request. I am following this tutorial: https://auth0.com/docs/integrations/aws-api-gateway/custom-authorizers/
And this is my Authorization lambda code:
Handler:
'use strict';
let jwtManager = require("./jwt_manager");
module.exports.authenticate = (event, context, callback) => {
jwtManager.validate(event, function (error, data) {
if (error) {
if (!error) {
context.fail("Unhandled error");
}
context.fail(error);
}
else {
console.log("SUCCEED");
context.succeed(data);
}
});
};
And this is the jwtManager:
"use strict";
require("dotenv").config({ silent: true });
let jwksClient = require("jwks-rsa");
let jwt = require("jsonwebtoken");
module.exports.validate = function(params, callback) {
var token = validateParams(params);
var client = jwksClient({
cache: true,
rateLimit: true,
jwksRequestsPerMinute: 10,
jwksUri: process.env.JWKS_URI
});
var decodedJwt = jwt.decode(token, { complete: true });
var kid = decodedJwt.header.kid;
client.getSigningKey(kid, function(error, data) {
if (error) {
console.log(error);
callback(error);
} else {
var signingKey = data.publicKey || data.rsaPublicKey;
jwt.verify(
token,
signingKey,
{ audience: process.env.AUDIENCE, issuer: process.env.ISSUER },
function(error, decoded) {
if (error) {
console.log("ERROR");
console.log(error);
callback(error);
}
else {
console.log(decoded);
var response = {
principalId: decoded.sub,
policyDocument: getPolicyDocument("Allow", params.methodArn),
context: {
scope: decoded.scope
}
}
console.log(response);
console.log(response.policyDocument);
callback(null, response);
}
}
);
}
});
};
function validateParams(params) {
var token;
if (!params.type || params.type !== "TOKEN") {
throw new Error("Expected 'event.type' parameter to have value TOKEN");
}
var tokenString = params.authorizationToken;
if (!tokenString) {
throw new Error("Expected 'event.authorizationToken' parameter to be set");
}
var match = tokenString.match(/^Bearer (.*)$/);
if (!match || match.length < 2) {
throw new Error(
"Invalid Authorization token - '" +
tokenString +
"' does not match 'Bearer .*'"
);
}
return match[1];
}
function getPolicyDocument(effect, resource) {
var policyDocument = {};
policyDocument.Version = '2012-10-17'; // default version
policyDocument.Statement = [];
var statementOne = {};
statementOne.Action = [ 'execute-api:Invoke', 'lambda:Invoke'] ; // default action
statementOne.Effect = effect;
statementOne.Resource = resource.split('/')[0] + '/*';
policyDocument.Statement[0] = statementOne;
return policyDocument;
}
Thanks in advance!
When you test an API Gateway with a custom authorizer attached but the auth lambda function never triggered, it is likely due to unsuccessful validation in token header name/ token pattern validation.
I am able to reproduce your issue.
The authorizer can only be triggered IF I change the header name from "Authorization" to "AuthorizationToken" in POSTMAN.
check the token header name I made the authorizer works
I think it is likely a new bug in AWS portal as I noticed they have changed the UI to configure API Gateway Authorizers not long ago.
It is very strange a HTTP request has to send bearer token in a header with name "AuthorizationToken". If your AWS plan allows you to access their technical support, you should alert them about this issue.