開發人員
SSO·SCIM 串接規格
OIDC、SAML 2.0、SCIM 2.0 串接所需的值與行為規格。
畫面設定步驟請參考 SSO 與 SCIM。
表格中的 {API} 是你所用環境的 Keural API 位址(例如 https://api.keural.ai)。實際值請使用 組織管理 → SSO 設定 畫面上顯示的位址。
登錄值彙整
| 項目 | 值 |
|---|---|
| OIDC 重新導向 URI | {API}/api/sso/callback |
| OIDC·SAML 登入起始 | {API}/api/sso/{orgId}/login |
| SAML SP EntityID | {API}/api/sso/saml/metadata |
| SAML ACS URL | {API}/api/sso/saml/callback |
| SCIM Base URL | {API}/scim/v2 |
登入一律從 Keural 開始(SP-initiated)。在登入畫面輸入已登錄網域的電子郵件後,會移至登入起始位址。成功時回到 Keural 首頁,失敗時移至 /login?error=sso。
OIDC
| 項目 | 行為 |
|---|---|
| 流程 | Authorization Code |
| authorize 請求 | response_type=code、client_id、redirect_uri、scope=openid email profile、state、nonce |
| state · nonce | 一次性使用,有效期 10 分鐘。登入視窗開啟超過 10 分鐘,則需從頭重新登入。 |
| 權杖交換 | 向 token endpoint 送出 POST,application/x-www-form-urlencoded。用戶端驗證為 client_secret_post(本文包含 client_id 與 client_secret)。 |
| ID 權杖簽章 | 只接受 RS256。金鑰以 kid 從 jwks_uri 查找。 |
| ID 權杖驗證 | 簽章、exp、aud 包含 client_id、nonce 相符、iss 與 Issuer URL 相符(忽略結尾的 /) |
| 電子郵件 | ID 權杖中的 email 宣告。若沒有,則以 Authorization: Bearer <access_token> 呼叫 userinfo endpoint 讀取 email。 |
| 名稱 | ID 權杖中的 name 宣告 |
| 端點 | 從 Issuer URL 的 /.well-known/openid-configuration 查找。找不到時,請在 開啟進階設定 中直接輸入 authorization、token、JWKS 與 userinfo 位址。 |
| 時間限制 | 每次呼叫 IdP 為 15 秒 |
IdP 應用程式必須允許 client_secret_post。若只允許 client_secret_basic 或 private_key_jwt,權杖交換會失敗。
SAML 2.0
| 項目 | 行為 |
|---|---|
| 請求 | 以 HTTP-Redirect 繫結送出 AuthnRequest。請求不簽章。 |
| 請求內容 | Destination=IdP SSO URL、AssertionConsumerServiceURL=ACS URL、ProtocolBinding=HTTP-POST、Issuer=SP EntityID、NameIDPolicy Format=…:nameid-format:unspecified、AllowCreate=true |
| 回應 | HTTP-POST 繫結,包含 SAMLResponse 與 RelayState。RelayState 必須原樣傳回 Keural 送出的值。 |
| 簽章 | Response 或 Assertion 其中之一必須有有效簽章。驗證只使用畫面上登錄的憑證。 |
| 斷言(Assertion) | 回應中必須恰好有一個 Assertion。不接受加密的 Assertion(EncryptedAssertion)。 |
| 狀態 | StatusCode 為 urn:oasis:names:tc:SAML:2.0:status:Success |
| Issuer | 若填入了 IdP EntityID,必須與 Assertion 的 Issuer 相符。 |
| 條件 | NotBefore、NotOnOrAfter(容許誤差 300 秒)、Audience=SP EntityID |
| SubjectConfirmationData | Recipient=ACS URL、NotOnOrAfter(容許誤差 300 秒)、InResponseTo=Keural 送出的請求 ID |
| 電子郵件 | 屬性的 Name 或 FriendlyName 為下列其中之一(不區分大小寫):email、mail、emailAddress、E-Mail-Addresses、http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress。若都沒有,則使用含有 @ 的 NameID。 |
| 名稱 | displayName、name、cn、http://schemas.microsoft.com/identity/claims/displayname |
| 憑證 | 一個 X.509 憑證,PEM 或 Base64(DER)格式。更換時,請輸入新的憑證並儲存。 |
| 中繼資料 | 不上傳 IdP 中繼資料 XML,改為輸入 IdP EntityID、IdP SSO URL 與憑證三個值。 |
使用者判定
| 項目 | 行為 |
|---|---|
| 導向 SSO 的條件 | 電子郵件 @ 之後的部分與 電子郵件網域 清單中的某一項完全相同(不區分大小寫)。子網域需另外登錄。 |
| 尋找帳號 | 以 IdP 回傳的電子郵件(小寫)尋找 Keural 帳號。 |
| 沒有帳號時 | 若 首次登入時自動建立使用者(JIT)已開啟,則建立帳號;若關閉,則拒絕登入。 |
| 加入組織 | 若不是組織成員,則以 成員 身分加入。座位已滿或屬於其他組織的帳號不會加入,僅能登入。 |
| 儲存電子郵件網域的條件 | 以 DNS TXT 驗證的網域。排除公開電子郵件網域。 |
網域驗證
| 項目 | 值 |
|---|---|
| 記錄類型 | TXT |
| 主機 | 按登錄時的網域原樣填寫(例如 acme.com)。不要使用前綴子網域。 |
| 值 | keural-verify=<UUID>,與畫面上顯示的值完全相同 |
| 檢查時機 | 按下 確認驗證 時查詢一次。 |
SCIM 2.0
| 項目 | 值 |
|---|---|
| Base URL | {API}/scim/v2 |
| 驗證 | Authorization: Bearer <SCIM 權杖>。權杖以 scim_ 開頭,發行時只會顯示一次。 |
| Content-Type | 請求為 application/scim+json 或 application/json,回應為 application/scim+json |
| 狀態碼 | 以實際的 HTTP 狀態碼回傳。錯誤內文採 SCIM Error 格式(schemas、status、detail、scimType)。 |
端點
| 方法 | 路徑 | 行為 |
|---|---|---|
GET | /Users | 清單。filter=userName eq "…"、startIndex(預設 1)、count(預設 100,最多 200) |
GET | /Users/{id} | 查詢一位使用者 |
POST | /Users | 建立(201)。若已有相同電子郵件,回傳 409 |
PATCH | /Users/{id} | 變更 active、displayName、name.formatted、name.givenName |
PUT | /Users/{id} | 套用 displayName、name、active。省略 active 時視為啟用。 |
DELETE | /Users/{id} | 停用帳號(204)。不刪除資料。 |
GET | /Groups、/Groups/{id} | 查詢兩個固定群組。filter=displayName eq "…" |
PATCH | /Groups/{id} | 新增、移除或取代成員 |
GET | /ServiceProviderConfig、/ResourceTypes、/Schemas | 查詢支援的功能 |
使用者屬性
| 屬性 | 用途 |
|---|---|
userName | 電子郵件。若沒有,則使用 emails[0].value。 |
displayName · name.formatted · name.givenName+name.familyName | 顯示名稱 |
active | false 為停用(阻擋登入),true 為復原 |
id | Keural 使用者 ID。包含在回應中。 |
不儲存 externalId。在 IdP 中查找使用者時,請使用 userName 過濾條件。
群組
| id | displayName | 加入成員時 | 移除成員時 |
|---|---|---|---|
keural-admins | Keural Admins | 管理員 | 成員 |
keural-members | Keural Members | 成員 | 不變 |
組織擁有者的角色不會因 SCIM 而變更。建立或刪除群組(POST、DELETE /Groups)會回傳 501。群組成員的 value 為 Keural 使用者 ID(/Users 中的 id)。
支援範圍
| 功能 | 支援 |
|---|---|
| PATCH | 是 |
| 過濾條件 | userName eq、displayName eq |
| Bulk · 排序 · ETag · 變更密碼 | 否 |
錯誤
| 狀態 | scimType | 原因 |
|---|---|---|
400 | invalidValue | userName 與 emails 都不存在 |
401 | — | 權杖不存在或不正確,或 SCIM 佈建已關閉 |
404 | — | 不屬於此組織的使用者或群組 |
409 | uniqueness | 已有相同電子郵件的帳號,或超過座位數 |
501 | — | 建立或刪除群組 |