tokenManager.js•3.73 kB
/**
* Token Manager utility
* Handles secure token storage, encryption, and refresh
*/
const crypto = require('crypto');
const jwt = require('jsonwebtoken');
const axios = require('axios');
const config = require('../config');
const facebookConfig = require('../config/facebook');
const logger = require('./logger');
// Encryption key and algorithm
const ENCRYPTION_KEY = config.JWT_SECRET; // Use JWT secret as encryption key
const ALGORITHM = 'aes-256-cbc';
/**
* Encrypt a token for secure storage
* @param {string} token - The token to encrypt
* @returns {string} - The encrypted token
*/
const encryptToken = async (token) => {
try {
// Create an initialization vector
const iv = crypto.randomBytes(16);
// Create cipher
const cipher = crypto.createCipheriv(ALGORITHM, Buffer.from(ENCRYPTION_KEY.padEnd(32).slice(0, 32)), iv);
// Encrypt the token
let encrypted = cipher.update(token);
encrypted = Buffer.concat([encrypted, cipher.final()]);
// Return iv + encrypted data as base64 string
return `${iv.toString('hex')}:${encrypted.toString('hex')}`;
} catch (error) {
logger.error(`Error encrypting token: ${error.message}`);
throw new Error('Token encryption failed');
}
};
/**
* Decrypt a stored token
* @param {string} encryptedToken - The encrypted token
* @returns {string} - The decrypted token
*/
const decryptToken = async (encryptedToken) => {
try {
// Split iv and encrypted data
const [ivHex, encryptedHex] = encryptedToken.split(':');
const iv = Buffer.from(ivHex, 'hex');
const encrypted = Buffer.from(encryptedHex, 'hex');
// Create decipher
const decipher = crypto.createDecipheriv(ALGORITHM, Buffer.from(ENCRYPTION_KEY.padEnd(32).slice(0, 32)), iv);
// Decrypt the token
let decrypted = decipher.update(encrypted);
decrypted = Buffer.concat([decrypted, decipher.final()]);
// Return decrypted token
return decrypted.toString();
} catch (error) {
logger.error(`Error decrypting token: ${error.message}`);
throw new Error('Token decryption failed');
}
};
/**
* Generate a JWT token for user authentication
* @param {Object} user - User object
* @returns {string} - JWT token
*/
const generateJWT = (user) => {
return jwt.sign(
{
id: user._id,
facebookId: user.facebookId,
name: user.name,
email: user.email
},
config.JWT_SECRET,
{ expiresIn: config.JWT_EXPIRY }
);
};
/**
* Verify a JWT token
* @param {string} token - JWT token
* @returns {Object} - Decoded token payload
*/
const verifyJWT = (token) => {
try {
return jwt.verify(token, config.JWT_SECRET);
} catch (error) {
logger.error(`JWT verification failed: ${error.message}`);
throw new Error('Invalid token');
}
};
/**
* Refresh a Facebook access token
* @param {string} refreshToken - Facebook refresh token
* @returns {Object} - New tokens { accessToken, refreshToken, expiresIn }
*/
const refreshFacebookToken = async (refreshToken) => {
try {
const response = await axios.get(`${facebookConfig.endpoints.base}/${facebookConfig.apiVersion}/oauth/access_token`, {
params: {
grant_type: 'fb_exchange_token',
client_id: facebookConfig.appId,
client_secret: facebookConfig.appSecret,
fb_exchange_token: refreshToken
}
});
return {
accessToken: response.data.access_token,
expiresIn: response.data.expires_in
};
} catch (error) {
logger.error(`Error refreshing Facebook token: ${error.message}`);
throw new Error('Failed to refresh Facebook token');
}
};
module.exports = {
encryptToken,
decryptToken,
generateJWT,
verifyJWT,
refreshFacebookToken
};