Files
ackify/docs/fr/architecture.md
Benjamin 68426bc882 feat: add PKCE support to OAuth2 flow for enhanced security
- Implement PKCE (Proof Key for Code Exchange) with S256 method
- Add crypto/pkce module with code verifier and challenge generation
- Modify OAuth flow to include code_challenge in authorization requests
- Update HandleCallback to validate code_verifier during token exchange
- Extend session lifetime from 7 to 30 days
- Add comprehensive unit tests for PKCE functions
- Maintain backward compatibility with fallback for non-PKCE sessions
- Add detailed logging for OAuth flow with PKCE tracking

PKCE enhances security by preventing authorization code interception
attacks, as recommended by OAuth 2.1 and OIDC standards.

feat: add encrypted refresh token storage with automatic cleanup

- Add oauth_sessions table for storing encrypted refresh tokens
- Implement AES-256-GCM encryption for refresh tokens using cookie secret
- Create OAuth session repository with full CRUD operations
- Add SessionWorker for automatic cleanup of expired sessions
- Configure cleanup to run every 24h for sessions older than 37 days
- Modify OAuth flow to store refresh tokens after successful authentication
- Track client IP and user agent for session security validation
- Link OAuth sessions to user sessions via session ID
- Add comprehensive encryption tests with security validations
- Integrate SessionWorker into server lifecycle with graceful shutdown

This enables persistent OAuth sessions with secure token storage,
reducing the need for frequent re-authentication from 7 to 30 days.
2025-10-26 02:32:10 +02:00

9.6 KiB

Architecture

Stack technique et principes de conception d'Ackify.

Vue d'Ensemble

Ackify est une application monolithique moderne avec séparation claire backend/frontend.

┌─────────────────────────────────────────┐
│           Client Browser                │
│  (Vue.js 3 SPA + TypeScript)            │
└──────────────┬──────────────────────────┘
               │ HTTPS / JSON
┌──────────────▼──────────────────────────┐
│         Go Backend (API-first)          │
│  ├─ RESTful API v1 (chi router)         │
│  ├─ OAuth2 Service                      │
│  ├─ Ed25519 Crypto                      │
│  └─ SMTP Email (optionnel)              │
└──────────────┬──────────────────────────┘
               │ PostgreSQL protocol
┌──────────────▼──────────────────────────┐
│       PostgreSQL 16 Database            │
│  (Signatures + Metadata + Sessions)     │
└─────────────────────────────────────────┘

Backend (Go)

Clean Architecture Simplifiée

backend/
├── cmd/
│   ├── community/        # Point d'entrée + injection dépendances
│   └── migrate/          # Outil migrations SQL
├── internal/
│   ├── domain/
│   │   └── models/       # Entités métier (User, Signature, Document)
│   ├── application/
│   │   └── services/     # Logique métier (SignatureService, etc.)
│   ├── infrastructure/
│   │   ├── auth/         # OAuth2 service
│   │   ├── database/     # Repositories PostgreSQL
│   │   ├── email/        # SMTP service
│   │   ├── config/       # Variables d'environnement
│   │   └── i18n/         # Backend i18n
│   └── presentation/
│       ├── api/          # HTTP handlers API v1
│       └── handlers/     # Legacy OAuth handlers
├── pkg/
│   ├── crypto/           # Ed25519 signatures
│   ├── logger/           # Structured logging
│   ├── services/         # OAuth provider detection
│   └── web/              # HTTP server setup
├── migrations/           # SQL migrations
├── templates/            # Email templates (HTML/text)
└── locales/              # Backend translations

Principes Go Appliqués

Interfaces :

  • Définies dans le package qui les utilise
  • Principe "accept interfaces, return structs"
  • Repositories implémentés dans infrastructure/database/

Injection de Dépendances :

  • Constructeurs explicites dans main.go
  • Pas de container DI complexe
  • Dépendances claires et visibles

Code Quality :

  • go fmt et go vet clean
  • Pas de code mort
  • Interfaces simples et focalisées

Frontend (Vue.js 3)

Structure SPA

webapp/
├── src/
│   ├── components/       # Composants réutilisables
│   │   ├── ui/          # shadcn/vue components
│   │   └── ...
│   ├── pages/           # Pages (router views)
│   │   ├── Home.vue
│   │   ├── Admin.vue
│   │   └── ...
│   ├── services/        # API client (axios)
│   ├── stores/          # Pinia state management
│   ├── router/          # Vue Router config
│   ├── locales/         # Traductions (fr, en, es, de, it)
│   └── composables/     # Vue composables
├── public/              # Assets statiques
└── scripts/             # Build scripts

Stack Frontend

  • Vue 3 - Composition API
  • TypeScript - Type safety
  • Vite - Build tool (HMR rapide)
  • Pinia - State management
  • Vue Router - Client routing
  • Tailwind CSS - Utility-first styling
  • shadcn/vue - UI components
  • vue-i18n - Internationalisation

Routing

const routes = [
  { path: '/', component: Home },               // Public
  { path: '/signatures', component: MySignatures }, // Auth required
  { path: '/admin', component: Admin }          // Admin only
]

Le frontend gère :

  • Route / avec query param ?doc=xxx → Page de signature
  • Route /admin → Dashboard admin
  • Route /signatures → Mes signatures

Base de Données

Schéma PostgreSQL

