UNPKG

@blenz/middy-authorizer-middleware

Version:

JWT token validation

107 lines 4.92 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; result["default"] = mod; return result; }; Object.defineProperty(exports, "__esModule", { value: true }); const http_errors_1 = __importDefault(require("http-errors")); const jsonwebtoken_1 = __importStar(require("jsonwebtoken")); const jwks_rsa_1 = __importDefault(require("jwks-rsa")); const auth_config_json_1 = __importDefault(require("../auth.config.json")); const authClient = jwks_rsa_1.default({ cache: true, rateLimit: true, jwksUri: `https://${auth_config_json_1.default.domain}/.well-known/jwks.json`, }); /** * Middy middleware for token authentication * * ``` * handler.use(AuthorizeMiddleware({...})) * ``` */ exports.AuthMiddleware = (config) => { return ({ before: async (handler) => { // Authorization not required if (!config.credentialsRequired) { return; } // Get token from auth header and verify it exists const authHeader = handler.event.headers.authorization; if (!authHeader) { throw new http_errors_1.default.Forbidden('Missing authorization header'); } // Validate auth header format const authHeaderParts = authHeader.split(' '); if (authHeaderParts.length !== 2 || authHeaderParts[0] !== 'Bearer') { throw new http_errors_1.default.Forbidden('Authorization header malformed - expected `Bearer token`'); } // Get the token const authToken = authHeaderParts[1]; if (authToken === undefined) { throw new http_errors_1.default.Forbidden('Authorization token undefined'); } // Decode the token let decodedToken; try { decodedToken = jsonwebtoken_1.default.decode(authToken, { complete: true }); } catch (err) { throw new http_errors_1.default.Forbidden(err.message); } // Validate token is not malformed if (!decodedToken || !decodedToken.header || !decodedToken.header.kid) { throw new http_errors_1.default.Forbidden('JWT token is malformed'); } const kid = decodedToken.header.kid; authClient.getSigningKey(kid, (err, key) => { if (err) { throw new http_errors_1.default.Forbidden(err.message); } const jwtOptions = { algorithms: ['RS256'], audience: auth_config_json_1.default.audience, issuer: `https://${auth_config_json_1.default.domain}` }; try { jsonwebtoken_1.default.verify(authToken, key.getPublicKey(), jwtOptions, (err, decoded) => { if (err) { throw new http_errors_1.default.Forbidden(err.message); } // TODO: Don't use auth0 roles, instead design our own role structure if (config.acceptedRoles) { const roles = decoded[`https://${process.env.URL}/roles`]; if (!roles || !roles.length || !config.acceptedRoles.some(x => roles.includes(x))) { throw new http_errors_1.default.Forbidden('User is not permitted to access the requested resource'); } } // Attach decoded token to auth event handler.event.auth = { payload: decoded, token: authToken }; console.log("SDFSDZFF"); console.log(handler.event.auth); }); } catch (err) { if (err instanceof jsonwebtoken_1.TokenExpiredError) { throw new http_errors_1.default.Forbidden(`Token expired: ${new Date(err.expiredAt).toUTCString()}`); } else if (err instanceof jsonwebtoken_1.NotBeforeError) { throw new http_errors_1.default.Forbidden(`Token not valid until: ${err.date.toUTCString()}`); } else { throw new http_errors_1.default.Forbidden('Invalid token'); } } }); }, }); }; exports.default = exports.AuthMiddleware; //# sourceMappingURL=auth.middleware.js.map