Skip to content

Instantly share code, notes, and snippets.

@julianpitt
Last active March 5, 2019 01:07
Show Gist options
  • Save julianpitt/af84d9aa321953f1bddbd0a91318db70 to your computer and use it in GitHub Desktop.
Save julianpitt/af84d9aa321953f1bddbd0a91318db70 to your computer and use it in GitHub Desktop.
'use strict';
/**
* Created by Peter Sbarski
* Updated by Mike Chambers
* Updated by Julian Pittas
* Last Updated: 27/02/2018
*
* Required Env consts:
* AUTH0_DOMAIN
*/
const jwt = require('jsonwebtoken');
const req = require('request');
const generatePolicy = (principalId, effect, resource) => {
const authResponse = {};
authResponse.principalId = principalId;
if (effect && resource) {
const statementOne = {
Action: 'execute-api:Invoke', // default action
Effect: effect,
Resource: resource,
}
const policyDocument = {
Version: '2012-10-17',
Statement: [statementOne]
}
authResponse.policyDocument = policyDocument;
}
return authResponse;
};
const verifyJWTToken = (jwtToken, pubKey) => {
return new Promise((resolve, reject) => {
jwt.verify(jwtToken, pubKey, { algorithms: ['RS256'] }, (err, decoded) => {
if (err) {
reject(err);
} else {
resolve(decoded);
}
});
});
};
const rp = (url) => {
new Promise((resolve, reject) => {
request(url, function (error, response, body) {
if(error) {
reject(error)
} else {
resolve(body)
}
});
});
}
const handler = (event, context, callback) => {
if (!event.authorizationToken) {
callback('Could not find authToken');
return;
}
const jwtToken = event.authorizationToken.split(' ')[1];
if (!jwtToken) {
callback('Could not find authToken');
return;
}
const decodedToken = jwt.decode(jwtToken, {complete: true});
const Auth0ApiBaseUrl = process.env.AUTH0_DOMAIN;
if(!Auth0ApiBaseUrl) {
callback('Base Url not found');
return;
}
return rp(`https://${Auth0ApiBaseUrl}/.well-known/jwks.json`)
.then((jwks) => {
const jwksKey = JSON.parse(jwks).keys[0];
//Validate the algorithm
if (!jwksKey) {
throw new Error('No supported jwt keys');
}
//Validate the algorithm
if (jwksKey.alg !== 'RS256' || decodedToken.header.alg !== 'RS256') {
throw new Error('Invalid algorithm used, only RS256 supported');
}
//Validate the signing key
if (!jwksKey.kid || decodedToken.header.kid !== jwksKey.kid) {
throw new Error('Invalid signing algorithm');
}
//Validate the certificate
if (!jwksKey.x5c[0]) {
throw new Error('No certificate found');
}
const cert = `-----BEGIN CERTIFICATE-----\n${jwksKey.x5c[0]}\n-----END CERTIFICATE-----\n`;
return cert;
})
.then((pubKey) => verifyJWTToken(jwtToken, pubKey))
.then(() => {
callback(null, generatePolicy('user', 'allow', event.methodArn));
})
.catch((err) => {
console.log('Failed jwt verification: ', err, 'auth: ', event.authorizationToken);
callback('Authorization Failed');
});
};
module.exports = {
handler
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment