DOCS

Autentikasi OAuth 2.0

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:

  1. Buat pasangan kunci RSA dan daftarkan kunci publik Anda dengan Zonos.
  2. Pada saat runtime, tandatangani asersi JWT dengan kunci privat Anda dan POSTkan ke titik akhir token.
  3. Zonos mengembalikan token akses berumur pendek.
  4. Sertakan token akses sebagai Authorization: Bearer <token> pada setiap permintaan API.

Buat pasangan kunci RSA 4096-bit dan bagikan kunci publik dengan Zonos. Ini dilakukan sekali selama onboarding.

Buat pasangan kunci 

1# Generate private key
2openssl genrsa -out private_key.pem 4096
3 
4 
5openssl rsa - private_key.pem -pubout -out public_key.pem

Bagikan 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.

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 

ClaimNilai
issID Organisasi Zonos Anda (mis. "org_abc123")
subMengidentifikasi layanan pemanggil (mis. "checkout-service")
audHarus persis "zonos-auth"
expStempel waktu Unix; 60–300 detik dari iat
iatStempel waktu Unix dari penerbitan
jtiUUID unik per asersi (memungkinkan deteksi putar ulang)

Tajuk JWT harus menentukan "alg": "RS256" dan "typ": "JWT".

Contoh kode 

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)

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 

BidangDiperlukanNilai
grant_typeYa"urn:ietf:params:oauth:grant-type:jwt-bearer"
assertionYaJWT yang ditandatangani (serialisasi kompak)

Permintaan dan respons 

1{
2 "grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer",
3 "assertion": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."
4}
Bidang responsDeskripsi
access_tokenToken Bearer untuk semua permintaan API berikutnya
token_typeSelalu "Bearer"
expires_inDetik sampai kedaluwarsa (default: 300)
scopeIzin yang dipisahkan spasi diberikan ke token ini

Contoh kode lengkap 

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

Sertakan token akses sebagai token Bearer di header Authorization pada setiap permintaan API Zonos.

Contoh permintaan 

1curl -X POST https://api.zonos.com/graphql \
2 -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..." \
3 -H "Content-Type: application/json" \
4 -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.

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

Referensi kesalahan 

Semua kesalahan mengikuti format respons kesalahan OAuth 2.0 (RFC 6749 §5.2):

1{
2 "error": "invalid_grant",
3 "error_description": "JWT assertion has expired"
4}
HTTP StatuserrorPenyebab
400unsupported_grant_typegrant_type bukan urn:ietf:params:oauth:grant-type:jwt-bearer
400invalid_requestBidang yang hilang atau salah bentuk
401invalid_grantTanda tangan tidak valid, asersi kedaluwarsa, organisasi tidak dikenal, atau kunci tidak terdaftar
500server_errorKesalahan internal — hubungi dukungan Zonos jika berlanjut

Penyebab umum invalid_grant:

  • exp berada di masa lalu — pastikan jam sistem Anda tersinkronisasi NTP
  • aud bukan persis "zonos-auth"
  • iss tidak 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_token atau nilai assertion. Perlakukan keduanya sebagai kredensial.
Pesan demo

Apakah halaman ini bermanfaat?