@blenz/middy-authorizer-middleware
Version:
JWT token validation
107 lines • 4.92 kB
JavaScript
;
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