DOCS

OAuth 2.0 驗證

OAuth 2.0 驗證

使用非對稱金鑰密碼術向 Zonos 驗證您的後端服務 — 無需共享祕密。

Zonos 支援透過 OAuth 2.0 JWT Bearer Token Grant (RFC 7523) 的機器對機器驗證。您的服務使用您的 RSA 私鑰簽署短期 JWT;Zonos 使用您註冊的公鑰驗證它,並返回範圍限於您組織的 Bearer 令牌。

流程摘要:

  1. 生成 RSA 金鑰對,並向 Zonos 註冊您的公鑰
  2. 在執行時,使用您的私鑰簽署 JWT 宣告,並將其 POST 到令牌端點。
  3. Zonos 返回短期存取令牌
  4. 在每個 API 請求上包含存取令牌作為 Authorization: Bearer <token>

生成 4096 位元 RSA 金鑰對,並與 Zonos 分享公鑰。這在上線期間執行一次。

生成金鑰對

1# 生成私鑰
2openssl genrsa -out private_key.pem 4096
3 
4# 提取公鑰
5openssl rsa -in private_key.pem -pubout -out public_key.pem

與 Zonos 分享 public_key.pem。將 private_key.pem 儲存在專用祕密管理器中(AWS Secrets Manager、HashiCorp Vault 等)— 不要在原始碼管理或環境變數中。

Zonos 將註冊您的金鑰,並返回您的組織 ID,這將成為所有 JWT 宣告中的 iss 聲明。

使用您的私鑰以 RS256 簽署 JWT。宣告對單次令牌交換有效 — 保持有效期窗口較短(60–300 秒)。

必需的聲明

聲明
iss您的 Zonos 組織 ID(例如 "org_abc123"
sub識別呼叫服務(例如 "checkout-service")
aud必須是 "zonos-auth"
expUnix 時間戳;iat 後的 60–300 秒
iat發佈的 Unix 時間戳
jti每個宣告的唯一 UUID(啟用重播偵測)

JWT 標頭必須指定 "alg": "RS256""typ": "JWT"

程式碼範例

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)

將簽署的 JWT 發送至 Zonos 令牌端點以接收短期 Bearer 令牌。

端點

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

也接受 application/x-www-form-urlencoded

請求欄位

欄位必需
grant_typeYes"urn:ietf:params:oauth:grant-type:jwt-bearer"
assertionYes您簽署的 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授予此令牌的空格分隔權限

完整程式碼範例

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

Authorization 標頭中將存取令牌作為 Bearer 令牌包含在每個 Zonos API 請求上。

範例請求

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

令牌生命週期和快取 

存取令牌預設在 5 分鐘後到期。快取令牌並主動刷新 — 不要在每個 API 呼叫上要求新令牌。每次刷新都需要新簽署的 JWT 宣告。

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

錯誤參考 

所有錯誤都遵循 OAuth 2.0 錯誤回應格式 (RFC 6749 §5.2):

1{
2 "error": "invalid_grant",
3 "error_description": "JWT assertion has expired"
4}
HTTP 狀態error原因
400unsupported_grant_typegrant_type 不是 urn:ietf:params:oauth:grant-type:jwt-bearer
400invalid_request遺漏或格式不正確的欄位
401invalid_grant無效的簽名、過期的宣告、未知的組織或未註冊的金鑰
500server_error內部錯誤 — 如果持續存在,請聯絡 Zonos 支援

常見 invalid_grant 原因:

  • exp 在過去 — 確保您的系統時鐘是 NTP 同步的
  • aud 不是 "zonos-auth"
  • iss 與您註冊的組織 ID 不相符
  • 公鑰已輪換但尚未與 Zonos 更新

安全最佳實踐 

  • 保護您的私鑰。 將其儲存在專用祕密管理器中 — 永遠不要在原始碼管理、環境變數或日誌中。
  • 保持宣告短期。 60–300 秒是標準的;沒有理由發佈更長的宣告。
  • 包含 jti 每個宣告的唯一值可啟用伺服器端重播偵測。
  • 定期輪換金鑰對。 在撤銷舊金鑰之前向 Zonos 註冊新公鑰以避免停機。
  • 永遠不要記錄 access_tokenassertion 值。 將兩者視為認證。
Book a demo

Was this page helpful?


在此頁面: