UNPKG

@topgroup/diginext

Version:

A BUILD SERVER & CLI to deploy apps to any Kubernetes clusters.

177 lines (176 loc) 8.88 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const jsonwebtoken_1 = require("jsonwebtoken"); const lodash_1 = require("lodash"); const passport_1 = __importDefault(require("passport")); const app_config_1 = require("../app.config"); const passports_1 = require("../modules/passports"); const mongodb_1 = require("../plugins/mongodb"); const sendAuthErrorResponse = (res, message, statusCode = 401, errorCode = "UNAUTHORIZED") => { res.status(statusCode) .header("Content-Type", "application/json") .json({ status: 0, error: true, messages: [message], errorCode, timestamp: new Date().toISOString(), }); }; /** * Why you don't need to care about this file? * --- * Because the {User} was already verified at "jwtStrategy" step before passing the token here! */ const jwt_auth = (req, res, next) => passport_1.default.authenticate("jwt", { session: false }, async function (err, user, info) { try { // Detailed logging for development if ((0, app_config_1.IsDev)()) { console.log("auth-jwt > authentication details :>>", { hasError: !!err, userExists: !!user, info: info === null || info === void 0 ? void 0 : info.toString(), }); } const { UserService } = await Promise.resolve().then(() => __importStar(require("../services"))); const userSvc = new UserService(); if (!user) { /** * If the token is expired or invalid, * we should delete it in the cookies or HTTP response */ res.cookie("x-auth-cookie", ""); res.header("Authorization", ""); delete req.headers.cookie; // check refresh token here: const isAccessTokenExpired = (info === null || info === void 0 ? void 0 : info.toString().indexOf("TokenExpiredError")) > -1; if (isAccessTokenExpired) { let refresh_token = req.query.refresh_token; console.log("jwt_auth > refresh_token :>> ", refresh_token); if (!refresh_token) { return sendAuthErrorResponse(res, "Refresh token is required.", 401, "MISSING_REFRESH_TOKEN"); } try { const { error: isInvalidRefreshToken, tokenDetails: refreshTokenDetails } = await (0, passports_1.verifyRefreshToken)(refresh_token); // More explicit error handling if (isInvalidRefreshToken) { console.error("jwt_auth > Invalid refresh token :>>", refresh_token); return sendAuthErrorResponse(res, "Invalid refresh token", 401, "INVALID_REFRESH_TOKEN"); } if (refreshTokenDetails.isExpired) { console.error("jwt_auth > Expired refresh token :>>", refresh_token); return sendAuthErrorResponse(res, "Refresh token expired", 401, "REFRESH_TOKEN_EXPIRED"); } // refresh token is valid -> generate new access token const { accessToken, refreshToken } = await (0, passports_1.generateJWT)(refreshTokenDetails.id, { expiresIn: process.env.JWT_EXPIRE_TIME || "2d", workspaceId: refreshTokenDetails.workspaceId, }); // assign new access token to cookie and request & response headers: res.cookie("x-auth-cookie", accessToken); res.cookie("refresh_token", refreshToken); res.header("Authorization", `Bearer ${accessToken}`); req.headers.authorization = `Bearer ${accessToken}`; req.query.access_token = accessToken; req.query.refresh_token = refreshToken; return jwt_auth(req, res, next); } catch (e) { console.error("jwt_auth > Refresh token error :>>", { error: e, refreshToken: refresh_token, timestamp: new Date().toISOString(), }); // More specific error handling if (e instanceof jsonwebtoken_1.TokenExpiredError) { return sendAuthErrorResponse(res, "Token has expired", 401, "TOKEN_EXPIRED"); } if (e instanceof jsonwebtoken_1.JsonWebTokenError) { return sendAuthErrorResponse(res, "Invalid token signature", 401, "INVALID_TOKEN_SIGNATURE"); } return sendAuthErrorResponse(res, "Unexpected authentication error", 401, "UNEXPECTED_AUTH_ERROR"); } } return sendAuthErrorResponse(res, "Invalid refresh token.", 401, "INVALID_REFRESH_TOKEN"); } else { // check active workspace if (!user.activeWorkspace) { const workspaces = user.workspaces; if (workspaces.length === 1) { user = await userSvc.updateOne({ _id: user._id }, { activeWorkspace: workspaces[0]._id }, { populate: ["roles", "workspaces", "activeWorkspace"] }); } } req.workspace = user.activeWorkspace; // role const { roles = [] } = user; const workspaceId = mongodb_1.MongoDB.toString(req.workspace._id); const activeRole = (0, lodash_1.isEmpty)(user.activeWorkspace) ? undefined : roles.find((role) => mongodb_1.MongoDB.toString(role.workspace) === workspaceId); if (activeRole && user.activeRole !== activeRole._id) { user = await userSvc.updateOne({ _id: user._id }, { activeRole: activeRole._id }, { populate: ["roles", "workspaces", "activeRole", "activeWorkspace"] }); } // Clean up empty workspace and role if ((0, lodash_1.isEmpty)(user.activeWorkspace)) delete user.activeWorkspace; if ((0, lodash_1.isEmpty)(user.activeRole)) delete user.activeRole; req.role = user.activeRole = activeRole; // user req.user = user; res.locals.user = user; // try to assign tokens to cookies (test) try { const { access_token: accessToken, refresh_token: refreshToken } = user.token || {}; if (accessToken && refreshToken) { res.cookie("x-auth-cookie", accessToken); res.cookie("refresh_token", refreshToken); res.header("Authorization", `Bearer ${accessToken}`); req.headers.authorization = `Bearer ${accessToken}`; req.query.access_token = accessToken; req.query.refresh_token = refreshToken; } } catch (e) { console.error(`[AUTH_JWT] Unable to assign tokens to cookies: ${e.stack}`); return sendAuthErrorResponse(res, "Failed to assign tokens", 401, "FAILED_TO_ASSIGN_TOKENS"); } next(); } } catch (globalError) { console.error("jwt_auth > Unexpected global error :>>", { error: globalError, timestamp: new Date().toISOString(), }); return sendAuthErrorResponse(res, "Unexpected error during authentication", 401, "UNEXPECTED_AUTH_ERROR"); } })(req, res, next); exports.default = jwt_auth;