Mendaftarkan aplikasi secara dinamis lewat Client Registration endpoint dengan initial access token, mengatur client policies, serta memilih metode autentikasi klien dari shared secret hingga private key JWT dan mTLS.

Di episode 25 kalian mengatur apa yang boleh dilakukan user dengan fine-grained authorization. Episode 26 ini membahas sisi lain dari ekosistem klien: bagaimana aplikasi baru bisa bergabung tanpa harus lewat admin console setiap kali. Dynamic client registration memungkinkan aplikasi mendaftarkan dirinya sendiri lewat API — pola yang sangat berguna di era CI/CD, SPA, dan microservices yang jumlahnya terus bertambah.
Sejauh ini kalian membuat klien satu per satu di admin console. Untuk skala besar itu tidak efisien. Keycloak menyediakan Client Registration endpoint yang menerima pendaftaran dinamis sesuai spesifikasi OpenID Connect Dynamic Client Registration:
/clients-registrations/openid-connect di bawah setiap realmPOST untuk mendaftar, GET untuk membaca, PUT untuk memperbarui, DELETE untuk menghapusClient metadata mencakup redirect_uris, grant_types, response_types, client_name, client_secret, dan lainnya — persis seperti yang biasa kalian isi di form admin console, tapi dalam bentuk JSON yang bisa diproduksi oleh pipeline.
Dinamis tidak berarti tanpa kendali. Kombinasikan dynamic registration dengan client policies di bawah: pendaftaran tetap terbuka lewat API, tetapi standar keamanan tetap dipaksakan oleh kebijakan terpusat. Untuk aplikasi internal yang jarang berubah, admin console tetap lebih cepat — dynamic registration unggul saat jumlah klien besar dan berubah sering.
Pendaftaran dinamis tidak boleh terbuka tanpa kendali. Keycloak memakai initial access token: token yang dibuat admin di Realm Settings → Client Registration → Initial Access Token. Saat membuatnya, kalian bisa membatasi jumlah pemakaian dan masa berlakunya — begitu kuota habis, token tidak bisa dipakai lagi:
curl -X POST "https://sso.example.com/realms/bank/clients-registrations/openid-connect" \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6I..." \
-H "Content-Type: application/json" \
-d '{
"client_id": "bank-mobile",
"client_name": "Bank Mobile",
"grant_types": ["authorization_code", "refresh_token"],
"redirect_uris": ["https://bank.example.com/callback"],
"public": true
}'initial access token dikirim pada header Authorization. Respon registrasi berisi client_id, client_secret (untuk klien rahasia), dan yang tak kalah penting registration access token — token untuk mengelola klien tersebut nanti. Simpan keduanya dengan aman; ia adalah kunci pengelolaan klien itu.
Setelah terdaftar, klien bisa dikelola lewat registration_client_uri yang dikembalikan pada respons. Dengan membawa registration access token, aplikasi atau pipeline bisa membaca, memperbarui, atau menghapus konfigurasi kliennya sendiri — tanpa akses admin:
curl -X PUT "https://sso.example.com/realms/bank/clients-registrations/openid-connect/119ef730-e427" \
-H "Authorization: Bearer <registration_access_token>" \
-H "Content-Type: application/json" \
-d '{
"redirect_uris": ["https://bank.example.com/callback", "https://bank.example.com/mobile"]
}'Pola ini sangat berguna untuk deployment otomatis: setiap rilis service baru mendaftarkan atau memperbarui kliennya sendiri dengan redirect URI dan grant type yang sesuai, dan menghapus kliennya saat lingkungan di-teardown.
Registration access token bersifat unik per klien dan hanya bisa mengelola klien tersebut — tidak bisa dipakai untuk mengubah klien lain. Jika hilang, admin bisa menerbitkan ulang lewat admin console, jadi perlakukan ia sebagai kredensial yang sama pentingnya dengan client_secret.
Model klien menentukan seberapa aman kredensial bisa disimpan. Ini perbandingannya:
| Aspek | Public Client | Confidential Client |
|---|---|---|
| Contoh | SPA, aplikasi mobile | Backend, service-to-service |
| Secret | Tidak punya | Punya client_secret atau key |
| Flow utama | Authorization Code + PKCE | Authorization Code, private key JWT, mTLS |
| Risiko secret | Tidak bisa disimpan aman | Harus dijaga di sisi server |
| Umum dipakai untuk | End-user di browser/HP | API server, daemon |
Aturan praktisnya: kalau aplikasi bisa di-decompile atau kode-nya terbaca browser, itu public — jangan pernah menyematkan secret di dalamnya. Gunakan PKCE. Sedangkan aplikasi yang berjalan di server bisa jadi confidential. Satu catatan: direct access grants (Resource Owner Password) memang tersedia di Keycloak, tetapi dianggap pola yang lemah dan sudah tidak dianjurkan — hindari kecuali untuk kasus legacy yang benar-benar tidak bisa dihindari.
Untuk skala besar, mengatur setiap klien satu per satu tidak realistis. Client policies memungkinkan kebijakan terpusat:
client_secret minimal panjang tertentu atau menambah atribut ke token.Dengan client policies, kalian bisa menjamin standar keamanan minimum — semua klien baru otomatis memakai metode autentikasi yang disetujui dan secret yang kuat — tanpa harus menilik setiap pendaftaran manual.
Ketika klien confidential berkomunikasi dengan Keycloak, ia harus membuktikan identitasnya. Metodenya beragam:
| Metode | Cara Kerja | Tingkat Keamanan |
|---|---|---|
| Client secret | shared secret dikirim bersama token request | Dasar |
| Client JWT | klien menandatangani assertion dengan secret | Sedang |
| Private key JWT | klien menandatangani assertion dengan private key | Tinggi |
| mTLS | sertifikat klien diverifikasi pada lapisan TLS | Tinggi |
| Client assertion | token JWT yang membuktikan identitas klien | Bervariasi |
client_secret_post dan client_secret_basic adalah metode dasar berbasis shared secret. private key JWT (private_key_jwt) menaikkan standar: klien memegang private key, sementara public key terdaftar di Keycloak — tidak ada rahasia bersama yang bisa bocor dari sisi server. Untuk keamanan tertinggi, mTLS memverifikasi sertifikat klien langsung di lapisan TLS. Client assertion adalah istilah umum untuk pembuktian identitas klien berupa token JWT, yang dipakai oleh beberapa metode di atas.
Tip
Untuk koneksi service-to-service, mulai dengan private_key_jwt dan pastikan secret klien tidak pernah masuk ke log. Klien yang sudah lama memakai shared secret sebaiknya dimigrasikan bertahap ke private key JWT — lakukan per klien, bukan sekaligus.
Episode 26 mengajarkan pengelolaan klien di skala besar: dynamic client registration lewat Client Registration endpoint dengan initial access token dan registration access token; pengelolaan klien terdaftar; perbedaan public dan confidential client; client policies untuk menegakkan standar; serta metode autentikasi klien dari shared secret hingga private key JWT dan mTLS.
Inti yang harus dibawa pulang:
Di episode 27 berikutnya, kalian membawa Keycloak ke skala enterprise: high availability & clustering — banyak instance, cache terdistribusi, dan load balancing di balik satu pintu masuk.