Tabla de Contenidos

SmartAuth

SmartAuth est le module d'authentification JWT pour Dolibarr, conçu pour les applications SmartMaker.

Pourquoi SmartAuth ?

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.

Notre approche

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 :

Journaux de connexion

Accédez aux journaux pour détecter des actions incorrectes et gérer les accès :

Installation

Téléchargez SmartAuth gratuitement sur le DoliStore : https://www.dolistore.com/product.php?id=2509&l=fr

Flux d'authentification JWT

Schéma global

┌─────────────┐         ┌─────────────┐         ┌─────────────┐
│   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           │                       │
       │<──────────────────────│                       │

Tokens JWT

SmartAuth utilise deux tokens :

Token Durée Usage
accessToken 15 minutes Authentifier les requêtes API
refreshToken 7 jours Obtenir un nouveau accessToken

Endpoints d'authentification

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
POST /qr-pair/{pairingId}/claim Mobile revendique un pairing affiché par le PC Non
POST /qr-pair/{pairingId}/poll Mobile poll jusqu'à confirmation du PC Non

Configuration côté api.php

Routes d'authentification

<?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);

Le fichier smartmaker-api-prepend.php

Ce fichier (généré par SmartBoot) contient :

<note important>Ne modifiez pas ce fichier sauf si vous savez ce que vous faites.</note>

Utilisation côté React

Configuration du Provider

// appConfig.js
export const config = {
  api: {
    prefixUrl: import.meta.env.VITE_API_URL,
    paths: {
      login: "login",
      logout: "logout",
      refresh: "refresh",
    },
  },
};

Login avec useApi (manuel)

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>
  );
};

Login simplifié avec LoginComponent

Plutôt que de réinventer le formulaire, smartcommon expose <LoginComponent> qui encapsule le flux complet : email + mot de passe + sélection d'entité optionnelle + scan QR pair smartAuth :

import { LoginComponent } from '@cap-rel/smartcommon';

<LoginComponent
  onSuccess={(user) => navigate("/")}
  onError={(err) => log.error(err)}
  // QR pair activé par défaut. Désactiver explicitement si le backend
  // n'expose pas /qr-pair (cas non-smartAuth).
  enableQrPair
  showRememberMe
  labels={{
    emailLabel: t("login.email"),
    submitLabel: t("login.submit"),
    scanQrLabel: t("login.scan-qr"),
  }}
/>

Voir Composants avancés -> LoginComponent pour les libellés, slots de styling et options du flux QR pair.

Refresh automatique

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

Logout

const handleLogout = async () => {
  await api.private.post('logout');
  setSession(null);
  navigate('/login');
};

Gestion des appareils

Enregistrer un appareil

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',
    },
  });
};

Structure côté Dolibarr

SmartAuth stocke les appareils dans une table dédiée :

Champ Description