espace-paie-odentas/lib/odentas-sign/jwt.ts
odentas b790faf12c feat: Implémentation complète du système Odentas Sign
- Remplacement de DocuSeal par solution souveraine Odentas Sign
- Système d'authentification OTP pour signataires (bcryptjs + JWT)
- 8 routes API: send-otp, verify-otp, sign, pdf-url, positions, status, webhook, signers
- Interface moderne avec canvas de signature et animations (framer-motion, confetti)
- Système de templates pour auto-détection des positions de signature (CDDU, RG, avenants)
- PDF viewer avec @react-pdf-viewer (compatible Next.js)
- Stockage S3: source/, signatures/, evidence/, signed/, certs/
- Tables Supabase: sign_requests, signers, sign_positions, sign_events, sign_assets
- Evidence bundle automatique (JSON metadata + timestamps)
- Templates emails: OTP et completion
- Scripts Lambda prêts: pades-sign (KMS seal) et tsaStamp (RFC3161)
- Mode test détecté automatiquement (emails whitelist)
- Tests complets avec PDF CDDU réel (2 signataires)
2025-10-27 19:03:07 +01:00

50 lines
1.3 KiB
TypeScript

import jwt from 'jsonwebtoken';
import type { SignatureSessionToken } from './types';
const JWT_SECRET = process.env.JWT_SECRET || process.env.NEXTAUTH_SECRET || 'odentas-sign-secret-key-change-in-production';
const JWT_EXPIRATION = '30m'; // 30 minutes
/**
* Crée un JWT pour une session de signature
*/
export function createSignatureSession(payload: {
signerId: string;
requestId: string;
email: string;
role: string;
}): string {
return jwt.sign(payload, JWT_SECRET, {
expiresIn: JWT_EXPIRATION,
issuer: 'odentas-sign',
audience: 'signature-session'
});
}
/**
* Vérifie et décode un JWT de session de signature
*/
export function verifySignatureSession(token: string): SignatureSessionToken | null {
try {
const decoded = jwt.verify(token, JWT_SECRET, {
issuer: 'odentas-sign',
audience: 'signature-session'
}) as SignatureSessionToken;
return decoded;
} catch (error) {
console.error('[JWT] Erreur de vérification:', error);
return null;
}
}
/**
* Extrait le token JWT depuis le header Authorization
*/
export function extractTokenFromHeader(authHeader: string | null): string | null {
if (!authHeader) return null;
const parts = authHeader.split(' ');
if (parts.length !== 2 || parts[0] !== 'Bearer') return null;
return parts[1];
}