SmartAuth est le module d'authentification JWT pour Dolibarr, conçu pour les applications SmartMaker.
Nativement Dolibarr propose une API où chaque utilisateur dispose d'une seule clé d'API donnant accès à tout son périmètre fonctionnel.
Ce fonctionnement pose problème : si vous développez une application mobile qui ne devrait avoir accès qu'à l'agenda de l'utilisateur, avec la clé native l'application pourra également accéder aux factures et autres éléments.
Avec SmartAuth, un utilisateur peut avoir autant de clés d'API qu'il souhaite, chaque clé ayant ses propres droits. Si une clé est liée à une application, elle ne sera pas réutilisable par une autre.
Avantages :
Téléchargez SmartAuth gratuitement sur le DoliStore : https://www.dolistore.com/product.php?id=2509&l=fr
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Mobile │ │ api.php │ │ Dolibarr │
│ (React) │ │ (JWT) │ │ (PHP) │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
│ 1. POST /login │ │
│ {login, password} │ │
│──────────────────────>│ │
│ │ 2. Vérifier user │
│ │──────────────────────>│
│ │ │
│ │ 3. User valide │
│ │<──────────────────────│
│ 4. {accessToken, │ │
│ refreshToken} │ │
│<──────────────────────│ │
│ │ │
│ 5. GET /items │ │
│ Authorization: Bearer│ │
│──────────────────────>│ │
│ │ 6. Valider token │
│ │ + charger user │
│ │──────────────────────>│
│ │ │
│ 7. Données │ │
│<──────────────────────│ │
SmartAuth utilise deux tokens :
| Token | Durée | Usage |
|---|---|---|
accessToken | 15 minutes | Authentifier les requêtes API |
refreshToken | 7 jours | Obtenir un nouveau accessToken |
| Méthode | Route | Description | Protégé |
|---|---|---|---|
| GET | /login | Récupérer les infos de connexion (logo, etc.) | Non |
| POST | /login | Authentification (login + password) | Non |
| GET | /refresh | Renouveler l'accessToken | Non |
| POST | /logout | Déconnexion (invalide le refreshToken) | Oui |
| POST | /device | Enregistrer un appareil pour les notifications | Oui |
<?php
require_once '../smartmaker-api-prepend.php';
use SmartAuth\Api\AuthController;
use SmartAuth\Api\RouteController as Route;
// Routes publiques
Route::get('login', AuthController::class, 'index'); // Infos connexion
Route::post('login', AuthController::class, 'login'); // Authentification
Route::get('refresh', AuthController::class, 'refresh'); // Refresh token
// Routes protégées
Route::post('logout', AuthController::class, 'logout', true); // Déconnexion
Route::post('device', AuthController::class, 'device', true); // Enregistrer device
// Vos routes métier...
Route::get('items', ItemController::class, 'index', true);
// Fallback
json_reply('Access denied', 403);
Ce fichier (généré par SmartBoot) contient :
<note important>Ne modifiez pas ce fichier sauf si vous savez ce que vous faites.</note>
// appConfig.js
export const config = {
api: {
prefixUrl: import.meta.env.VITE_API_URL,
paths: {
login: "login",
logout: "logout",
refresh: "refresh",
},
},
};
import { useApi, useGlobalStates } from '@cap-rel/smartcommon';
const LoginPage = () => {
const api = useApi();
const gst = useGlobalStates();
const handleLogin = async (data) => {
try {
const user = await api.login(data);
gst.local.set('session', user);
} catch (error) {
console.error('Login failed:', error);
}
};
return (
<form onSubmit={handleSubmit(handleLogin)}>
{/* ... */}
</form>
);
};
Le hook useApi gère automatiquement le refresh du token :
// Quand l'accessToken expire, useApi : // 1. Intercepte l'erreur 401 // 2. Appelle GET /refresh avec le refreshToken // 3. Met à jour les tokens en session // 4. Rejoue la requête originale
const handleLogout = async () => {
await api.private.post('logout');
setSession(null);
navigate('/login');
};
Pour les notifications push, enregistrez l'appareil après le login :
const registerDevice = async (pushToken) => {
await api.private.post('device', {
json: {
token: pushToken,
platform: 'android', // ou 'ios', 'web'
name: 'Mon téléphone',
},
});
};
SmartAuth stocke les appareils dans une table dédiée :
| Champ | Description |
|---|---|
fkuser | Date de dernière utilisation |
useGlobalStates qui persiste en localStorage chiffréSmartAuth inclut un système complet de réinitialisation de mot de passe par token.
| Méthode | Route | Description | Protégé |
|---|---|---|---|
| POST | /password/reset | Demande de réinitialisation (envoi d'email) | Non |
| POST | /password/confirm | Confirmation avec token | Non |
| POST | /password/change | Changement de mot de passe (utilisateur connecté) | Oui |
// Côté React
const requestReset = async (email) => {
await api.public.post('password/reset', {
json: { email }
});
};
Le serveur :
const confirmReset = async (token, newPassword) => {
await api.public.post('password/confirm', {
json: { token, password: newPassword }
});
};
const changePassword = async (oldPassword, newPassword) => {
await api.private.post('password/change', {
json: {
current_password: oldPassword,
new_password: newPassword
}
});
};
SmartAuth fournit un système de fichiers temporaires pour le téléchargement de binaires (exports Excel, PDF générés, etc.).
| Méthode | Route | Description |
|---|---|---|
| GET | /temp-file/{token} | Téléchargement base64 (JSON) |
| GET | /temp-file/{token}/binary | Téléchargement binaire (stream) |
| DELETE | /temp-file/{token} | Suppression du fichier |
use SmartAuth\Api\SmartTempFile;
public function exportExcel($payload)
{
// Générer le fichier
$filePath = '/tmp/export.xlsx';
// ... génération du fichier ...
// Stocker en fichier temporaire (TTL défaut : 1 heure)
$tempFile = new SmartTempFile();
$token = $tempFile->store($filePath, [
'filename' => 'export.xlsx',
'mimetype' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'user_id' => $payload['user_id'],
'entity' => $payload['entity'],
]);
return [['token' => $token], 200];
}
// Téléchargement binaire
const downloadExport = async (token) => {
const response = await api.get(`temp-file/${token}/binary`, { raw: true });
const blob = await response.blob();
// Créer un lien de téléchargement
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'export.xlsx';
a.click();
URL.revokeObjectURL(url);
};
SmartAuth gère automatiquement les headers CORS pour les requêtes cross-origin.
| Constante Dolibarr | Description | Défaut |
|---|---|---|
SMARTAUTHCORSORIGIN | Origine autorisée | * |
SMARTAUTHCORSMETHODS | Méthodes autorisées | GET, POST, PUT, DELETE, PATCH, OPTIONS |
SMARTAUTHCORSHEADERS | Headers autorisés | Content-Type, Authorization, X-DeviceId |
Les requêtes OPTIONS (preflight) sont gérées automatiquement.
<note important>En production, configurez SMARTAUTHCORSORIGIN avec l'URL exacte de votre application au lieu de *.</note>
Si votre Dolibarr est derrière un reverse proxy (nginx, Apache, etc.), configurez les IP de confiance pour que SmartAuth détecte correctement l'adresse IP du client :
| Constante | Description |
|---|---|
SMARTAUTHTRUSTEDPROXIES | Liste d'IP séparées par des virgules (ex: 10.0.0.1,192.168.1.100) |
Les IP privées (127.x, 10.x, 172.16-31.x, 192.168.x) sont automatiquement considérées comme des proxys de confiance.
SmartAuth définit des routes locales automatiquement chargées. Elles n'ont pas besoin d'être déclarées dans votre api.php :
| Groupe | Routes |
|---|---|
| Auth | /login, /refresh, /logout, /device |
| Mot de passe | /password/reset, /password/confirm, /password/change |
| Fichiers | /file/{hash}, /file/{hash}/binary |
| Fichiers temporaires | /temp-file/{token}, /temp-file/{token}/binary |
| Synchronisation | /sync/register, /sync/pull, /sync/push, /sync/status, /sync/conflicts |
| PWA | /manifest, /icon/{size} |