DOCS

OAuth 2.0-Authentifizierung

OAuth 2.0-Authentifizierung

Authentifizieren Sie Ihre Backend-Services bei Zonos mit asymmetrischer Schlüsselkryptografie — ohne gemeinsame Geheimnisse.

Zonos unterstützt Machine-to-Machine-Authentifizierung über OAuth 2.0 JWT Bearer Token Grant (RFC 7523). Ihr Service signiert ein kurzlebiges JWT mit Ihrem RSA-Privatschlüssel; Zonos verifiziert es mit Ihrem registrierten öffentlichen Schlüssel und gibt ein Bearer-Token zurück, das auf Ihre Organisation beschränkt ist.

Ablaufübersicht:

  1. Generieren Sie ein RSA-Schlüsselpaar und registrieren Sie Ihren öffentlichen Schlüssel bei Zonos.
  2. Signieren Sie zur Laufzeit eine JWT-Assertion mit Ihrem Privatschlüssel und senden Sie sie per POST an den Token-Endpunkt.
  3. Zonos gibt ein kurzlebiges Access Token zurück.
  4. Fügen Sie das Access Token als Authorization: Bearer <token> bei jeder API-Anfrage hinzu.

Generieren Sie ein 4096-Bit-RSA-Schlüsselpaar und teilen Sie den öffentlichen Schlüssel mit Zonos. Dies erfolgt einmalig während des Onboardings.

Schlüsselpaar generieren 

Teilen Sie public_key.pem mit Zonos. Speichern Sie private_key.pem in einem dedizierten Secrets Manager (AWS Secrets Manager, HashiCorp Vault usw.) — niemals in der Quellcodeverwaltung oder in Umgebungsvariablen.

Zonos registriert Ihren Schlüssel und gibt Ihre Organization ID zurück, die zum iss-Claim in allen JWT-Assertions wird.

Signieren Sie ein JWT mit RS256 unter Verwendung Ihres Privatschlüssels. Die Assertion ist für einen einzelnen Token-Austausch gültig — halten Sie das Ablauffenster kurz (60–300 Sekunden).

Erforderliche Claims 

ClaimValue
issYour Zonos Organization ID (e.g. "org_abc123")
subIdentifies the calling service (e.g. "checkout-service")
audMust be exactly "zonos-auth"
expUnix timestamp; 60–300 seconds from iat
iatUnix timestamp of issuance
jtiUnique UUID per assertion (enables replay detection)

Der JWT-Header muss "alg": "RS256" und "typ": "JWT" angeben.

Codebeispiele 

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)

Senden Sie das signierte JWT an den Zonos-Token-Endpunkt, um ein kurzlebiges Bearer-Token zu erhalten.

Endpunkt 

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

application/x-www-form-urlencoded wird ebenfalls akzeptiert.

Anfragefelder 

FieldRequiredValue
grant_typeYes"urn:ietf:params:oauth:grant-type:jwt-bearer"
assertionYesYour signed JWT (compact serialization)

Anfrage und Antwort 

1{
2 "grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer",
3 "assertion": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."
4}
Response fieldDescription
access_tokenBearer token for all subsequent API requests
token_typeAlways "Bearer"
expires_inSeconds until expiry (default: 300)
scopeSpace-separated permissions granted to this token

Vollständige Codebeispiele 

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"]

Fügen Sie das Access Token als Bearer-Token im Authorization-Header bei jeder Zonos-API-Anfrage hinzu.

Beispielanfrage 

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

Token-Lebenszyklus und Caching 

Access Tokens laufen standardmäßig nach 5 Minuten ab. Cachen Sie das Token und erneuern Sie es proaktiv — fordern Sie nicht bei jedem API-Aufruf ein neues Token an. Jede Erneuerung erfordert eine neu signierte JWT-Assertion.

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"]

Fehlerreferenz 

Alle Fehler folgen dem OAuth 2.0-Fehlerantwortformat (RFC 6749 §5.2):

1{
2 "error": "invalid_grant",
3 "error_description": "JWT assertion has expired"
4}
HTTP StatuserrorCause
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

Häufige Ursachen für invalid_grant:

  • exp liegt in der Vergangenheit — stellen Sie sicher, dass Ihre Systemuhr NTP-synchronisiert ist
  • aud ist nicht exakt "zonos-auth"
  • iss stimmt nicht mit Ihrer registrierten Organization ID überein
  • Öffentlicher Schlüssel wurde rotiert, aber noch nicht bei Zonos aktualisiert

Sicherheits-Best Practices 

  • Schützen Sie Ihren Privatschlüssel. Speichern Sie ihn in einem dedizierten Secrets Manager — niemals in der Quellcodeverwaltung, Umgebungsvariablen oder Logs.
  • Halten Sie Assertions kurzlebig. 60–300 Sekunden sind Standard; es gibt keinen Grund, längere auszustellen.
  • Fügen Sie jti hinzu. Ein eindeutiger Wert pro Assertion ermöglicht serverseitige Replay-Erkennung.
  • Rotieren Sie Schlüsselpaare regelmäßig. Registrieren Sie einen neuen öffentlichen Schlüssel bei Zonos, bevor Sie den alten widerrufen, um Ausfallzeiten zu vermeiden.
  • Protokollieren Sie niemals access_token- oder assertion-Werte. Behandeln Sie beides als Anmeldedaten.

War diese Seite hilfreich?