UNPKG

auth0-lambda-authorizer

Version:

An Auth0 Authorizer for AWS Lambda

180 lines 7.9 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (_) try { if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [0, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; var _this = this; exports.__esModule = true; var Either_1 = require("fp-ts/lib/Either"); var jwt = require("jsonwebtoken"); var R = require("ramda"); var logFactory_1 = require("./logFactory"); var log = logFactory_1.logFactory.getLogger("lambda.authorizer"); exports.getPolicyDocument = function (effect, resource) { var policyDocument = { Statement: [ { Action: "execute-api:Invoke", Effect: effect, Resource: resource }, ], Version: "2012-10-17" }; return policyDocument; }; var validateToken = function (token) { if (!token) { var errorMessage = "Expected 'event.authorizationToken' parameter to be set"; log.error(errorMessage); throw new Error(errorMessage); } }; var validateParams = function (params) { if (!params.type || params.type !== "TOKEN") { var errorMessage = "Expected 'event.type' parameter to have value TOKEN"; log.error(errorMessage); throw new Error(errorMessage); } }; var getToken = function (params) { validateParams(params); var tokenString = params.authorizationToken; validateToken(tokenString); var match = tokenString.match(/^Bearer (.*)$/); if (!match || match.length < 2) { var errorMessage = "Invalid Authorization token - '" + tokenString + "' does not match 'Bearer .*'"; log.error(errorMessage); throw new Error(errorMessage); } return match[1]; }; var verifyToken = function (token, secret, algorithm, audience) { try { var verified = jwt.verify(token, secret, { algorithms: [algorithm] }); if (!R.is(String, verified)) { return Either_1.right(verified); } else { log.error({ data: verified, msg: "FAILED TO VERIFY" }); return Either_1.left(new Error("Failed to verify")); } } catch (e) { log.error({ data: e, msg: "Failed to verify the Auth0 token" }); return Either_1.left(e); } }; var getRoles = function (payload) { if (R.isNil(payload)) { return []; } else { return payload.roles; } }; var craftResponse = function (token, client, algorithm, policyDocument) { log.info({ msg: "In retrieveSigningKey ", data: { token: token, client: client, policyDocument: policyDocument } }); var decoded = jwt.decode(token, { complete: true }); var kid = decoded.header.kid; log.info({ msg: "Decoded ", data: decoded }); if (decoded instanceof String) { log.error({ data: decoded, msg: "FAILED TO DECODE " }); return Either_1.left(Error("Decoding failed")); } else { var authResponse = { context: { scope: decoded.payload.sub }, policyDocument: policyDocument, principalId: decoded.payload.sub }; return Either_1.right({ authResponse: authResponse, payload: decoded.payload }); } }; exports.getKeys = function (token, client) { return new Promise(function (resolve, reject) { client.getKeys(function (err, keys) { if (err) { log.error({ data: err, msg: "An error occurred getting keys" }); return reject(err); } return resolve(keys); }); }); }; exports.getSigningKey = function (client, kid) { return new Promise(function (resolve, reject) { client.getSigningKey(kid, function (err, key) { if (err) { log.error({ data: err, msg: "An error occurred fetching the Signing Key" }); return reject(err); } var signingKey = key.publicKey || key.rsaPublicKey; return resolve(signingKey); }); }); }; exports.authenticate = function (apiGatewayEvent, tokenConfig) { return __awaiter(_this, void 0, void 0, function () { var client, algorithm, auth0Audience, token, policyDocument, keys, signingKey, verification; return __generator(this, function (_a) { switch (_a.label) { case 0: client = tokenConfig.client, algorithm = tokenConfig.algorithm, auth0Audience = tokenConfig.auth0Audience; token = getToken(apiGatewayEvent); policyDocument = exports.getPolicyDocument("Allow", apiGatewayEvent.methodArn); log.info({ msg: "Created Policy Document: ", data: policyDocument }); return [4 /*yield*/, exports.getKeys(token, client)]; case 1: keys = _a.sent(); log.info({ data: keys, msg: "Fetched Keys from Auth0" }); return [4 /*yield*/, exports.getSigningKey(client, keys[0].kid)]; case 2: signingKey = _a.sent(); log.info({ data: signingKey, msg: "Retrieved signing key from Auth0" }); verification = verifyToken(token, signingKey, algorithm, auth0Audience) .chain(function (verified) { log.info({ msg: "Verified Token: ", data: verified }); return craftResponse(token, client, algorithm, policyDocument); }) .mapLeft(function (e) { log.error({ msg: "An unrecovarable exception ocurred while authenticating ", data: e }); return e; }); return [2 /*return*/, verification]; } }); }); }; //# sourceMappingURL=authorizer.js.map