認證與金鑰
每個 /v1 端點都要帶金鑰。金鑰決定哪一家商店、哪一個應用程式、可以做哪些事。商店身分由金鑰推導,請求裡無從指定。
帶上 Bearer 標頭
金鑰放在 Authorization 標頭。
curl -sS https://api.sfec.cloud/v1/me \
-H "Authorization: Bearer $SFAPP_KEY"
標頭格式是 Bearer、一個半形空白、金鑰本體。Bearer 大小寫不拘。前後多餘的空白、兩個以上的空白都回 401。查詢字串與請求內文不接受金鑰。
讀金鑰格式
sfapp_live_ab12cd34_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
└────┬───┘ └──┬───┘ └──────────────┬──────────────┘
固定前綴 key_id(8 碼) 祕密段(32 碼)
| 段落 | 內容 | 可否外流 |
|---|---|---|
sfapp_live_ |
固定前綴 | 可 |
key_id |
8 碼小寫英數,例 ab12cd34 |
可,適合寫進日誌 |
| 祕密段 | 32 碼英數,發放當下給一次 | 否 |
矽羽只保存整串金鑰的雜湊與 key_id,祕密段無法還原。金鑰遺失時撤銷舊的、重發一把新的。
日誌與錯誤回報記 key_id 就足以指認是哪一把。向矽羽申請撤銷時也用 key_id 指名。
對照權限與端點
一把金鑰帶固定的權限範圍(scope),發放後無法自行擴充。
| 權限範圍 | 對應端點 |
|---|---|
read_blog |
GET /v1/blog/posts、GET /v1/blog/posts/{id}、GET /v1/blog/categories |
write_blog |
POST /v1/blog/posts、PATCH /v1/blog/posts/{id}、DELETE /v1/blog/posts/{id}、POST /v1/blog/categories |
publish_blog |
POST /v1/blog/posts/{id}/publish、POST /v1/blog/posts/{id}/unpublish |
write_media |
POST /v1/media/images、DELETE /v1/media/images/{id} |
read_audit |
GET /v1/audit/events |
write_blog 隱含 read_blog。publish_blog 要單獨申請,只有 write_blog 的金鑰寫得了草稿、動不了線上內容。
GET /v1/me 接受任一把有效金鑰。回應的 scopes 是這把金鑰展開隱含關係後的實際清單。
盯住到期日
金鑰預設 365 天到期。到期時間看 GET /v1/me 的 key_expires_at(ISO 8601 含時區),沒有設定到期日時是 null。
{
"scopes": ["read_blog", "write_blog"],
"key_expires_at": "2027-09-14T00:00:00+08:00"
}
過期的金鑰回 401 unauthorized,回應與輸錯金鑰相同。到期前沒有預告。把 key_expires_at 讀進監控,到期前自行提醒換新。
輪替金鑰
同一個應用程式可以同時有兩把有效金鑰,換金鑰不必停機。輪替步驟:
- 向矽羽申請第二把金鑰,權限與舊的相同。
- 把新金鑰部署上線。
- 以
GET /v1/audit/events或自己的記錄確認新金鑰在用。 - 請矽羽撤銷舊金鑰。
先撤銷再換會讓整合在中間那段時間全部回 401。
輪替的時機:
- 每年一次。
- 負責串接的人員異動。
- 金鑰可能外流。
- 金鑰貼進共享空間。
撤銷金鑰
懷疑金鑰外流就聯絡矽羽撤銷。撤銷即時生效,被撤銷的金鑰之後一律回 401。撤銷不影響已寫入的資料,也不影響同一個應用程式的其他金鑰。
聯絡時提供 key_id,完整金鑰留在自己手上。
保管金鑰
- 金鑰只放環境變數或密碼管理器,版本控制與設定檔裡留空。
- 金鑰留在伺服器端。前端程式碼、瀏覽器、手機應用程式都在顧客拿得到的範圍內。
- 交接用密碼管理器分享,不用聊天室、工單或截圖。
- 一個用途一把金鑰:排程一把、代理程式一把、手動測試一把。出事時撤銷那一把。
- 只需要讀的整合就只發
read_blog。 - 日誌與錯誤回報只記
key_id。
分辨 401 與 403
401 代表金鑰無效,403 代表金鑰有效、權限不足。
401 unauthorized |
403 insufficient_scope |
|
|---|---|---|
| 常見原因 | 沒帶 Authorization、格式不符、金鑰打錯、已過期、已撤銷 |
金鑰缺少這支端點需要的權限範圍 |
| 處理動作 | 檢查標頭格式與金鑰是否仍有效 | 依 error.details 所列權限向矽羽申請 |
details 內容 |
不列欄位 | 每筆的 field 是 scope,issue 是 required: 加權限名 |
| 可否重試 | 否,原樣重送結果相同 | 否,原樣重送結果相同 |
403 的回應指名缺哪一個權限:
{
"error": {
"code": "insufficient_scope",
"message": "這把金鑰的權限不足,請向矽羽申請 details 所列的 scope 後再試。",
"details": [{ "field": "scope", "issue": "required: publish_blog" }],
"request_id": "req_k4m2p7q9r3s5t8v6w2x4y7z3",
"retryable": false
}
}