I am using a new feature of the API Gateway with Lambda functions to use a Custom Authorizer (https://docs.aws.amazon.com/apigateway/latest/developerguide/use-custom-authorizer.html).
The authorizer uses JWT Tokens to validate the token for the current user context and scope(s). All is working fine but there is one concept regarding AWS Policies that I cannot quite figure out from documentation.
The output of a Custom Authorizer function has to be an object containing two things:
principalId
- in questionpolicyDocument
- a valid Policy document with statements to allow user authorized access to Lambda Resources, stages, etc.
Now, the examples for Custom Authorizers currently show almost arbitrary values for the principalId
variable. But if I am thinking correctly, this principalId
should be unique for each user? And perhaps have a user specific unique value associated with it (such as token.userId
or token.email
).
If this is true, then for my provided code below, if the JWT Token is not valid, then I do not have access to the userId
or email
, and have no clue what to set the principalId
to. I am setting it temporarily to user
just to have something return for a Deny policy to ensure that the response is 403 Forbidden
.
Anyone have any clue on best practices for setting principalId
for a Custom Authorizer?
var jwt = require('jsonwebtoken');
var JWT_SECRET = 'My$ecret!';
/**
* Implicit AWS API Gateway Custom Authorizer. Validates the JWT token passed
* into the Authorization header for all requests.
* @param {Object} event [description]
* @param {Object} context [description]
* @return {Object} [description]
*/
exports.handler = function(event, context) {
var token = event.authorizationToken;
try {
var decoded = jwt.verify(token, JWT_SECRET);
context.done(null, generatePolicy(decoded.id, 'Allow', 'arn:aws:execute-api:*:*:*'));
} catch(ex) {
console.error(ex.name + ": " + ex.message);
context.done(null, generatePolicy('user', 'Deny', 'arn:aws:execute-api:*:*:*'));
}
};
function generatePolicy(principalId, effect, resource) {
var authResponse = {};
authResponse.principalId = principalId;
if (effect && resource) {
var policyDocument = {};
policyDocument.Version = '2012-10-17'; // default version
policyDocument.Statement = [];
var statementOne = {};
statementOne.Action = 'execute-api:Invoke'; // default action
statementOne.Effect = effect;
statementOne.Resource = resource;
policyDocument.Statement[0] = statementOne;
authResponse.policyDocument = policyDocument;
}
return authResponse;
}