import { Request, Response } from 'express'; import { asyncHandler } from '../middleware/error-handler'; import { StateService } from '../services/state.service'; import { IdNotController } from '../controllers/idnot.controller'; import { ExternalServiceError, ValidationError } from '../types/errors'; export class IdNotCallbackHandlers { static callback = asyncHandler(async (req: Request, res: Response): Promise => { const code = req.query.code as string | undefined; const state = req.query.state as string | undefined; // Debug logging to inspect what reaches the backend via Nginx // Note: keep logs concise to avoid leaking sensitive data in production try { // Only log presence/length of params to avoid full values in logs const safeQuery = { code_present: typeof code === 'string', code_length: typeof code === 'string' ? code.length : undefined, state_present: typeof state === 'string', state_length: typeof state === 'string' ? state.length : undefined }; console.info('[IdNotCallback] incoming request', { originalUrl: req.originalUrl, method: req.method, query: safeQuery, headers: { host: req.headers.host, 'x-forwarded-for': req.headers['x-forwarded-for'], 'x-forwarded-proto': req.headers['x-forwarded-proto'] } }); } catch {} if (!code || !state) { throw new ValidationError('Missing code or state', [ { field: 'code', value: code, constraints: ['required'] }, { field: 'state', value: state, constraints: ['required'] } ]); } const payload = StateService.verifyState(state); // Mock désactivé: suppression du bypass IDNOT_MOCK // Exchange code using existing controller logic to build auth and user const { authToken } = await IdNotController.authenticate(code); const url = new URL(payload.next_url); // Normalisation du chemin pour dev4: forcer le préfixe /lecoffre si absent try { if (url.hostname === 'dev4.4nkweb.com' && url.pathname === '/authorized-client') { url.pathname = '/lecoffre/authorized-client'; } } catch {} // Prefer fragment to avoid leaking in server logs const hash = url.hash ? url.hash.replace(/^#/, '') + `&authToken=${encodeURIComponent(authToken)}` : `authToken=${encodeURIComponent(authToken)}`; const redirectTo = `${url.origin}${url.pathname}${url.search}#${hash}`; res.redirect(302, redirectTo); }); }