DOCS

Authentification OAuth 2.0

Authentification OAuth 2.0

Authentifiez vos services backend avec Zonos via la cryptographie à clé asymétrique — sans secrets partagés.

Zonos prend en charge l'authentification machine à machine via OAuth 2.0 JWT Bearer Token Grant (RFC 7523). Votre service signe un JWT à courte durée de vie avec votre clé privée RSA ; Zonos le vérifie à l'aide de votre clé publique enregistrée et renvoie un jeton Bearer limité à votre organisation.

Résumé du flux :

  1. Générez une paire de clés RSA et enregistrez votre clé publique auprès de Zonos.
  2. À l'exécution, signez une assertion JWT avec votre clé privée et envoyez-la en POST au point de terminaison de jeton.
  3. Zonos renvoie un jeton d'accès à courte durée de vie.
  4. Incluez le jeton d'accès sous la forme Authorization: Bearer <token> sur chaque requête API.

Générez une paire de clés RSA 4096 bits et partagez la clé publique avec Zonos. Cela se fait une fois lors de l'intégration.

Générer la paire de clés 

1openssl genrsa -out private_key.pem 4096
2 
3 
4openssl rsa - private_key.pem -pubout -out public_key.pem

Partagez public_key.pem avec Zonos. Stockez private_key.pem dans un gestionnaire de secrets dédié (AWS Secrets Manager, HashiCorp Vault, etc.) — jamais dans le contrôle de source ou les variables d'environnement.

Zonos enregistrera votre clé et renverra votre Organization ID, qui devient la revendication iss dans toutes les assertions JWT.

Signez un JWT avec RS256 en utilisant votre clé privée. L'assertion est valide pour un seul échange de jeton — gardez une fenêtre d'expiration courte (60–300 secondes).

Revendications requises 

RevendicationValeur
issVotre Organization ID Zonos (par ex. "org_abc123")
subIdentifie le service appelant (par ex. "checkout-service")
audDoit être exactement "zonos-auth"
expHorodatage Unix ; 60–300 secondes après iat
iatHorodatage Unix d'émission
jtiUUID unique par assertion (permet la détection de rejeu)

L'en-tête JWT doit spécifier "alg": "RS256" et "typ": "JWT".

Exemples de code 

1import jwt, uuid, time
2 
3with open("private_key.pem") as f:
4 private_key = f.read()
5 
6now = int(time.time())
7assertion = jwt.encode(
8 {
9 "iss": "org_abc123",
10 "sub": "checkout-service",
11 "aud": "zonos-auth",
12 "iat": now,
13 "exp": now + 300,
14 "jti": str(uuid.uuid4()),
15 },
16 private_key,
17 algorithm="RS256",
18)

Envoyez le JWT signé au point de terminaison de jeton Zonos pour recevoir un jeton Bearer à courte durée de vie.

Point de terminaison 

POST https://auth.zonos.com/oauth/token
Content-Type: application/json

application/x-www-form-urlencoded est également accepté.

Champs de requête 

ChampRequisValue
grant_typeOui"urn:ietf:params:oauth:grant-type:jwt-bearer"
assertionOuiVotre JWT signé (sérialisation compacte)

Requête et réponse 

1{
2 "grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer",
3 "assertion": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."
4}
Champ de réponseDescription
access_tokenJeton Bearer pour toutes les requêtes API suivantes
token_typeToujours "Bearer"
expires_inSecondes avant expiration (par défaut : 300)
scopePermissions séparées par des espaces accordées à ce jeton

Exemples de code complets 

1import requests
2 
3response = requests.post(
4 "https://auth.zonos.com/oauth/token",
5 json={
6 "grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer",
7 "assertion": assertion,
8 },
9)
10data = response.json()
11access_token = data["access_token"]
12expires_in = data["expires_in"]

Incluez le jeton d'accès comme jeton Bearer dans l'en-tête Authorization sur chaque requête API Zonos.

Exemple de requête 

1curl -X POST https://api.zonos.com/graphql \
2 -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..." \
3 -H "Content-Type: application/json" \
4 -d '{ "query": "{ ... }" }'

Cycle de vie et mise en cache des jetons 

Les jetons d'accès expirent par défaut après 5 minutes. Mettez le jeton en cache et actualisez de manière proactive — ne demandez pas un nouveau jeton à chaque appel API. Chaque actualisation nécessite une nouvelle assertion JWT signée.

1import time, requests
2 
3_cache = {"access_token": None, "expires_at": 0}
4 
5def get_access_token():
6 if time.time() < _cache["expires_at"] - 30:
7 return _cache["access_token"]
8 
9 assertion = build_jwt_assertion()
10 data = requests.post(
11 "https://auth.zonos.com/oauth/token",
12 json={
13 "grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer",
14 "assertion": assertion,
15 },
16 ).json()
17 
18 _cache["access_token"] = data["access_token"]
19 _cache["expires_at"] = time.time() + data["expires_in"]
20 return _cache["access_token"]

Référence des erreurs 

Toutes les erreurs suivent le format de réponse d'erreur OAuth 2.0 (RFC 6749 §5.2) :

1{
2 "error": "invalid_grant",
3 "error_description": "JWT assertion has expired"
4}
Statut HTTPerrorCause
400unsupported_grant_typegrant_type was not urn:ietf:params:oauth:grant-type:jwt-bearer
400invalid_requestMissing or malformed field
401invalid_grantInvalid signature, expired assertion, unknown org, or unregistered key
500server_errorInternal error — contact Zonos support if persistent

Causes courantes de invalid_grant :

  • exp est dans le passé — assurez-vous que l'horloge système est synchronisée NTP
  • aud n'est pas exactement "zonos-auth"
  • iss ne correspond pas à votre Organization ID enregistré
  • La clé publique a été renouvelée mais pas encore mise à jour auprès de Zonos

Bonnes pratiques de sécurité 

  • Protégez votre clé privée. Stockez-la dans un gestionnaire de secrets dédié — jamais dans le contrôle de source, les variables d'environnement ou les journaux.
  • Gardez les assertions à courte durée de vie. 60–300 secondes est la norme ; il n'y a aucune raison d'en émettre de plus longues.
  • Incluez jti. Une valeur unique par assertion permet la détection de rejeu côté serveur.
  • Renouvelez les paires de clés périodiquement. Enregistrez une nouvelle clé publique auprès de Zonos avant de révoquer l'ancienne pour éviter les interruptions.
  • Ne journalisez jamais les valeurs access_token ou assertion. Traitez les deux comme des identifiants.

Cette page a-t-elle été utile?