Spesifikasi integrasi SSO·SCIM
Nilai dan perilaku yang diperlukan untuk integrasi OIDC·SAML 2.0·SCIM 2.0.
Lihat SSO dan SCIM untuk urutan pengaturan di layar.
{API} pada tabel adalah alamat API Keural di lingkungan yang Anda gunakan (contoh: https://api.keural.ai). Gunakan alamat yang ditampilkan di layar Manajemen organisasi → Pengaturan SSO.
Ringkasan nilai pendaftaran
| Item | Nilai |
|---|---|
| URI redirect OIDC | {API}/api/sso/callback |
| Mulai login 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 |
Login selalu dimulai dari Keural (SP-initiated). Saat email dengan domain yang terdaftar dimasukkan di layar login, Anda diarahkan ke alamat mulai login. Jika berhasil, Anda diarahkan ke halaman utama Keural. Jika gagal, Anda diarahkan ke /login?error=sso.
OIDC
| Item | Perilaku |
|---|---|
| Alur | Authorization Code |
| Permintaan authorize | response_type=code, client_id, redirect_uri, scope=openid email profile, state, nonce |
| state · nonce | Sekali pakai dan berlaku 10 menit. Jika jendela login dibiarkan terbuka lebih dari 10 menit, mulai ulang dari awal. |
| Pertukaran token | POST ke token endpoint, application/x-www-form-urlencoded, autentikasi klien client_secret_post (client_id dan client_secret di badan permintaan) |
| Tanda tangan ID token | Hanya menerima RS256. Kunci dicari di jwks_uri berdasarkan kid. |
| Verifikasi ID token | Tanda tangan, exp, aud memuat client_id, nonce cocok, iss sama dengan Issuer URL (garis miring di akhir diabaikan) |
Klaim email di ID token. Jika tidak ada, userinfo endpoint dipanggil dengan Authorization: Bearer <access_token> untuk membaca email. | |
| Nama | Klaim name di ID token |
| Endpoint | Dicari di /.well-known/openid-configuration pada Issuer URL. Untuk IdP yang endpoint-nya tidak dapat ditemukan, masukkan langsung alamat authorization · token · JWKS · userinfo melalui Buka pengaturan lanjutan. |
| Batas waktu | 15 detik untuk setiap panggilan ke IdP |
Aplikasi IdP harus mengizinkan client_secret_post. Jika pengaturannya hanya mengizinkan client_secret_basic atau private_key_jwt, pertukaran token akan gagal.
SAML 2.0
| Item | Perilaku |
|---|---|
| Permintaan | AuthnRequest dikirim dengan binding HTTP-Redirect. Permintaan tidak ditandatangani. |
| Isi permintaan | Destination=IdP SSO URL, AssertionConsumerServiceURL=ACS URL, ProtocolBinding=HTTP-POST, Issuer=SP EntityID, NameIDPolicy Format=…:nameid-format:unspecified, AllowCreate=true |
| Respons | Binding HTTP-POST, berisi SAMLResponse dan RelayState. RelayState harus dikembalikan persis seperti yang dikirim Keural. |
| Tanda tangan | Response atau Assertion harus memiliki tanda tangan yang valid. Kunci verifikasi hanya memakai sertifikat yang didaftarkan di layar. |
| Assertion | Respons harus memuat tepat satu assertion. Assertion terenkripsi (EncryptedAssertion) tidak diterima. |
| Status | StatusCode adalah urn:oasis:names:tc:SAML:2.0:status:Success |
| Issuer | Jika EntityID IdP diisi, harus sama dengan Issuer pada assertion |
| Kondisi | NotBefore dan NotOnOrAfter (toleransi 300 detik), Audience=SP EntityID |
| SubjectConfirmationData | Recipient=ACS URL, NotOnOrAfter (toleransi 300 detik), InResponseTo=ID permintaan yang dikirim Keural |
Atribut Name atau FriendlyName berupa salah satu dari berikut (tidak peka huruf besar/kecil): email, mail, emailAddress, E-Mail-Addresses, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress. Jika tidak ada, NameID yang mengandung @ yang dipakai. | |
| Nama | displayName, name, cn, http://schemas.microsoft.com/identity/claims/displayname |
| Sertifikat | Satu X.509. PEM atau Base64(DER). Saat mengganti sertifikat, masukkan sertifikat baru lalu simpan. |
| Metadata | Alih-alih mengunggah XML metadata IdP, masukkan tiga nilai: IdP EntityID · IdP SSO URL · sertifikat. |
Penentuan pengguna
| Item | Perilaku |
|---|---|
| Kriteria pengalihan ke SSO | Bagian setelah @ pada email sama persis dengan salah satu item daftar domain email (tidak peka huruf besar/kecil). Subdomain didaftarkan terpisah. |
| Mencari akun | Akun Keural dicari berdasarkan email (huruf kecil) yang diberikan IdP. |
| Saat akun tidak ada | Jika pembuatan otomatis pengguna yang belum terdaftar (JIT) aktif, akun dibuat. Jika nonaktif, login ditolak. |
| Bergabung ke organisasi | Jika bukan anggota organisasi, pengguna bergabung sebagai Anggota. Akun yang kursinya penuh atau yang termasuk organisasi lain tidak bergabung dan hanya bisa login. |
| Syarat penyimpanan domain email | Domain yang diverifikasi dengan DNS TXT, kecuali domain email publik |
Verifikasi domain
| Item | Nilai |
|---|---|
| Jenis record | TXT |
| Host | Domain yang didaftarkan apa adanya (contoh: acme.com). Jangan pakai subdomain di depannya. |
| Nilai | keural-verify=<UUID>, nilai persis seperti yang tampil di layar |
| Waktu pemeriksaan | Dicek sekali saat Konfirmasi verifikasi ditekan. |
SCIM 2.0
| Item | Nilai |
|---|---|
| Base URL | {API}/scim/v2 |
| Autentikasi | Authorization: Bearer <token SCIM>. Token diawali scim_ dan hanya ditampilkan sekali saat diterbitkan. |
| Content-Type | Permintaan application/scim+json atau application/json, respons application/scim+json |
| Kode status | Dikembalikan sebagai kode status HTTP yang sebenarnya. Isi galat berformat SCIM Error (schemas, status, detail, scimType). |
Endpoint
| Metode | Path | Perilaku |
|---|---|---|
GET | /Users | Daftar. filter=userName eq "…", startIndex (default 1), count (default 100, maksimum 200) |
GET | /Users/{id} | Mengambil satu pengguna |
POST | /Users | Membuat (201). Jika email yang sama sudah ada, 409. |
PATCH | /Users/{id} | Mengubah active, displayName, name.formatted, name.givenName |
PUT | /Users/{id} | Menerapkan displayName·name·active. Jika active tidak disertakan, dianggap aktif. |
DELETE | /Users/{id} | Menangguhkan akun (204). Data tidak dihapus. |
GET | /Groups, /Groups/{id} | Mengambil dua grup tetap. filter=displayName eq "…" |
PATCH | /Groups/{id} | Menambah, menghapus, atau mengganti anggota |
GET | /ServiceProviderConfig, /ResourceTypes, /Schemas | Melihat fitur yang didukung |
Atribut pengguna
| Atribut | Kegunaan |
|---|---|
userName | Email. Jika tidak ada, emails[0].value dipakai. |
displayName · name.formatted · name.givenName+name.familyName | Nama tampilan |
active | false menangguhkan (login diblokir), true memulihkan |
id | ID pengguna Keural. Dimuat dalam respons. |
externalId tidak disimpan. Untuk mencari pengguna dari IdP, gunakan filter userName.
Grup
| id | displayName | Saat anggota ditambahkan | Saat anggota dihapus |
|---|---|---|---|
keural-admins | Keural Admins | Admin | Anggota |
keural-members | Keural Members | Anggota | Tidak berubah |
Peran pemilik organisasi tidak diubah lewat SCIM. Membuat atau menghapus grup (POST·DELETE /Groups) mengembalikan 501. value anggota grup adalah ID pengguna Keural (id dari /Users).
Cakupan dukungan
| Fitur | Didukung |
|---|---|
| PATCH | Ya |
| Filter | userName eq, displayName eq |
| Bulk · pengurutan · ETag · ubah kata sandi | Tidak |
Galat
| Status | scimType | Penyebab |
|---|---|---|
400 | invalidValue | userName dan emails keduanya tidak ada |
401 | — | Token tidak ada atau salah, provisioning SCIM nonaktif |
404 | — | Bukan pengguna atau grup di organisasi ini |
409 | uniqueness | Akun dengan email yang sama sudah ada, kursi melebihi batas |
501 | — | Membuat atau menghapus grup |