Authentification#

L’API utilise OAuth2 client_credentials — le flux de machine à machine. Pas d’utilisateur, pas de redirection navigateur, pas d’écran de consentement.

Deux hôtes sont impliqués, et ton client parle aux deux :

Rôle

Hôte

Objet

Fournisseur d’identité

https://auth.shiftavo.com

émet les jetons

Shard

depuis le claim api_base de ton jeton

sert les données

Présenter tes identifiants#

Les deux méthodes standard d’authentification client OAuth2 (RFC 6749 §2.3.1) sont acceptées. Utilise celle que ta bibliothèque HTTP ou OAuth rend la plus simple — elles sont équivalentes ici.

client_secret_post — identifiants dans le corps du formulaire :

POST /identity/o/api/token HTTP/1.1
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials
client_id=cust-acme-integration
client_secret=<secret>
scope=shifts.read

client_secret_basic — identifiants dans un en-tête HTTP Basic, seul client_id dans le corps :

POST /identity/o/api/token HTTP/1.1
Authorization: Basic base64("cust-acme-integration:<secret>")
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials
client_id=cust-acme-integration
scope=shifts.read

client_secret_basic est la valeur par défaut de la spécification et ce que produisent la plupart des bibliothèques OAuth du marché ; client_secret_post est plus simple à construire à la main, sans étape base64.

Expiration et renouvellement#

Les jetons durent 1800 secondes par défaut. Le flux client_credentials n’a pas de jeton de rafraîchissement — c’est voulu (RFC 6749 §4.4.3), et cela ne te coûte rien : ton client détient déjà le client_id et le client_secret, donc « rafraîchir » revient simplement à demander un nouveau jeton avec le même appel. Un jeton de rafraîchissement ne serait qu’un secret de plus à stocker.

Deux règles rendent un client robuste :

  • Mets le jeton en cache et réutilise-le jusqu’à approcher d’expires_in. Le renouveler ~30 secondes à l’avance évite les courses au moment de l’expiration.

  • En cas de 401 renvoyé par l’API de données — un jeton peut être invalidé plus tôt, par exemple lors d’une rotation de clé — supprime le jeton mis en cache, demandes-en un nouveau et réessaie la requête une fois.

Routage : le claim api_base#

Le jeton est un JWT. Au-delà des champs OAuth standard, il porte :

Claim

Exemple

Signification

api_base

https://app.shiftavo.com

URL de base de l’hôte à appeler

aud

["https://app.shiftavo.com/api"]

API du shard cible

tenant_id

0194d1c0-…

L’entreprise à laquelle tu es rattaché

tenant_name

Acme

Nom affiché

tenant_status

active

Les entreprises non actives se voient refuser un jeton

Lis api_base et appelle cet hôte. Garde un repli configuré au cas où le claim serait absent, mais privilégie le claim : c’est lui qui nous permet d’ajouter ou de déplacer un shard sans aucun changement de ton côté.

aud et le rattachement à l’entreprise sont définis côté serveur à partir du tenant auquel appartiennent tes identifiants. Ils ne sont pas demandables — un client ne peut physiquement pas viser une autre entreprise ni un autre shard.

Ce qu’un jeton machine n’est pas#

Les jetons machine n’ont aucun sub ni claim d’utilisateur ou d’affiliation. Chaque appel agit en tant qu’intégration elle-même, limitée par ses scopes. Deux conséquences :

  • L’API ne peut pas deviner qui est responsable d’une écriture : certaines écritures t’obligent donc à nommer explicitement une personne — voir Nommer la personne derrière une écriture.

  • Un jeton utilisateur de première partie (issu de l’app web ou mobile) est rejeté sur cette surface. Elle est réservée aux machines.

Erreurs à ce stade#

Symptôme

Cause

401 renvoyé par le point de terminaison du jeton

client_id / client_secret erronés, ou l’entreprise est suspendue

400 invalid_scope sur le point de terminaison du jeton

tu as demandé un scope qui n’a pas été accordé à ton client

401 renvoyé par l’API de données

jeton expiré, invalide ou invalidé par anticipation — renouvelle-le et réessaie une fois

403 insufficient_scope renvoyé par l’API de données

jeton valide, autorisation manquante — voir Scopes