步驟 1——註冊您的公鑰(一次性設定)
生成 4096 位 RSA 金鑰對,並與 Zonos 共享公鑰。這在上線期間進行一次。
生成金鑰對
1
# 生成私鑰2
openssl genrsa -out private_key.pem 40963
4
# 提取公鑰5
openssl rsa -in private_key.pem -pubout -out public_key.pem與 Zonos 共享 public_key.pem。將 private_key.pem 存儲在專用密鑰管理器中(AWS Secrets Manager、HashiCorp Vault 等)——絕不要放在原始碼管理或環境變數中。
Zonos 將註冊您的金鑰並返回您的組織 ID,該 ID 將成為所有 JWT 聲明中的 iss 聲明。
步驟 2——構建 JWT 聲明
使用私鑰以 RS256 簽署 JWT。該聲明對單個令牌交換有效——保持到期視窗短(60–300 秒)。
必需聲明
| 聲明↕ | 值↕ |
|---|---|
iss | 您的 Zonos 組織 ID(例如 "org_abc123") |
sub | 識別調用服務(例如 "checkout-service") |
aud | 必須恰好為 "zonos-auth" |
exp | Unix 時間戳;從 iat 之後的 60–300 秒 |
iat | 發行時間的 Unix 時間戳 |
jti | 每個聲明的唯一 UUID(啟用重放檢測) |
JWT 標題必須指定 "alg": "RS256" 和 "typ": "JWT"。
代碼範例
1
import jwt, uuid, time2
3
with open("private_key.pem") as f:4
private_key = f.read()5
6
now = int(time.time())7
assertion = 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
)步驟 3——交換聲明以獲取訪問令牌
將簽署的 JWT 發送至 Zonos 令牌端點以接收短期有效的 Bearer 令牌。
端點
POST https://auth.zonos.com/oauth/token
Content-Type: application/json
也接受 application/x-www-form-urlencoded。
請求欄位
| 欄位↕ | 必需↕ | 值↕ |
|---|---|---|
grant_type | 是 | "urn:ietf:params:oauth:grant-type:jwt-bearer" |
assertion | 是 | 您簽署的 JWT(緊湊序列化) |
請求和回應
1
{2
"grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer",3
"assertion": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."4
}| 回應欄位↕ | 描述↕ |
|---|---|
access_token | 用於所有後續 API 請求的 Bearer 令牌 |
token_type | 始終為 "Bearer" |
expires_in | 到期前的秒數(預設值:300) |
scope | 授予此令牌的以空格分隔的權限 |
完整代碼範例
1
import requests2
3
response = requests.post(4
"https://auth.zonos.com/oauth/token",5
json={6
"grant_type": ,7
: assertion,8
},9
)10
data = response.json()11
access_token = data[]12
expires_in = data[]步驟 4——使用訪問令牌呼叫 Zonos API
在每個 Zonos API 請求的 Authorization 標題中包含訪問令牌作為 Bearer 令牌。
範例請求
1
curl -X POST https://api.zonos.com/graphql \2
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..." \3
-H "Content-Type: application/json" \4
-d '{ "query": "{ ... }" }'令牌生命週期和緩存
訪問令牌預設在 5 分鐘後過期。緩存令牌並主動刷新——不要在每個 API 呼叫上請求新令牌。每次刷新都需要新簽署的 JWT 聲明。
1
import time, requests2
3
_cache = {"access_token": None, "expires_at": 0}4
5
def 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"]錯誤參考
所有錯誤都遵循 OAuth 2.0 錯誤回應格式 (RFC 6749 §5.2):
1
{2
"error": "invalid_grant",3
"error_description": "JWT assertion has expired"4
}| HTTP 狀態↕ | error↕ | 原因↕ |
|---|---|---|
400 | unsupported_grant_type | grant_type 不是 urn:ietf:params:oauth:grant-type:jwt-bearer |
400 | invalid_request | 缺少或格式錯誤的欄位 |
401 | invalid_grant | 無效簽名、過期聲明、未知組織或未註冊的金鑰 |
500 | server_error | 內部錯誤——如果持續,請聯絡 Zonos 支援 |
常見的 invalid_grant 原因:
exp在過去——確保您的系統時鐘已 NTP 同步aud不恰好為"zonos-auth"iss不匹配您的已註冊組織 ID- 公鑰已輪換但尚未向 Zonos 更新
安全最佳實踐
- 保護您的私鑰。 將其存儲在專用密鑰管理器中——絕不要放在原始碼管理、環境變數或日誌中。
- 保持聲明短期有效。 60–300 秒是標準做法;沒有理由發行更長的。
- 包含
jti。 每個聲明的唯一值啟用伺服器端重放檢測。 - 定期輪換金鑰對。 在撤銷舊金鑰之前向 Zonos 註冊新的公鑰,以避免停機。
- 絕不記錄
access_token或assertion值。 將兩者都視為憑證。
OAuth 2.0 驗證
使用非對稱金鑰密碼學對您的後端服務進行 Zonos 驗證——無需共享密鑰。
Zonos 支持通過 OAuth 2.0 JWT Bearer 令牌授予 (RFC 7523) 進行機器到機器驗證。您的服務使用您的 RSA 私鑰簽署短期有效的 JWT;Zonos 使用您註冊的公鑰驗證該 JWT 並返回一個以您的組織為範圍的 Bearer 令牌。
流程摘要:
Authorization: Bearer <token>。