Gérer les clients OAuth2

OAuth2 · RFC 6749 · Identifiants du client

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

1

Créer un client

Dans le backend, sous Outils → Clients OAuth2 xoPort, créez un nouveau client avec les périmètres souhaités.

2

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.

3

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
Modification de la portée effective uniquement à partir du prochain jeton : un jeton déjà émis conserve les portées qui étaient valables au moment de son émission jusqu'à son expiration, soit au maximum une heure. Pour retirer immédiatement une portée, modifiez les portées, puis sélectionnez « Révoquer les jetons » dans le menu d’actions du client dans le backend (à partir de la version 4.9.168 de la boutique, droit « Supprimer » ; le secret reste inchangé). Sur les versions antérieures, désactivez le client puis réactivez-le immédiatement : cela révoque également tous les jetons, le secret reste inchangé. L’option « Renouveler le secret » révoque également les jetons, mais nécessite le nouveau secret dans la connexion.

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 !