- 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)
50 lines
1.3 KiB
TypeScript
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];
|
|
}
|