espace-paie-odentas/SIGNATURE_VERIFICATION_SYSTEM.md
odentas d5a110484b feat: Système de vérification de signature électronique avec QR code
- Page publique /verify/[id] affichant Odentas Seal, TSA, certificat
- API /api/signatures/create-verification pour créer preuves
- Générateur PDF de preuve avec QR code (jsPDF)
- Hook useSignatureProof() pour intégration facile
- Table Supabase signature_verifications avec RLS public
- Page de test /test-signature-verification
- Documentation complète du système

Les signataires peuvent scanner le QR code ou visiter l'URL pour vérifier l'authenticité et l'intégrité de leur document signé.
2025-10-29 09:22:01 +01:00

8.2 KiB

Système de Vérification de Signature Électronique

Vue d'ensemble

Ce système permet aux signataires de vérifier l'authenticité et l'intégrité de leurs documents signés électroniquement via une page web publique accessible par URL ou QR code.

Architecture

1. Page de Vérification Publique

Fichier: app/verify/[id]/page.tsx

  • Route dynamique: https://espace-paie.odentas.com/verify/{uuid}
  • Accessible sans authentification (RLS public en lecture)
  • Affiche tous les détails techniques de la signature

2. Table Supabase

Fichier: supabase/migrations/20251028_signature_verifications.sql

signature_verifications
├── id (UUID)  Identifiant unique de vérification
├── document_name  Nom du document signé
├── pdf_url  URL du PDF signé
├── signed_at  Date/heure de signature
├── signer_name  Nom du signataire
├── signer_email  Email du signataire
├── signature_hash  Hash SHA-256 du contenu signé
├── signature_hex  Signature complète en hexadécimal
├── certificate_info (JSONB)  Infos du certificat
├── timestamp (JSONB)  Horodatage TSA
├── verification_status (JSONB)  Statuts de validation
├── contract_id  Lien vers le contrat
└── organization_id  Lien vers l'organisation

3. API de Création

Fichier: app/api/signatures/create-verification/route.ts

POST /api/signatures/create-verification
Body: {
  document_name: string,
  pdf_url: string,
  signer_name: string,
  signer_email: string,
  signature_hash: string,
  organization_id: string,
  // Optionnel:
  signature_hex?: string,
  certificate_info?: object,
  timestamp?: object,
  contract_id?: string
}

Returns: {
  verification_id: string,
  verification_url: string,
  qr_code_data_url: string (PNG en base64)
}

4. Générateur de PDF de Preuve

Fichier: lib/signature-proof-pdf.ts

Génère un PDF A4 professionnel contenant:

  • En-tête Odentas Sign
  • Informations du document signé
  • QR code (70x70mm, centré)
  • URL de vérification
  • Détails techniques (hash, algorithme, certificat)
  • Note explicative sur le certificat auto-signé

5. Hook React

Fichier: hooks/useSignatureProof.ts

const { createSignatureProof, isCreating } = useSignatureProof();

const proof = await createSignatureProof({
  document_name: "Contrat CDDU",
  pdf_url: "https://...",
  signer_name: "Jean Dupont",
  signer_email: "jean@example.com",
  signature_hash: "dafe9a5e...",
  organization_id: "uuid"
});

// Retourne:
// - verification_url
// - qr_code_data_url
// - proof_pdf_blob

Workflow d'Utilisation

Lors de la Signature d'un Document

  1. Le document est signé avec Odentas Sign (Lambda PAdES)
  2. Extraction des données :
    • Hash SHA-256 du contenu signé
    • Certificat de signature
    • Horodatage TSA (si présent)
  3. Appel API /api/signatures/create-verification
  4. Génération :
    • Entrée dans signature_verifications
    • QR code pointant vers /verify/{id}
    • PDF de preuve avec QR code
  5. Téléchargement :
    • Document signé (PDF avec signature PAdES)
    • Preuve de signature (PDF avec QR code)

Vérification par le Signataire

  1. Scanner le QR code ou visiter l'URL
  2. Page publique affiche :
    • Statut global (Valide / Techniquement Valide)
    • 📄 Informations du document
    • 🛡️ Odentas Seal (sceau électronique)
      • Format PAdES-BASELINE-B
      • Intégrité vérifiée (hash SHA-256)
      • Algorithme RSASSA-PSS
      • Détails du certificat
    • 🕐 Odentas TSA (horodatage)
      • RFC 3161 conforme
      • Autorité de temps
      • Empreinte horodatée
    • 🔍 Vérification technique
      • Structure PAdES valide
      • ByteRange correct
      • signing-certificate-v2 présent
      • MessageDigest intact
      • Statut du certificat (auto-signé ou qualifié)

Éléments Affichés

