Langkah 1 — Daftarkan kunci publik Anda (pengaturan satu kali)
Buat pasangan kunci RSA 4096-bit dan bagikan kunci publik dengan Zonos. Ini dilakukan sekali selama onboarding.
Buat pasangan kunci
# Generate private keyopenssl genrsa -out private_key.pem 4096 openssl rsa - private_key.pem -pubout -out public_key.pemBagikan public_key.pem dengan Zonos. Simpan private_key.pem di pengelola rahasia khusus (AWS Secrets Manager, HashiCorp Vault, dll.) — tidak pernah di kontrol sumber atau variabel lingkungan.
Zonos akan mendaftarkan kunci Anda dan mengembalikan ID Organisasi Anda, yang menjadi klaim iss di semua asersi JWT.
Langkah 2 — Bangun asersi JWT
Tandatangani JWT dengan RS256 menggunakan kunci privat Anda. Asersi berlaku untuk pertukaran token tunggal — jaga jendela kedaluwarsa tetap pendek (60–300 detik).
Klaim yang diperlukan
| Claim↕ | Nilai↕ |
|---|---|
iss | ID Organisasi Zonos Anda (mis. "org_abc123") |
sub | Mengidentifikasi layanan pemanggil (mis. "checkout-service") |
aud | Harus persis "zonos-auth" |
exp | Stempel waktu Unix; 60–300 detik dari iat |
iat | Stempel waktu Unix dari penerbitan |
jti | UUID unik per asersi (memungkinkan deteksi putar ulang) |
Tajuk JWT harus menentukan "alg": "RS256" dan "typ": "JWT".
Contoh kode
import jwt, uuid, time with open("private_key.pem") as f: private_key = f.read() now = int(time.time())assertion = jwt.encode( { "iss": "org_abc123", "sub": "checkout-service", "aud": "zonos-auth", "iat": now, "exp": now + 300, "jti": str(uuid.uuid4()), }, private_key, algorithm="RS256",)Langkah 3 — Tukar asersi untuk token akses
Kirim JWT yang ditandatangani ke titik akhir token Zonos untuk menerima token Bearer berumur pendek.
Titik akhir
POST https://auth.zonos.com/oauth/token
Content-Type: application/json
application/x-www-form-urlencoded juga diterima.
Bidang permintaan
| Bidang↕ | Diperlukan↕ | Nilai↕ |
|---|---|---|
grant_type | Ya | "urn:ietf:params:oauth:grant-type:jwt-bearer" |
assertion | Ya | JWT yang ditandatangani (serialisasi kompak) |
Permintaan dan respons
{ "grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer", "assertion": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."}| Bidang respons↕ | Deskripsi↕ |
|---|---|
access_token | Token Bearer untuk semua permintaan API berikutnya |
token_type | Selalu "Bearer" |
expires_in | Detik sampai kedaluwarsa (default: 300) |
scope | Izin yang dipisahkan spasi diberikan ke token ini |
Contoh kode lengkap
import requests response = requests.post( "https://auth.zonos.com/oauth/token", json={ "grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer", "assertion": assertion, },)data = response.json()access_token = data["access_token"]expires_in = data["expires_in"]Langkah 4 — Panggil API Zonos dengan token akses
Sertakan token akses sebagai token Bearer di header Authorization pada setiap permintaan API Zonos.
Contoh permintaan
curl -X POST https://api.zonos.com/graphql \ -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..." \ -H "Content-Type: application/json" \ -d '{ "query": "{ ... }" }'Siklus hidup token dan caching
Token akses berakhir dalam 5 menit secara default. Cache token dan segarkan secara proaktif — jangan minta token baru pada setiap panggilan API. Setiap penyegaran memerlukan asersi JWT yang baru ditandatangani.
import time, requests _cache = {"access_token": None, "expires_at": 0} def get_access_token(): if time.time() < _cache["expires_at"] - 30: return _cache["access_token"] assertion = build_jwt_assertion() data = requests.post( "https://auth.zonos.com/oauth/token", json={ "grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer", "assertion": assertion, }, ).json() _cache["access_token"] = data["access_token"] _cache["expires_at"] = time.time() + data["expires_in"] return _cache["access_token"]Referensi kesalahan
Semua kesalahan mengikuti format respons kesalahan OAuth 2.0 (RFC 6749 §5.2):
{ "error": "invalid_grant", "error_description": "JWT assertion has expired"}| HTTP Status↕ | error↕ | Penyebab↕ |
|---|---|---|
400 | unsupported_grant_type | grant_type bukan urn:ietf:params:oauth:grant-type:jwt-bearer |
400 | invalid_request | Bidang yang hilang atau salah bentuk |
401 | invalid_grant | Tanda tangan tidak valid, asersi kedaluwarsa, organisasi tidak dikenal, atau kunci tidak terdaftar |
500 | server_error | Kesalahan internal — hubungi dukungan Zonos jika berlanjut |
Penyebab umum invalid_grant:
expberada di masa lalu — pastikan jam sistem Anda tersinkronisasi NTPaudbukan persis"zonos-auth"isstidak cocok dengan ID Organisasi terdaftar Anda- Kunci publik diputar tetapi belum diperbarui dengan Zonos
Praktik terbaik keamanan
- Lindungi kunci privat Anda. Simpan di pengelola rahasia khusus — tidak pernah di kontrol sumber, variabel lingkungan, atau log.
- Jaga asersi tetap berumur pendek. 60–300 detik adalah standar; tidak ada alasan untuk mengeluarkan yang lebih lama.
- Sertakan
jti. Nilai unik per asersi memungkinkan deteksi putar ulang sisi server. - Putar pasangan kunci secara berkala. Daftarkan kunci publik baru dengan Zonos sebelum mencabut yang lama untuk menghindari downtime.
- Jangan pernah log
access_tokenatau nilaiassertion. Perlakukan keduanya sebagai kredensial.
Autentikasi OAuth 2.0
Autentikasi layanan backend Anda dengan Zonos menggunakan kriptografi kunci asimetris — tanpa rahasia bersama.
Zonos mendukung autentikasi mesin-ke-mesin melalui OAuth 2.0 JWT Bearer Token Grant (RFC 7523). Layanan Anda menandatangani JWT berumur pendek dengan kunci privat RSA Anda; Zonos memverifikasinya menggunakan kunci publik terdaftar Anda dan mengembalikan token Bearer yang dibatasi ruang lingkup untuk organisasi Anda.
Ringkasan alur:
Authorization: Bearer <token>pada setiap permintaan API.