Gérer les clients OAuth2
Clients OAuth2
Créez et gérez des clients OAuth2 pour l'accès à l'API. Chaque client se voit attribuer des champs d'application (autorisations) spécifiques et peut générer des jetons valables pendant 1 heure.
POST /oauth/token
grant_type=client_credentials
Flux d'authentification par informations d'identification du client
Le protocole OAuth2 « Client Credentials Grant » (RFC 6749, section 4.4) pour l'authentification de machine à machine
Créer un client
Dans le backend, sous Outils → Clients OAuth2 xoPort, créez un nouveau client avec les périmètres souhaités.
Demander un jeton
À l'aide de l'ID client et de la clé secrète, demandez un jeton d'accès via le point de terminaison /oauth/token.
Utiliser l'API
Utiliser le jeton dans l'en-tête « Authorization: Bearer » pour toutes les requêtes API.
Demander un jeton
curl -X POST https://shop.de/xpanel/xoport/oauth/token
-H "Content-Type: application/x-www-form-urlencoded"
-d "grant_type=client_credentials"
-d "client_id=xoc_abc123..."
-d "client_secret=xos_def456..."
Réponse
{
"access_token": "xoat_eyJhbGciOiJIUzI1NiIs...",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "products:read products:write categories:read"
}
Erreur au niveau du point de terminaison des jetons
Le point de terminaison du jeton répond au format OAuth2 avec error et error_description, vérifiés dans cet ordre :
| HTTP | error |
Quand |
|---|---|---|
| 405 | invalid_request |
Appel non effectué via POST |
| 400 | unsupported_grant_type |
grant_type n'est pas client_credentials, même avec un JSON tronqué qui n'est pas lisible |
| 400 | invalid_request |
client_id ou client_secret manquant ; depuis la v2.122.11, l'un d'entre eux peut également se présenter sous forme de liste (client_id[]=…, un tableau dans le corps JSON) |
| 429 | rate_limit_exceeded |
plus de 30 requêtes en 300 secondes pour cette client_id (voir « Limite de requêtes » ci-dessous) |
| 401 | invalid_client |
Client inconnu, clé secrète incorrecte ou client désactivé |
| 400 | invalid_scope |
Aucun des champs d'application demandés n'est autorisé pour le client. Depuis la version v2.122.11, cela inclut également un champ d'application demandé qui ne peut pas être lu (UTF-8 non valide ou une liste telle que scope[]=…) ; aucun jeton n'est émis. |
Sans scope, tous les champs d’application du client s’appliquent.
Portées disponibles
| Portée | Description | Opérations |
|---|---|---|
products:read |
Lire les produits | GET |
products:write |
Créer/mettre à jour des produits | POST |
products:delete |
Supprimer des produits | DELETE |
categories:read |
Lire les catégories | GET |
catégories : écriture |
Créer/mettre à jour des catégories | POST |
categories:delete |
Supprimer des catégories | DELETE |
clients : lecture |
Lire les clients | GET |
customers:write |
Créer/mettre à jour des clients | POST |
customers:delete |
Supprimer des clients | DELETE |
manufacturers:read |
Lire les fabricants | GET |
manufacturers:write |
Créer/mettre à jour des fabricants | POST |
manufacturers:delete |
Supprimer des fabricants | DELETE |
commandes : lecture |
Lire les commandes | GET |
news:read |
Lire les articles d'actualité | GET |
news:write |
Créer/mettre à jour un article d'actualité | POST |
news:delete |
Supprimer un article d'actualité | DELETE |
newscategories:read |
Lire les catégories d'actualités | GET |
newscategories:write |
Créer/mettre à jour des catégories d'actualités | POST |
newscategories:delete |
Supprimer des catégories d'actualités | DELETE |
faq:read |
Lire la FAQ | GET |
faq:write |
Créer/mettre à jour la FAQ | POST |
faq:delete |
Supprimer une FAQ | DELETE |
faqcategories : lire |
Lire les catégories de la FAQ | GET |
faqcategories:write |
Créer/mettre à jour les catégories de la FAQ | POST |
faqcategories:delete |
Supprimer des catégories de FAQ | DELETE |
Introspection des scopes
L’endpoint /me vous permet d’interroger les scopes du jeton actuel :
curl -X GET https://shop.de/xpanel/xoPort/me
-H "Authorization: Bearer xoat_eyJhbGciOi..."
Réponse
{
"success": true,
"api_version": "2.122.11",
"type": "client_info",
"data": {
"client_id": "xoc_abc123...",
"client_name": "Mein API Client",
"scopes": ["products:read", "products:write", "categories:read"],
"rate_limit": 5000,
"rate_limit_window": 3600,
"rate_limit_remaining": 4987,
"rate_limit_reset": 1792327500,
"token_expires_at": "2026-10-18 15:00:00",
"token_created_at": "2026-10-18 14:00:00",
"client_created_at": "2026-01-15 10:30:00",
"client_last_used_at": "2026-10-18 14:22:15"
},
"timestamp": "2026-10-18 14:22:16"
}
Depuis la version v2.122.11 rate_limit_window, la durée de la fenêtre de comptage est exprimée en secondes (toujours 3 600). rate_limit_remaining et rate_limit_reset ont les mêmes valeurs que les en-têtes X-RateLimit-Remaining et X-RateLimit-Reset de la même réponse ; la requête envoyée à /me est prise en compte dans ce calcul. Pour les clients sans limite de requêtes, les deux valeurs sont null.
Limite de requêtes
La limite de requêtes s'applique par client, et non par jeton : tous les jetons et processus d'un même client partagent un compteur. Le comptage s’effectue dans une fenêtre glissante de 3 600 secondes ; une place se libère dès que la requête la plus ancienne comptabilisée date de plus d’une heure. Vous définissez la valeur (rate_limit, nombre de requêtes par fenêtre) dans le backend au niveau du client ; GET /me l’affiche (null signifie « illimité », 0 a le même effet).
Paramètres par défaut (depuis la version 4.9.17 de la boutique ; auparavant, un champ vide signifiait « illimité ») : pour l’exploitant, le champ est prérempli à 5 000 lors de la création ; une valeur supérieure n’est pas possible, et s’il est enregistré vide, la valeur par défaut est 5 000. Une valeur supérieure à 5 000 définie par XONIC est conservée tant que le champ reste inchangé. À partir de la version 4.9.174 de Shop, la fonction « Modifier le client » affiche, pour un client illimité, un champ vide accompagné de la mention « Illimité (défini par XONIC) » ; s’il est enregistré vide, il reste illimité ; un nombre inférieur ou égal à 5 000 le limite ; seul XONIC peut alors le rétablir à « illimité ». ⚠️ Jusqu’à la version 4.9.173 de Shop, un client « illimité » se voyait attribuer la valeur 5 000 dès que l’administrateur l’enregistrait, même si seuls le nom ou la note avaient été modifiés. Dans l’administrateur XONIC, le champ est vide, et « vide » signifie ici « illimité ». ⚠️ Jusqu’à la version Shop 4.9.173, lors de la création avec un champ vide, un client avec une limite de 5 000 était tout de même généré si la colonne dans la base de données avait la valeur par défaut de 5 000 (par exemple après une réinstallation à partir de la version Shop 4.9.17). Vérifiez ces valeurs après la création dans « GET /me » → « rate_limit ». Sur les boutiques de la version 4.9.17 à 4.9.167, chaque vérification HealthCheck et chaque mise à jour réinitialisent un client « illimité » à 5 000 ; à partir de la version 4.9.168 de la boutique, la valeur « illimitée » est conservée. Une limite modifiée prend effet immédiatement, y compris pour les jetons en cours.
Quota dans chaque réponse Depuis la v2.122.11
Chaque réponse à une requête comportant un jeton valide provenant d’un client soumis à une limite de requêtes comporte trois en-têtes :
| En-tête | Contenu |
|---|---|
X-RateLimit-Limit |
Limite de requêtes du client par tranche de 3 600 secondes |
X-RateLimit-Remaining |
Nombre de requêtes encore disponibles dans la fenêtre ; cette requête a déjà été décomptée. « 0 » signifie : cette requête a encore été acceptée, la suivante sera rejetée. |
X-RateLimit-Reset |
Temps Unix (en secondes depuis 1970, UTC) auquel la requête la plus ancienne comptabilisée quitte la fenêtre : son heure plus 3 600 secondes, sans changement d’heure |
- Avec en-têtes : données, réponses d'erreur telles que 400, 403 ou 404, téléchargements de fichiers, requêtes XML avec jeton et la réponse 429 elle-même.
- Sans en-têtes : clients sans limite de requêtes, requêtes sans jeton valide (401), requêtes XML sans jeton ou provenant d’une adresse dont l’IP est autorisée par l’interface XML et le point de terminaison des jetons.
- Le reste s'applique à l'ensemble des processus du client : ce qu'une réponse mentionne peut déjà avoir été utilisé par un processus parallèle.
- Les boutiques jusqu’à la version 4.9.170 n’envoient pas ces en-têtes. Leur absence ne signifie pas « illimité » : dans ce cas, consultez
GET /me.
Si la limite est dépassée, l’API répond avec un code HTTP 429 et Retry-After, voir l’exemple dans la section « Gestion des erreurs ».
Limite propre au point de terminaison du jeton
POST /oauth/token a sa propre limite : 30 requêtes en 300 secondes par client_id, également calculée de manière glissante ; les requêtes avec un secret incorrect sont également comptabilisées. Au-delà, un code d'erreur HTTP 429 est renvoyé avec rate_limit_exceeded. Depuis la version v2.122.11, Retry-After indique le nombre de secondes jusqu'à la prochaine acceptation (de 1 à 300) ; auparavant, cette valeur était fixe à 300. Le point de terminaison des jetons n'envoie pas de X-RateLimit-*. Un jeton est valable une heure : récupérez-le une seule fois et transmettez-le à tous les processus.
Journal d'utilisation
Dans le backend, le journal d'utilisation affiche, pour chaque client, les 1 000 dernières requêtes avec la requête et la réponse correspondantes. Ne figurent pas dans ce journal les interruptions de l'exportation avec un code HTTP 400 avant le début d'une requête (erreurs de filtrage, de défilement et de chemin d'accès), les justificatifs et les pièces jointes individuelles aux tickets, la réponse 429 et les requêtes XML. Ces requêtes sont néanmoins comptabilisées dans la limite de requêtes, à l'exception des codes 429 et des requêtes XML sans jeton.
Restriction IP (facultative)
Depuis la version v2.119.0, l’API REST exige systématiquement un jeton OAuth2, et ses champs d’application s’appliquent. L’autorisation IP de l’interface XML (XML_PORT_IP_FILTER) ne donne pas accès à l’API REST.
De plus, vous pouvez limiter l’accès à des adresses fixes. Si le paramètre XOPORT_REST_IP_LIST est renseigné, toute requête doit provenir d’une adresse figurant dans la liste et comporter un jeton valide ; la liste ne remplace en aucun cas le jeton. Les requêtes provenant d’autres adresses reçoivent la réponse « 403 » avec le message « reason: deny_ip_not_listed ».
Remarque de sécurité
Ne stockez jamais le secret client ni le jeton d'accès dans le code du frontend ou dans des dépôts publics !