Reputation: 141
I've spent the better part of today trying to make authorizers work, I've checked multiple examples and they all seem to be doing the same thing my code does.
I use serverless framework here's the authorization code:
exports.handler = function (event: APIGatewayTokenAuthorizerEvent): APIGatewayAuthorizerResult {
const authorizer = new Authorizer();
try {
if (!event.authorizationToken) throw new Error("No token");
const token = event.authorizationToken.split(" ")[1];
const decodedData = authorizer.verifyToken(token) as unknown as User;
const policy = generatePolicy(token, event.methodArn);
return {
...policy,
context: {
user: JSON.stringify(decodedData),
},
};
} catch (err) {
console.log(err);
throw "Unauthorized";
}
};
const generatePolicy = (principalId: string, methodArn: string) => {
return {
principalId,
policyDocument: {
Version: "2012-10-17",
Statement: [
{
Action: "execute-api:Invoke",
Effect: "Allow",
Resource: methodArn,
},
],
},
};
};
and here's the serverless config
const serverlessConfiguration: AWS = {
service: "user-crud",
frameworkVersion: "2",
custom: {
webpack: {
webpackConfig: "./webpack.config.js",
includeModules: true,
},
},
plugins: ["serverless-webpack"],
provider: {
name: "aws",
runtime: "nodejs14.x",
region: "eu-west-1",
apiGateway: {
minimumCompressionSize: 1024,
shouldStartNameWithService: true,
},
environment: {
AWS_NODEJS_CONNECTION_REUSE_ENABLED: "1",
},
lambdaHashingVersion: "20201221",
},
functions: {
jwtAuthorizer: {
handler: "src/api/authorizer.handler",
name: "jwtAuthorizer",
},
get: {
name: "get",
handler: "src/api/get.handler",
role: "arn:aws:iam::109394173706:role/dynamodb_cloudwatch_full",
events: [
{
http: {
path: "get",
method: "get",
cors: true,
authorizer: "jwtAuthorizer",
},
},
],
},
}...
I always get 500 response when the token is correct and I return the object, so I guess there's something wrong with the return object?
If the token is incorrect and I throw "Unauthorized" then I get back the correct 401 response.
Upvotes: 8
Views: 7986
Reputation: 2255
You need to configure Resource-based policy statements in your AWS Lambda to allow API Gateway Authorizer to call your function. It is in Configuration -> Permissions -> Resource-based policy statements.
Then, add something like the following:
{
"Version": "2012-10-17",
"Id": "default",
"Statement": [
{
"Sid": "allow-api_gateway-authorizer-invoke",
"Effect": "Allow",
"Principal": {
"Service": "apigateway.amazonaws.com"
},
"Action": "lambda:InvokeFunction",
"Resource": "<LAMBDA AUTHORIZER FUNCTION ARN HERE>",
"Condition": {
"ArnLike": {
"AWS:SourceArn": "arn:aws:execute-api:<API GATEWAY REGION>:<ACCOUNT_NUMBER>:*/authorizers/*"
}
}
}
]
}
Upvotes: 0
Reputation: 727
Well, there are some other reasons for getting,
{
message : null
}
error from Api Gateway. I had a very hard time identifying mine.
Lambda Invoke Role
for your authorizerExecution failed due to configuration error: Invalid JSON in response: Unrecognized field "headers", not marked as ignorable
in Api Gateway Logs. You have to tackle it by adding cors with explicit mention of those headersboolean
based return, you must enable lambda response 2.0delete
the RestApiGateway
and create again. The changes might not get updated in CloudFront properly sometimes. function allowPolicy(methodArn) {
console.log("Allow Policy")
return {
"principalId": "apigateway.amazonaws.com",
"policyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Action": "execute-api:Invoke",
"Effect": "Allow",
"Resource": methodArn
}
]
},
"context": {
"stringValue": "blablabla",
"numberValue": 10,
"booleanValue": true,
}
};
}
Upvotes: 7
Reputation: 141
Apparently, the handler needs to be async, otherwise, it expects a callback... Time well spent :|
Upvotes: 6