Refactor auth routes: explicit dependency injection
- Updated all auth route modules to use destructured dependencies - Added JSDoc comments for factory functions - Replaced ctx. references with direct parameter access - Updated auth/index.js to extract and pass explicit dependencies - sso-gate.js maintains session helper exports from session-handlers - All files pass syntax validation Files refactored: - routes/auth/keys.js - routes/auth/session-handlers.js - routes/auth/sso-gate.js - routes/auth/totp.js - routes/auth/index.js (orchestrator)
This commit is contained in:
@@ -2,11 +2,20 @@ const express = require('express');
|
||||
const { renewCSRFToken } = require('../../csrf-protection');
|
||||
const { ValidationError, AuthenticationError } = require('../../errors');
|
||||
|
||||
module.exports = function(ctx) {
|
||||
module.exports = function({ authManager, asyncHandler, errorResponse, log }) {
|
||||
const router = express.Router();
|
||||
/**
|
||||
* Auth TOTP routes factory
|
||||
* @param {Object} deps - Explicit dependencies
|
||||
* @param {Object} deps.authManager - Auth manager
|
||||
* @param {Function} deps.asyncHandler - Async route handler wrapper
|
||||
* @param {Function} deps.errorResponse - Error response helper
|
||||
* @param {Object} deps.log - Logger instance
|
||||
* @returns {express.Router}
|
||||
*/
|
||||
|
||||
// Get current TOTP config (public route)
|
||||
router.get('/totp/config', ctx.asyncHandler(async (req, res) => {
|
||||
router.get('/totp/config', asyncHandler(async (req, res) => {
|
||||
res.json({
|
||||
success: true,
|
||||
config: {
|
||||
@@ -18,7 +27,7 @@ module.exports = function(ctx) {
|
||||
}, 'totp-config-get'));
|
||||
|
||||
// Generate new TOTP secret + QR code
|
||||
router.post('/totp/setup', ctx.asyncHandler(async (req, res) => {
|
||||
router.post('/totp/setup', asyncHandler(async (req, res) => {
|
||||
const { authenticator } = require('otplib');
|
||||
const QRCode = require('qrcode');
|
||||
|
||||
@@ -46,7 +55,7 @@ module.exports = function(ctx) {
|
||||
}, 'totp-setup'));
|
||||
|
||||
// Verify first code to confirm setup, then activate TOTP
|
||||
router.post('/totp/verify-setup', ctx.asyncHandler(async (req, res) => {
|
||||
router.post('/totp/verify-setup', asyncHandler(async (req, res) => {
|
||||
const { authenticator } = require('otplib');
|
||||
const { code } = req.body;
|
||||
|
||||
@@ -83,7 +92,7 @@ module.exports = function(ctx) {
|
||||
}, 'totp-verify-setup'));
|
||||
|
||||
// Login: verify TOTP code and set session cookie
|
||||
router.post('/totp/verify', ctx.asyncHandler(async (req, res) => {
|
||||
router.post('/totp/verify', asyncHandler(async (req, res) => {
|
||||
const { authenticator } = require('otplib');
|
||||
const { code } = req.body;
|
||||
|
||||
@@ -105,19 +114,19 @@ module.exports = function(ctx) {
|
||||
throw new AuthenticationError('[DC-111] Invalid code');
|
||||
}
|
||||
|
||||
ctx.log.info('auth', 'TOTP verified, creating session', { ip: ctx.session.getClientIP(req), duration: ctx.totpConfig.sessionDuration });
|
||||
log.info('auth', 'TOTP verified, creating session', { ip: ctx.session.getClientIP(req), duration: ctx.totpConfig.sessionDuration });
|
||||
ctx.session.create(req, ctx.totpConfig.sessionDuration);
|
||||
ctx.session.setCookie(res, ctx.totpConfig.sessionDuration);
|
||||
|
||||
// Rotate CSRF token for the new session
|
||||
const newCsrfToken = renewCSRFToken(res, req.secure || req.protocol === 'https');
|
||||
|
||||
ctx.log.debug('auth', 'Session created', { sessions: ctx.session.ipSessions.size });
|
||||
log.debug('auth', 'Session created', { sessions: ctx.session.ipSessions.size });
|
||||
res.json({ success: true, message: 'Authenticated successfully', sessionDuration: ctx.totpConfig.sessionDuration, csrfToken: newCsrfToken });
|
||||
}, 'totp-verify'));
|
||||
|
||||
// Check session validity (used by Caddy forward_auth)
|
||||
router.get('/totp/check-session', ctx.asyncHandler(async (req, res) => {
|
||||
router.get('/totp/check-session', asyncHandler(async (req, res) => {
|
||||
// Never cache session checks — stale cached 200s cause auth loops
|
||||
res.setHeader('Cache-Control', 'no-store, no-cache, must-revalidate');
|
||||
res.setHeader('Pragma', 'no-cache');
|
||||
@@ -127,7 +136,7 @@ module.exports = function(ctx) {
|
||||
}
|
||||
|
||||
const valid = ctx.session.isValid(req);
|
||||
ctx.log.debug('auth', 'Session check', { ip: ctx.session.getClientIP(req), valid, sessions: ctx.session.ipSessions.size });
|
||||
log.debug('auth', 'Session check', { ip: ctx.session.getClientIP(req), valid, sessions: ctx.session.ipSessions.size });
|
||||
if (valid) {
|
||||
return res.status(200).json({ authenticated: true });
|
||||
}
|
||||
@@ -136,7 +145,7 @@ module.exports = function(ctx) {
|
||||
}, 'totp-check-session'));
|
||||
|
||||
// Disable TOTP
|
||||
router.post('/totp/disable', ctx.asyncHandler(async (req, res) => {
|
||||
router.post('/totp/disable', asyncHandler(async (req, res) => {
|
||||
const { code } = req.body;
|
||||
|
||||
// Always require a valid TOTP code when TOTP is active
|
||||
@@ -169,7 +178,7 @@ module.exports = function(ctx) {
|
||||
}, 'totp-disable'));
|
||||
|
||||
// Update TOTP settings (session duration)
|
||||
router.post('/totp/config', ctx.asyncHandler(async (req, res) => {
|
||||
router.post('/totp/config', asyncHandler(async (req, res) => {
|
||||
const { sessionDuration } = req.body;
|
||||
|
||||
if (sessionDuration && !ctx.session.durations.hasOwnProperty(sessionDuration)) {
|
||||
|
||||
Reference in New Issue
Block a user