Aller au contenu

Authentification

Pennylane prend en charge trois modes d'authentification. Tous se traduisent par un jeton Bearer dans l'en-tête Authorization, que le SDK définit pour vous.

Jeton Company API

Pour les intégrations qui gèrent une seule société (le cas le plus courant).

Créé dans Paramètres > Connectivité > Développeurs par un administrateur de la société. Les jetons portent :

  • un ensemble de scopes (permissions) : lecture seule, ou lecture et écriture, par domaine de ressources ;
  • une date d'expiration : anticipez le renouvellement, un jeton expiré déclenche une Pennylane\Sdk\Exception\AuthenticationException.
use Pennylane\Sdk\Pennylane;

$client = new Pennylane();                     // variable d'environnement PENNYLANE_API_TOKEN
$client = new Pennylane(apiToken: 'tok...');    // explicite

Jeton Firm API

Pour les cabinets d'expertise comptable opérant sur l'ensemble de leur portefeuille de dossiers clients. Généré depuis le compte cabinet. Utilisez le client dédié :

use Pennylane\Sdk\PennylaneFirm;

$firm = new PennylaneFirm();                   // variable d'environnement PENNYLANE_FIRM_API_TOKEN

Les jetons Firm et Company ne sont pas interchangeables : ils s'authentifient sur des URL de base différentes, avec des scopes différents.

OAuth 2.0 (applications partenaires)

Si vous développez une application que d'autres sociétés Pennylane installent, utilisez le flux authorization-code. Le SDK fournit les fonctions d'aide Pennylane\Sdk\OAuth\OAuthApp pour tout le processus : authorizationUrl() pour rediriger l'utilisateur, exchangeCode() pour échanger le code reçu contre une paire de jetons, et refresh() pour la renouveler.

Une fois un jeton d'accès obtenu, utilisez-le comme un jeton de société :

$client = new Pennylane(apiToken: $tokens->accessToken);

Rotation des jetons de rafraîchissement

Pennylane fait tourner les jetons de rafraîchissement : chaque appel à refresh() invalide les deux jetons précédents. Ne lancez jamais deux rafraîchissements en parallèle, et persistez immédiatement la paire retournée.

Scopes

Chaque endpoint requiert un scope, documenté sur la ligne Scope: de la docblock de chaque méthode du SDK (par exemple customer_invoices:all pour créer des factures, customer_invoices:readonly pour les lister). Lorsque le jeton n'a pas le scope requis, l'API répond 403 et le SDK lève une Pennylane\Sdk\Exception\PermissionDeniedException :

use Pennylane\Sdk\Exception\PermissionDeniedException;

try {
    $client->customerInvoices->create(/* ... */);
} catch (PermissionDeniedException $e) {
    echo $e->getMessage();   // le message de l'API, qui précise le scope manquant
    echo $e->statusCode;     // 403
}

Principaux scopes v2 : customers, products, customer_invoices, quotes, customer_mandates, billing_subscriptions, commercial_documents, suppliers, supplier_invoices, purchase_requests, journals, ledger_accounts, ledger_entries, categories, transactions, bank_accounts, file_attachments (chacun en :readonly ou :all), ainsi que trial_balance:readonly, fiscal_years:readonly, bank_establishments:readonly et exports:fec, exports:agl, exports:gl.

Obligation du HTTPS

Le SDK refuse d'envoyer un jeton bearer sur une connexion http en clair : construire un client avec un baseUrl non sécurisé lève une Pennylane\Sdk\Exception\ConfigurationException avant même l'envoi d'une requête. La seule exception est http sur localhost, 127.0.0.1 ou ::1, pour le développement local.

new Pennylane(baseUrl: 'http://example.com'); // lève ConfigurationException

Bonnes pratiques

  • Ne committez jamais un jeton. Utilisez des variables d'environnement ou un gestionnaire de secrets.
  • Privilégiez les jetons en lecture seule pour les intégrations de reporting.
  • Donnez à chaque intégration son propre jeton, afin de pouvoir en révoquer un sans casser les autres, et pour que le budget de limite de débit (attribué par jeton) ne soit pas partagé.