mirror of
https://github.com/rgrgogu/new_starr.git
synced 2026-09-27 00:12:54 +08:00
chore: relocate backend into apps/api ahead of monorepo merge
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
/***********************************************************************************************************************************************************************
|
||||
* File Name: token.util.js
|
||||
* Type of Program: Utility
|
||||
* Description: JWT access & refresh token helpers.
|
||||
* - generateTokens() → produces { accessToken, refreshToken }
|
||||
* - verifyAccessToken() → validates and returns decoded payload
|
||||
* - verifyRefreshToken() → validates the long-lived refresh token
|
||||
* - hashToken() → SHA-256 hash used to store refresh tokens in DB
|
||||
* Author: rgrgogu
|
||||
* Date Created: Oct. 6, 2025
|
||||
***********************************************************************************************************************************************************************
|
||||
* HOW TO USE:
|
||||
* const { generateTokens, verifyAccessToken } = require('../utils/token.util');
|
||||
* const { accessToken, refreshToken } = generateTokens(user);
|
||||
***********************************************************************************************************************************************************************/
|
||||
const jwt = require('jsonwebtoken');
|
||||
const crypto = require('crypto');
|
||||
|
||||
/**
|
||||
* Generates a signed access token and a signed refresh token.
|
||||
* @param {object} user - Sequelize User instance
|
||||
* @returns {{ accessToken: string, refreshToken: string }}
|
||||
*/
|
||||
const generateTokens = (user) => {
|
||||
const payload = {
|
||||
user_id: user.user_id,
|
||||
email: user.email,
|
||||
acc_type: user.acc_type,
|
||||
reg_type: user.reg_type,
|
||||
};
|
||||
|
||||
const accessToken = jwt.sign(payload, process.env.JWT_SECRET, {
|
||||
expiresIn: process.env.JWT_EXPIRES_IN || '1d',
|
||||
});
|
||||
|
||||
const refreshToken = jwt.sign(
|
||||
{ user_id: user.user_id },
|
||||
process.env.JWT_REFRESH_SECRET,
|
||||
{ expiresIn: process.env.JWT_REFRESH_EXPIRES_IN || '7d' }
|
||||
);
|
||||
|
||||
return { accessToken, refreshToken };
|
||||
};
|
||||
|
||||
/**
|
||||
* Verifies an access token.
|
||||
* @param {string} token
|
||||
* @returns {object} decoded payload
|
||||
* @throws if invalid / expired
|
||||
*/
|
||||
const verifyAccessToken = (token) =>
|
||||
jwt.verify(token, process.env.JWT_SECRET);
|
||||
|
||||
/**
|
||||
* Verifies a refresh token.
|
||||
* @param {string} token
|
||||
* @returns {object} decoded payload
|
||||
*/
|
||||
const verifyRefreshToken = (token) =>
|
||||
jwt.verify(token, process.env.JWT_REFRESH_SECRET);
|
||||
|
||||
/**
|
||||
* SHA-256 hash a token string for safe DB storage.
|
||||
* @param {string} token
|
||||
* @returns {string} hex digest
|
||||
*/
|
||||
const hashToken = (token) =>
|
||||
crypto.createHash('sha256').update(token).digest('hex');
|
||||
|
||||
/**
|
||||
* SHA-256 hash a token string for safe DB storage.
|
||||
* @param {string} decoded
|
||||
* @param {number} thresholdDays
|
||||
* @returns {string} if expired or not
|
||||
*/
|
||||
const shouldRotateRefreshToken = (decoded, thresholdDays = 1) => {
|
||||
const now = Math.floor(Date.now() / 1000);
|
||||
const timeLeft = decoded.exp - now;
|
||||
const threshold = thresholdDays * 24 * 60 * 60;
|
||||
return timeLeft <= threshold;
|
||||
};
|
||||
|
||||
module.exports = { generateTokens, verifyAccessToken, verifyRefreshToken, hashToken, shouldRotateRefreshToken };
|
||||
Reference in New Issue
Block a user