Search code examples
amazon-web-servicesaws-lambdajwtaws-api-gatewayapi-gateway

API Gateway JWT Authorizer is always returning 401 even though authorization test succeeds


I have an API Gateway that i'm trying to add JWT authorization to. I have setup the authorization lambda based on this AWS resource. I have tested the lambda direct and also through the 'test' button and both generate the proper response policy document just fine.

But when i test through the endpoint with postman i always get 401

{
    "message": "Unauthorized"
}

I turned on CloudWatch logging and also turned on X-Ray Tracing and the request is never logged at all. I see the logs for the test invocations and i see other logs for other non-authorized resources in CloudWatch and X-Ray.

If i disable the authorizer and deploy the request goes through just fine.

What gives?

Here is my authorizer code.

export async function handler(event) {
    console.log(event);
    
    let response = generatePolicy(null, 'Deny', event.methodArn);
    let token = event.authorizationToken;
    
    if (token) {
        const jwt = await validateJwtSignature(token.substring(7)); // Strip "Bearer " from the begning of the token..
        if (jwt) {
            response = generatePolicy(jwt, 'Allow', event.methodArn);
        }
    }
    
    console.log(JSON.stringify(response));
    return response;
};

// Help function to generate an IAM policy
// Ex.  generatePolicy('user', 'Deny', event.methodArn);
// Ex.  generatePolicy('user', 'Allow', event.methodArn);
function generatePolicy(jwt, effect, resource) {
    const authResponse = {
        principalId: (jwt || {}).sub
    };

    if (effect && resource) {
        authResponse.policyDocument = {
            Version: '2012-10-17',
            Statement: [
                {
                    Action: 'execute-api:Invoke',
                    Effect: effect,
                    Resource: resource
                }
            ]
        };
    }

    return authResponse;
}

enter image description here enter image description here enter image description here


Solution

  • Turns out the AWS guide that is was using is not clear on step # 16 here where it says to use authorizationToken as the Token source.

    This is wrong. It should be Authorization as that is the right header. The guide made me think that the Token Source and the property passed to the lambda were the same thing.

    https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-use-lambda-authorizer.html

    This is a working authorizer. Rather annoying that neither CloudWatch nor x-ray logging indicated that the request was rejected for that reason.

    enter image description here