Odentas Seal

  • Format : PAdES-BASELINE-B (ETSI TS 102 778)
  • Intégrité : Hash SHA-256 du document
  • Algorithme : RSASSA-PSS avec SHA-256
  • Certificat :
    • Émetteur
    • Sujet
    • Période de validité
    • Numéro de série

Odentas TSA (si présent)

  • Standard : RFC 3161
  • Autorité : URL du TSA
  • Timestamp : Date/heure certifiée
  • Empreinte : Hash horodaté

Vérification Technique

  • Structure PAdES valide
  • ByteRange correct et complet
  • Attribut signing-certificate-v2 présent
  • MessageDigest intact
  • ⚠️ Certificat auto-signé (ou si qualifié)

Statuts de Validation

"Signature Valide"

  • Certificat qualifié reconnu par les autorités européennes
  • Tous les contrôles techniques passent
  • Valeur légale : QES (Qualified Electronic Signature)

"Signature Techniquement Valide" ⚠️

  • Certificat auto-signé (Odentas Media SAS)
  • Tous les contrôles techniques passent
  • Valeur légale : SES (Simple Electronic Signature)
  • Note explicative affichée

Sécurité

Row Level Security (RLS)

-- Lecture publique (vérification accessible à tous)
CREATE POLICY "Vérifications publiques" ON signature_verifications
  FOR SELECT USING (true);

-- Seul le système peut créer/modifier
CREATE POLICY "Système peut gérer" ON signature_verifications
  FOR ALL USING (auth.uid() IS NOT NULL);

Données Publiques

Les informations exposées sont volontairement publiques :

  • Nom du signataire
  • Email du signataire
  • Nom du document
  • Hash SHA-256
  • Certificat de signature

Aucune donnée sensible (contenu du document, IBAN, etc.) n'est stockée.

Intégration dans l'Application

Dans les Contrats CDDU/RG

Après signature via Docuseal + Odentas Sign :

import { useSignatureProof } from "@/hooks/useSignatureProof";

const { createSignatureProof } = useSignatureProof();

// Après réception du document signé
const proof = await createSignatureProof({
  document_name: `Contrat ${employee.prenom} ${employee.nom}`,
  pdf_url: signedPdfUrl,
  signer_name: `${employee.prenom} ${employee.nom}`,
  signer_email: employee.email,
  signature_hash: extractedHash,
  contract_id: contract.id,
  organization_id: contract.organization_id,
});

// Télécharger les deux fichiers:
// 1. Document signé (PDF PAdES)
// 2. Preuve de signature (PDF avec QR code)
downloadFile(signedPdfUrl, "contrat-signe.pdf");
downloadFile(URL.createObjectURL(proof.proof_pdf_blob), "preuve-signature.pdf");

Design

Page de Vérification

  • Layout : Gradient slate 50→100
  • Cards : Blanc avec shadow-xl et border-radius 16px
  • Statuts :
    • Vert (green-600) pour valide
    • ⚠️ Orange (orange-600) pour techniquement valide
    • Rouge (red-600) pour invalide
  • Icônes : Lucide React (CheckCircle2, Shield, Clock, FileText)

PDF de Preuve

  • Format : A4 portrait
  • En-tête : Indigo (Odentas branding)
  • QR Code : 70x70mm, centré, haute qualité
  • Sections :
    • Document signé (fond slate-100)
    • QR code avec URL
    • Détails techniques
    • Note importante (fond orange-50)

Variables d'Environnement

NEXT_PUBLIC_APP_URL=https://espace-paie.odentas.com

Utilisée pour générer les URLs de vérification.

Migration Supabase

# Appliquer la migration
supabase db push

# Ou manuellement
psql -h db.xxx.supabase.co -U postgres -d postgres -f supabase/migrations/20251028_signature_verifications.sql

Exemples d'URLs

https://espace-paie.odentas.com/verify/550e8400-e29b-41d4-a716-446655440000

TODO / Améliorations Futures

  • Support multi-signatures (plusieurs signataires)
  • Historique de vérifications (analytics)
  • Notifications email avec lien de vérification
  • API publique de vérification (pour intégrations tierces)
  • Support certificats qualifiés (badge "Qualifié eIDAS")
  • Archivage long terme (LTV avec DSS/LTA)
  • Export PDF/A pour archivage légal

Conformité

  • PAdES-BASELINE-B : ETSI TS 102 778
  • RFC 3161 : Horodatage électronique
  • RFC 5035 : signing-certificate-v2
  • RGPD : Données publiques consenties
  • ⚠️ eIDAS : SES (auto-signé) ou QES (avec certificat qualifié)

Odentas Media SAS - Signature électronique sécurisée