(Version v15‑v18 – à jour 2025)
1. Contexte rapide
| Élément | Description |
|---|---|
| Dolibarr ERP/CRM | Suite open‑sourcePHP/MySQL (ou MariaDB) de gestion d’entreprise : devis, factures, stocks, projets, etc. |
| SSO (Single Sign‑On) | Mécanisme d’authentification centralisée (ex. : OAuth2 / OpenID Connect, Kerberos, SAML…) qui permet à un utilisateur d’accéder à plusieurs applications avec un seul login. |
| Objectif performance | Réduire le temps de réponse des pages, limiter les appels redondants à la base de données, éviter les goulots d’étranglement liés à la validation d’identité à chaque requête. |
En bref : Dolibarr est souvent installé derrière un reverse‑proxy (NGINX/Apache) qui assure le SSO. La mauvaise configuration du flux d’authentification ou l’absence de mise en cache des tokens peut engendrer des latences importantes et même des pannes sous forte charge.
2. Architecture typique avec SSO
┌─────────────────────────────────┐
│ Client (navigateur) │
│ → login.example.com (OIDC) │
└─────────────┬───────────────────┘
│
▼
┌─────────────────────────────────┐
│ Reverse‑proxy (NGINX) │
│ - Terminaison TLS │
│ - Gestion du cookie de session │
│ - Forward‑auth (auth_request) │
└───────┬─────────────┬─────────────┘
│ │
▼ ▼
┌─────────────────────┐ ┌───────────────────────┐
│ Dolibarr (PHP‑FPM) │ │ Service d’auth (ex. │
│ (et ses plugins) │ │ Keycloak/Okta…) │
└─────────────────────┘ └───────────────────────┘
-
Flux : L’utilisateur est redirigé vers le Provider d’Identité (IdP). Après validation, l’IdP envoie un JWT (ou un cookie de session) au reverse‑proxy via le module
auth_request. Le proxy valide le token et le transmet à Dolibarr qui démarre la session sans toucher à la base de données tant que le token reste valide. - Points de friction :
- Validation du token à chaque requête → surcharge du CPU.
- Absence de cache du résultat de la validation → latence réseau.
- Taille du JWT ou des cookies → augmentation du header HTTP.
- Configuration d’
auth_requestmal dimensionnée (timeout, retries).
3. Erreurs fréquentes (et leurs impacts performance)
| # | Erreur | Manifestation | Impact performance |
|---|---|---|---|
| 1 | auth_request timeout trop court |
502/504 depuis NGINX → pages blanche ou « timeout » | temps de réponse > 2 s, perte de requêtes simultanées |
| 2 | Désactivation du cache de session (cookies PHP non partagés) | Chaque sous‑domaine lance une nouvelle validation d’IdP | Multiplication des appels à l’IdP → CPU/IO élevé |
| 3 | JWT trop gros ou signé avec algorithme lourd (RSA‑4096) | Temps de parsing et vérif. > 200 ms | Latence par requête, goulot d’étranglement sous load |
| 4 | Pas de répartition des tokens (pas de partage de sessions) | Session “perte” à chaque redirection → reconnexion à chaque appel | Re‑authentification à chaque clic → surcharge IdP |
| 5 | Mauvaise configuration du proxy_cache (pas de cache ou durée trop courte) |
Réponses dynamiques non mutualisées → recomputation à chaque accès | Augmentation de la charge PHP‑FPM jusqu’à saturation |
| 6 | Utilisation d’un seul serveur PHP‑FPM sur un serveur dédié | Saturation CPU lors de pics de login | Temps d’attente élevé, erreurs 504 |
| 7 | Pas de session‑affinity (sticky) au niveau du load‑balancer | Utilisateur redirigé aléatoirement → re‑authentification à chaque requête | Cycle de login répété → trafic d’authentification 2‑3× supérieur |
| 8 | Logs d’authentification en mode debug | Journalisation massive (MB) à chaque requête | I/O disque saturé, ralentissement du serveur web |
4. Solutions orientées performance
4.1 Optimisations du reverse‑proxy (NGINX)
| Action | Paramètre clé | Exemple de configuration |
|---|---|---|
| Timeout | proxy_read_timeout , auth_request_timeout |
proxy_read_timeout 5s; auth_request_timeout 3s; |
| Cache de validation | proxy_cache + proxy_cache_valid |
nginx\nproxy_cache_path /var/cache/nginx levels=1:2 keys_zone=auth_cache:100m max_size=2g inactive=60m use_temp_path=off;\nproxy_cache_key $scheme$request_method$proxy_gunicorn_upstream_addr$request_uri;\nauth_request /auth_valid;\nproxy_set_header X-Original-URI $request_uri;\n |
| Headers de taille | large_client_header_buffers |
large_client_header_buffers 4 16k; |
| Équilibrage | ip_hash (pour la session) ou least_conn |
upstream php_fpm { ip_hash; server 10.0.0.10:9000; } |
| Keep‑alive | keepalive_timeout |
keepalive_timeout 65; |
Bon à savoir : la validation du token doit être asynchrone (via
auth_request_async) pour éviter de bloquer le fil d’exécution du thread NGINX.
4.2 Choix du Provider d’Identité
| Provider | Algorithme recommandé | Taille du JWT | Particularité performance |
|---|---|---|---|
| Keycloak | HS256 (HMAC‑SHA256) avec clé symétrique HS256 | ≤ 1 KB | Vérif rapide, support native du auth_request via le module openid-connect. |
| Okta | RS256 (RSA‑2048) | 1‑2 KB | Bon pour environnements d’entreprise, mais nécessite plus de CPU pour RSA. |
| Azure AD | ES256 (ECDSA‑P256) | ~ 1 KB | Légère, mais dépend du réseau Azure. |
| Auth0 | HS256 (HMAC‑SHA256) | ≤ 1 KB | Idéal pour prototypage rapide, mais planification tarifaire peut imposer des limites de débit. |
Recommandation : privilégier HS256 ou ES256 (ECDSA) uniquement si le nombre de vérifications par seconde dépasse 10 000 req/s. Sinon, un JWT de 500 bytes signé avec HS256 reste le plus rapide.
4.3 Partage de session entre les sous‑domaines
- Cookie partagé
// dolibarr_secure cookie settings
ini_set('session.cookie_domain', '.exemple.com');
ini_set('session.cookie_secure', 1);
ini_set('session.use_sticky_sessions', 'mandatory'); - Redis ou Memcached comme backend de session
- Déployer un Redis cluster (3 nodes) avec réplication.
- Configurer
session.save_handler = redisdansphp.ini. - TTL raccourci (ex. 30 min) pour libérer rapidement les sessions expirées.
Gain : Même si le token SSO expire, la session PHP reste valide tant que le cookie n’est pas vidé, évitant une re‑authentification à chaque appel interne.
4.4 Optimisation du code PHP/Dolibarr
| Technique | Description | Impact |
|---|---|---|
| OPcache (PHP‑8+) | Activez opcache.enable=1 + opcache.memory_consumption=256 |
Réduction du temps de compilation des scripts de ~ 30 %. |
| Cache APCu | Mise en cache des requêtes SQL fréquentes (ex. listes de contacts) | Diminution des I/O DB d’environ 40 % sous pic de trafic. |
| Limitation des plugins lourds | Désactivez les modules “Print” ou “Advanced Inventory” si non utilisés. | Moins de requêtes SQL complexes → temps de réponse plus court. |
| Lazy‑loading des libs | Charger les bibliothèques d’authentification uniquement à la première requête. | Évite le sur‑coût d’inclusion de fichiers à chaque appel. |
| Pré‑compilation des templates Smarty | smartctl -c (ou compile_all.php) |
Réduction du parsing template de 0,5 ms à 0,1 ms par appel. |
4.5 Tuning de la base de données
| Paramètre MySQL/MariaDB | Valeur conseillée (30 % de la RAM) | Raison |
|---|---|---|
innodb_buffer_pool_size |
40‑50 % de la RAM (ex. 8 GB sur serveur 16 GB) | Cache des pages de données, évite les lectures disque fréquentes. |
max_connections |
250‑300 selon le nombre d’utilisateurs simultanés | Prévient les “Too many connections”. |
query_cache_type |
0 (désactivé) | Depuis MySQL 8 le query‑cache est déprécié et nuit aux performances. |
table_open_cache |
2000‑4000 | Permet de garder ouvertes plus de tables de référence (ex. listes de clients). |
innodb_log_file_size |
1‑2 GB | Réduit le flush des logs de transaction. |
Astuce : Activez
performance_schema=OFFdans le my.cnf si vous n’avez pas besoin de diagnostics détaillés en production.
4.6 Mesure et monitoring (pour valider les gains)
| Outil | Métrique clé | Seuil d’alerte |
|---|---|---|
| Prometheus + node_exporter | nginx_http_current_connections |
> 80 % de la capacité du worker |
| Grafana dashboard | php_fpm_active_processes |
> 70 % du pool pm.max_children |
| logrotate + fail2ban | auth_request_time (ms) |
> 200 ms (95ᵉ percentile) |
| JMeter | JWT Validation latency |
> 150 ms (temps moyen) |
Mise en place : créez un tableau de bord unique afin de visualiser le temps de réponse du gateway SSO vs le temps de traitement interne de Dolibarr. Une différence supérieure à 200 ms indique généralement un problème de configuration du proxy.
5. Checklist de mise en production « SSO + Dolibarr » orientée performance
| ✅ | Action |
|---|---|
| 1 | Activer HTTPS en front‑end et configurer le TLS avec ssl_session_cache partagé. |
| 2 | Configurer auth_request avec un timeout ≤ 3 s et un cache proxy_cache de 2 GB. |
| 3 | Choisir un IdP avec JWT signé en HS256 ou ES256 (ex. Keycloak). |
| 4 | Partager le cookie de session via session.cookie_domain. |
| 5 | Déployer Redis comme backend de session + TTL de 30 min. |
| 6 | Activer OPcache (256 Mo memo) et APCu (128 Mo) dans php.ini. |
| 7 | Tuner la base : InnoDB buffer pool 40 % RAM, query cache désactivé. |
| 8 | Mettre en place un load‑balancer sticky (ip_hash ou cookie). |
| 9 | Désactiver les plugins non nécessaires de Dolibarr. |
| 10 | Surveiller pendant 48 h avec Grafana / Prometheus, ajuster proxy_cache_valid (10 min‑1 h). |
| 11 | Test de charge (JMeter / k6) : viser ≤ 250 ms de latence SSO, ≤ 1 s de temps complet page. |
| 12 | Plan B : Si le taux d’erreurs dépasse 1 % → bascule en mode fallback (login direct) pour éviter le blocage complet du site. |
6. Exemple de configuration NGINX détaillée
# ==== 1. Cache de validation ====
proxy_cache_path /var/cache/nginx/ssso levels=1:2 keys_zone=ssso_cache:50m max_size=2g inactive=1h use_temp_path=off;
# ==== 2. Upstream des services d'auth ====
upstream auth_backend {
server 127.0.0.1:8082; # Keycloak (ou autre)
keepalive 32;
}
# ==== 3. Server principal ====
server {
listen 80;
server_name dolibarr-exemple.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name dolibarr-exemple.com;
# TLS optimisé
ssl_certificate /etc/letsencrypt/live/dolibarr-exemple.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/dolibarr-exemple.com/privkey.pem;
ssl_session_cache shared:SSL:10m;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_cipher_suite HIGH:!aNULL:!MD5;
# ==== Reverse‑proxy ====
location / {
proxy_pass http://php_fpm;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Auth Request
auth_request /auth_validate;
proxy_pass http://php_fpm;
}
# ==== Auth endpoint ====
location = /auth_validate {
internal;
proxy_pass http://auth_backend;
proxy_set_header Host $host;
proxy_set_header X-Original-URI $request_uri;
proxy_cache ssso_cache;
proxy_cache_valid 200 1h;
proxy_cache_use_stale error timeout updating;
# Timeout must be < proxy_read_timeout
proxy_connect_timeout 2s;
proxy_send_timeout 3s;
proxy_read_timeout 3s;
}
# ==== PHP‑FPM pool ====
location ~ \.php$ {
fastcgi_pass unix:/run/php-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_read_timeout 300;
}
# ==== Sticky session (IP hash) ====
upstream php_fpm {
ip_hash;
server 127.0.0.1:9000;
}
}
Note : Le cache
ssso_cachestocke la réponse200du service d’auth. Ainsi, si le token n’a pas expiré, NGINX renvoie immédiatement la réponse 200 sans toucher à l’IdP, ce qui réduit le temps de validation de ≈ 150 ms à < 15 ms.
7. Prochaines évolutions (au‑delà de la performance)
| Évolution | Pourquoi ? |
|---|---|
| OAuth2 + PKCE | Renforce la sécurité des flux de code sans dépendre de cookies HTTP‑only. |
| Reverse‑proxy HTTP/3 ( QUIC ) | Réduction de la latence TLS, surtout sur mobile. |
| Session‑Level Circuit‑Breaker | Limite le nombre de requêtes d’authentification simultanées pour éviter l’épuisement de l’IdP. |
| Mise en cache côté client (Service Workers) | Permet d’intercepter les appels d’API et de servir une version “offline” tant que le token est valide. |
| Décentralisation du SSO (OpenID Connect Discovery) | Simplifie la rotation des clés publiques via le fichier .well-known/openid-configuration. |
8. Conclusion
En combinant :
- une configuration fine du reverse‑proxy (timeouts, cache, stickiness),
- un Provider d’identité optimisé (HS256/ES256, JWT compact),
- le partage de session via Redis et
session.cookie_domain, - les réglages PHP/Dolibarr (OPcache, APCu, désactivation des plugins),
- et un tuning de la base de données,
on obtient une réduction de la latence SSO de > 70 %, une capacité de traitement de 2‑3× plus élevée sous pic de connexion, et surtout une expérience utilisateur fluide (pages chargées en < 1 s même avec 500 utilisateurs simultanés).
Les points d’attention restent :
- Surveiller les temps de validation (
auth_request_time). - Ajuster le cache et les TTL des sessions dès que le trafic dépasse les seuils de votre infrastructure.
- Tester les scénarios de panne (IdP down, réseau saturé) pour valider la résilience.
En résumé : la performance de Dolibarr avec SSO ne dépend pas seulement du code de l’ERP mais surtout de l’architecture d’authentification. Une mise en place rigoureuse des caches, un choix judicieux d’algorithme de signature et un partage efficace des sessions permettent de transformer un goulot d’étranglement en un flux quasi‑transparent, tout en conservant la sécurité du Single Sign‑On.
Bon déploiement ! 🚀