Tables principales :

  • signatures - Signatures Ed25519
  • documents - Métadonnées documents
  • expected_signers - Tracking signataires
  • reminder_logs - Historique emails
  • checksum_verifications - Vérifications intégrité
  • oauth_sessions - Sessions OAuth2 + refresh tokens

Voir Database pour le schéma complet.

Migrations

  • Format : XXXX_description.up.sql / XXXX_description.down.sql
  • Appliquées automatiquement au démarrage (service ackify-migrate)
  • Outil : /backend/cmd/migrate

Sécurité

Cryptographie

Ed25519 :

  • Signatures digitales (courbe elliptique)
  • Clé privée 256 bits
  • Non-répudiation garantie

SHA-256 :

  • Hachage payload avant signature
  • Détection de tampering
  • Chaînage blockchain-like (prev_hash)

AES-256-GCM :

  • Chiffrement refresh tokens OAuth2
  • Clé dérivée de ACKIFY_OAUTH_COOKIE_SECRET

OAuth2 + PKCE

Flow :

  1. Client génère code_verifier (random)
  2. Calcule code_challenge = SHA256(code_verifier)
  3. Auth request avec code_challenge
  4. Provider retourne code
  5. Token exchange avec code + code_verifier

Sécurité :

  • Protection contre interception du code
  • Méthode S256 (SHA-256)
  • Activé automatiquement

Sessions

  • Cookies sécurisés (HttpOnly, Secure, SameSite=Lax)
  • Chiffrement HMAC-SHA256
  • Stockage PostgreSQL avec refresh tokens chiffrés
  • Durée : 30 jours
  • Cleanup automatique : 37 jours

Build & Déploiement

Multi-Stage Docker

# Stage 1 - Frontend build
FROM node:22-alpine AS frontend
COPY webapp/ /build/webapp/
RUN npm ci && npm run build
# Output: webapp/dist/

# Stage 2 - Backend build + embed frontend
FROM golang:alpine AS backend
ENV GOTOOLCHAIN=auto
COPY backend/ /build/backend/
COPY --from=frontend /build/webapp/dist/ /build/backend/cmd/community/web/dist/
RUN go build -o community ./cmd/community
# Frontend embedded via embed.FS

# Stage 3 - Runtime (distroless)
FROM gcr.io/distroless/static-debian12:nonroot
COPY --from=backend /build/backend/community /app/community
CMD ["/app/community"]

Résultat :

  • Image finale < 30 MB
  • Binaire unique (backend + frontend)
  • Aucune dépendance runtime

Injection Runtime

Le ACKIFY_BASE_URL est injecté dans index.html au démarrage :

// Remplace __ACKIFY_BASE_URL__ par la valeur réelle
html = strings.ReplaceAll(html, "__ACKIFY_BASE_URL__", baseURL)

Permet de changer le domaine sans rebuild.

Performance

Backend

  • Connection pooling PostgreSQL (25 max)
  • Prepared statements - Anti-injection SQL
  • Rate limiting - 5 auth/min, 10 doc/min, 100 req/min
  • Structured logging - JSON avec request IDs

Frontend

  • Code splitting - Lazy loading routes
  • Tree shaking - Dead code elimination
  • Minification - Production builds optimisés
  • HMR - Hot Module Replacement (dev)

Database

  • Index sur (doc_id, user_sub, session_id)
  • Constraints UNIQUE pour garanties
  • Triggers pour immutabilité
  • Autovacuum activé

Scalabilité

Limites Actuelles

  • Monolithe : ~10k req/s
  • PostgreSQL : Single instance
  • Sessions : In-database (pas de Redis)

Scaling Horizontal (futur)

Pour > 100k req/s :

  1. Load Balancer - Multiple instances backend
  2. PostgreSQL read replicas - Séparation read/write
  3. Redis - Cache sessions + rate limiting
  4. CDN - Assets statiques

Monitoring

Logs Structurés

Format JSON :

{
  "level": "info",
  "timestamp": "2025-01-15T14:30:00Z",
  "request_id": "abc123",
  "method": "POST",
  "path": "/api/v1/signatures",
  "duration_ms": 42,
  "status": 201
}

Health Check

GET /api/v1/health

Response :

{
  "status": "healthy",
  "database": "connected"
}

Métriques (futur)

  • Prometheus metrics endpoint
  • Grafana dashboards
  • Alerting (PagerDuty, Slack)

Tests

Coverage

72.6% code coverage (unit + integration)

  • Unit tests : 180+ tests
  • Integration tests : 33 tests PostgreSQL
  • CI/CD : GitHub Actions + Codecov

Voir Development pour lancer les tests.

Choix Techniques

Pourquoi Go ?

  • Performance native (compiled)
  • Concurrency simple (goroutines)
  • Typage fort
  • Binaire unique
  • Déploiement simple

Pourquoi Vue 3 ?

  • Composition API moderne
  • TypeScript natif
  • Reactive par défaut
  • Ecosystème riche
  • Performances excellentes

Pourquoi PostgreSQL ?

  • ACID compliance
  • Contraintes d'intégrité
  • Triggers
  • JSON support
  • Mature et stable

Pourquoi Ed25519 ?

  • Sécurité moderne (courbe elliptique)
  • Performance > RSA
  • Signatures courtes (64 bytes)
  • Standard crypto/ed25519 Go

Références