UNPKG

@replyke/express

Version:

Replyke: Build interactive apps with social features like comments, votes, feeds, user lists, notifications, and more.

101 lines (100 loc) 4.06 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const jsonwebtoken_1 = __importDefault(require("jsonwebtoken")); const models_1 = require("../../../models"); const models_2 = require("../../../models"); const reduceAuthenticatedUserDetails_1 = __importDefault(require("../../../helpers/reduceAuthenticatedUserDetails")); const config_1 = require("../../../config"); exports.default = async (req, res) => { const { refreshToken } = req.body; const projectId = req.project.id; const cookies = req.cookies; const { refreshTokenSecret } = (0, config_1.getCoreConfig)(); const refreshTokenJWT = cookies?.["replyke-refresh-jwt"] || refreshToken; if (!refreshTokenJWT) { res.status(200).json({ user: null, accessToken: null, }); return; } try { // Decode and verify the refresh token JWT const decoded = jsonwebtoken_1.default.verify(refreshTokenJWT, refreshTokenSecret); const { sub: userId, jti, projectId: decodedProjectId } = decoded; // Invalid token if (!userId || !jti || decodedProjectId !== projectId) { res.status(403).json({ error: "Invalid refresh token.", code: "auth/invalid-refresh-token", }); return; } // Find the refresh token in the Token table using the `jti` const storedToken = (await models_2.Token.findOne({ where: { id: jti, userId, projectId }, })); // Token not found or mismatch if (!storedToken || storedToken.refreshToken !== refreshTokenJWT) { res.status(403).json({ error: "Refresh token not recognized.", code: "auth/refresh-token-mismatch", }); return; } // get the target model for that alias: const SuspensionModel = models_1.User.associations.suspensions .target; const ActiveSuspensionModel = SuspensionModel.scope({ method: ["active", new Date()], }); // Find user by ID const userWithSuspensions = (await models_1.User.findByPk(userId, { include: [ { model: ActiveSuspensionModel, as: "suspensions", required: false, }, ], })); if (!userWithSuspensions) { res.status(403).json({ error: "User not found.", code: "auth/no-user-found", }); return; } // Generate a new access token const accessTokenJWT = jsonwebtoken_1.default.sign({ sub: userWithSuspensions.id, // Subject, representing the user ID projectId, // Project ID, indicating which project this token is tied to role: "user", // User role aud: "replyke.com", // Audience iss: "replyke.com", // Issuer }, process.env.ACCESS_TOKEN_SECRET, { expiresIn: "30m" } // Access token expires in 30 minutes ); const reducedAuthenticatedUser = (0, reduceAuthenticatedUserDetails_1.default)(userWithSuspensions); // Send the new access token to the client res.status(200).json({ success: true, accessToken: accessTokenJWT, user: reducedAuthenticatedUser, }); userWithSuspensions.lastActive = new Date(); userWithSuspensions.save(); const { handlers } = (0, config_1.getCoreConfig)(); await handlers.requestNewAccessToken({ projectId, userId }); } catch (err) { console.error("Error verifying refresh token:", err); res.status(403).json({ error: "Invalid or expired refresh token.", code: "auth/refresh-token-invalid", details: err.message, }); } };