59 lines
2.0 KiB
JavaScript
59 lines
2.0 KiB
JavaScript
/**
|
|
* Temporary 30-second auth for email render (Puppeteer).
|
|
* Isolated from auth.js to avoid circular dependency with utils.js -> auth.js -> keycloak.js -> database.js -> utils.js
|
|
*/
|
|
import config from '../../config.js';
|
|
import crypto from 'crypto';
|
|
import jwt from 'jsonwebtoken';
|
|
import NodeCache from 'node-cache';
|
|
import log4js from 'log4js';
|
|
|
|
const logger = log4js.getLogger('EmailRenderAuth');
|
|
logger.level = config.server?.logLevel || 'info';
|
|
|
|
const EMAIL_RENDER_TTL = 30;
|
|
const emailRenderAuthCache = new NodeCache({ stdTTL: EMAIL_RENDER_TTL });
|
|
|
|
/**
|
|
* Creates a temporary auth code for email render (Puppeteer) with 30-second TTL.
|
|
* The UI exchanges this code via getLoginToken to establish a brief session for rendering.
|
|
* @param {Object} userDoc - User document (must have username, email, _id, etc.)
|
|
* @returns {string} authCode to pass in URL query params
|
|
*/
|
|
export const createEmailRenderAuthCode = (userDoc) => {
|
|
const authCode = crypto.randomBytes(32).toString('hex');
|
|
const expiresAt = Date.now() + EMAIL_RENDER_TTL * 1000;
|
|
const accessToken = jwt.sign(
|
|
{ preferred_username: userDoc.username },
|
|
config.auth.sessionSecret,
|
|
{ expiresIn: EMAIL_RENDER_TTL }
|
|
);
|
|
const tokenData = {
|
|
access_token: accessToken,
|
|
expires_at: expiresAt,
|
|
_id: userDoc._id,
|
|
username: userDoc.username,
|
|
email: userDoc.email,
|
|
name: userDoc.name,
|
|
firstName: userDoc.firstName,
|
|
lastName: userDoc.lastName,
|
|
};
|
|
emailRenderAuthCache.set(authCode, tokenData);
|
|
logger.debug(`Created email render auth code (TTL ${EMAIL_RENDER_TTL}s) for user ${userDoc.username}`);
|
|
return authCode;
|
|
};
|
|
|
|
/**
|
|
* Exchanges an email render auth code for token data. Consumes the code (one-time use).
|
|
* @param {string} code - The auth code from URL query
|
|
* @returns {Object|null} Token data or null if invalid/expired
|
|
*/
|
|
export const getAndConsumeEmailRenderTokenData = (code) => {
|
|
const data = emailRenderAuthCache.get(code);
|
|
if (data) {
|
|
emailRenderAuthCache.del(code);
|
|
return data;
|
|
}
|
|
return null;
|
|
};
|