@topgroup/diginext
Version:
A BUILD SERVER & CLI to deploy apps to any Kubernetes clusters.
177 lines (176 loc) • 8.88 kB
JavaScript
;
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;