Skip to content

Instantly share code, notes, and snippets.

@mauricio-santos-deel
Created June 12, 2019 16:29
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mauricio-santos-deel/3b4de84ddd16451435024ce0b6141a12 to your computer and use it in GitHub Desktop.
Save mauricio-santos-deel/3b4de84ddd16451435024ce0b6141a12 to your computer and use it in GitHub Desktop.
Example of Aws Lambda Authorizer that uses JWT
const jwtLib = require('jsonwebtoken');
const jwksClient = require('jwks-rsa');
const util = require('util'); // node-js util
var httpRequestPromise = require('request-promise');
module.exports.handler = async (event, context) => {
try {
const jwtToken = getToken(event);
const jwtDecoded = jwtLib.decode(jwtToken, { complete: true });
const myAppUserId = jwtDecoded.payload.userId;
if (!decoded || !decoded.header || !decoded.header.kid) {
throw new Error('invalid token');
}
const client = jwksClient({
cache: true,
rateLimit: true,
jwksRequestsPerMinute: 10, // Default value
jwksUri: process.env.JWKS_URI
});
const jwtKey = await util.promisify(client.getSigningKey);
const jwtOptions = {audience: process.env.AUDIENCE, issuer: process.env.TOKEN_ISSUER};
const signingKey = jwtKey.publicKey || jwtKey.rsaPublicKey;
await jwt.verify(token, signingKey, jwtOptions);
const userData = await httpRequestPromise({
uri: `http://www.myapp.com/api/users/${myAppUserId}`,
json: true,
});
if (!userIsAuthorized(userData)) {
throw new Error('User is not authorized by specific business rules');
}
return buildPolicy(event, decoded, userData);
} catch (err) {
console.log(err);
context.fail("Unauthorized");
return `Unauthorized: ${err.message}`;
}
};
function getToken(event) {
if (!event.type || event.type !== 'TOKEN') {
throw new Error('Expected "event.type" parameter to have value "TOKEN"');
}
const tokenString = event.authorizationToken;
if (!tokenString) {
throw new Error('Expected "event.authorizationToken" parameter to be set');
}
const match = tokenString.match(/^Bearer (.*)$/);
if (!match || match.length < 2) {
throw new Error(`Invalid Authorization token - ${tokenString} does not match "Bearer .*"`);
}
return match[1];
}
function userIsAuthorized(userData) {
// Here is where you implement your specifics business rules
return true;
}
function buildPolicy(decoded, userData) {
return {
principalId: userId,
policyDocument: {
Version: '2012-10-17', // default version
Statement: [{
Action: 'execute-api:Invoke', // default action
Effect: 'Allow',
Resource: "*"
}]
},
// the context variable will be sent to the microservice
context: {
scope: decoded.scope,
payload: JSON.stringify(decoded),
userData: JSON.stringify(userData),
userId: userData.id
}
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment