Clients
client คืออะไร?
หัวข้อที่มีชื่อว่า “client คืออะไร?”client คือแอปพลิเคชันใด ๆ ที่มอบหมายงาน authentication และ authorisation ให้ Keycloak จัดการ เมื่อ user ต้องการ sign in เข้าแอปของคุณ แอปของคุณจะ redirect พวกเขาไปยัง Keycloak Keycloak จะยืนยันตัวตน user แล้ว redirect กลับมายังแอปของคุณพร้อมกับ code หรือ token การ redirect ไปมาแบบนี้คือ Authorization Code flow ของ OAuth2 / OIDC และ “client” ก็คือฝ่ายที่แอปของคุณลงทะเบียนตัวเองเอาไว้
ตัวอย่างของ client:
- React SPA ที่เรียก REST API แทน user ที่ log in อยู่
- แอปพลิเคชันเว็บ Spring Boot ที่แสดง dashboard หลัง login
- mobile app ที่ให้ user จัดการบัญชีของตัวเอง
- backend microservice ที่เรียก service อื่นโดยใช้ token แบบ machine-to-machine
client ทุกตัวอยู่ภายใน realm หนึ่งเดียวเท่านั้น หากคุณมีแอปพลิเคชันที่ต่างกันสองตัว ให้ลงทะเบียน client สองตัว — แม้ว่าทั้งสองจะใช้ user ร่วมกันก็ตาม
การสร้าง client
หัวข้อที่มีชื่อว่า “การสร้าง client”- ใน admin console ตรวจสอบให้แน่ใจว่าคุณอยู่ใน realm ที่ถูกต้อง (เช็กที่ drop-down มุมบนซ้าย)
- คลิก Clients ในแถบด้านซ้าย
- คลิก Create client (มุมบนขวาของรายการ client)
- ที่ขั้นตอน General Settings:
- Client type — ปล่อยไว้เป็น OpenID Connect (มาตรฐานสมัยใหม่; ใช้ SAML เฉพาะเมื่อระบบ legacy บังคับให้ใช้เท่านั้น)
- Client ID — ใส่ identifier ที่สั้น เป็นตัวพิมพ์เล็ก และคั่นด้วยขีดกลาง (เช่น
my-app-frontend) นี่คือclient_idที่แอปพลิเคชันของคุณส่งไปในคำขอ token - Name — display name ที่อ่านง่ายสำหรับคนทั่วไป (ไม่บังคับ) ที่แสดงใน admin console
- Description — บันทึกข้อความอิสระ (ไม่บังคับ)
- คลิก Next
- ที่ขั้นตอน Capability config:
- Client authentication — ปล่อยไว้เป็น Off สำหรับ public client (SPA, mobile); เปิดเป็น On สำหรับ confidential client (แอปฝั่ง server) ดูรายละเอียดในบทเรียน Client Types
- Authorization — ปล่อยไว้เป็น Off เว้นแต่คุณต้องใช้ authorisation policy แบบละเอียดของ Keycloak
- คลิก Next
- ที่ขั้นตอน Login settings — นี่คือจุดที่การตั้งค่า redirect ซึ่งสำคัญต่อความปลอดภัยอยู่:
- Root URL — base URL ของแอปพลิเคชันของคุณ (เช่น
http://localhost:3000) Keycloak จะนำมาต่อหน้า URI แบบ relative - Valid redirect URIs — URI ที่แน่นอนซึ่ง Keycloak ได้รับอนุญาตให้ redirect กลับไปหลัง login ใส่อย่างน้อยหนึ่งรายการ (เช่น
http://localhost:3000/*) อนุญาตให้ใช้ wildcard ได้ แต่ควรเจาะจงให้มากที่สุดเท่าที่จะทำได้ใน production - Valid post logout redirect URIs — URI ที่อนุญาตหลัง logout ใส่
+เพื่อใช้รายการเดียวกับ valid redirect URIs ซ้ำ หรือระบุอย่างชัดเจน - Web origins — origin ที่อนุญาตให้ส่งคำขอแบบ cross-origin (CORS) ใส่
+เพื่อให้มาจาก valid redirect URIs หรือระบุเป็นรายการอย่างชัดเจน (เช่นhttp://localhost:3000) - คลิก Save
- Root URL — base URL ของแอปพลิเคชันของคุณ (เช่น
ตอนนี้ client ของคุณลงทะเบียนเรียบร้อยแล้ว คุณจะไปอยู่ที่แท็บ Settings ของ client
รายการ client
หัวข้อที่มีชื่อว่า “รายการ client”หน้า Clients (แถบด้านซ้าย) จะแสดง client ทุกตัวที่ลงทะเบียนอยู่ใน realm ของคุณ รายการประกอบด้วย:
- Client ID — identifier ที่แอปของคุณใช้
- Enabled — client ทำงานอยู่หรือไม่
- Type — OpenID Connect หรือ SAML
- Description — บันทึกของคุณ (ไม่บังคับ)
คลิกที่ client ID ใดก็ได้เพื่อเปิดการตั้งค่าและแท็บต่าง ๆ ของตัวเอง (Settings, Credentials, Roles, Client scopes, Advanced ฯลฯ)
การตั้งค่าสำคัญหลังจากสร้าง
หัวข้อที่มีชื่อว่า “การตั้งค่าสำคัญหลังจากสร้าง”Valid redirect URIs
หัวข้อที่มีชื่อว่า “Valid redirect URIs”หลังจาก user ยืนยันตัวตน Keycloak จะ redirect พวกเขากลับไปยัง URI ตัวใดตัวหนึ่งในรายการนี้ หาก redirect URI ในคำขอไม่ตรงกับรายการใดเลย Keycloak จะปฏิเสธคำขอด้วย error นี่คือการควบคุมด้านความปลอดภัยที่สำคัญ: ช่วยป้องกันการโจมตีแบบ authorisation-code interception ที่ผู้โจมตีหลอก Keycloak ให้ redirect code ไปยังเว็บไซต์ที่พวกเขาควบคุมอยู่
ให้ redirect URI เจาะจงมากที่สุดเท่าที่จะทำได้ ในระหว่างพัฒนา http://localhost:3000/* ถือว่ายอมรับได้ แต่ใน production ให้ระบุเฉพาะ callback path ที่แน่นอนเท่านั้น:
https://app.example.com/auth/callbackWeb origins
หัวข้อที่มีชื่อว่า “Web origins”รายการ Web origins ควบคุมว่า origin ใดบ้างที่ browser อนุญาตให้เรียก Keycloak token endpoint โดยตรง (สำหรับ CORS preflight) หาก SPA ของคุณรันอยู่ที่ https://app.example.com และเรียก https://auth.example.com/realms/my-app/protocol/openid-connect/token origin นั้นต้องอยู่ในรายการนี้
การตั้งค่า Web origins เป็น + คือทางลัดที่สะดวก ซึ่งบอก Keycloak ให้อนุญาตทุก origin ที่ปรากฏในรายการ Valid redirect URIs ของคุณ
curl เพื่อตรวจสอบ OIDC discovery document ของ client คุณ
หัวข้อที่มีชื่อว่า “curl เพื่อตรวจสอบ OIDC discovery document ของ client คุณ”ทุก realm จะเปิดเผย OpenID Connect discovery document คุณใช้ document นี้ตรวจสอบ issuer, token endpoint และ JWKS URI ของ client คุณได้:
curl https://localhost:8080/realms/my-app/.well-known/openid-configuration | jq .แทนที่ my-app ด้วยชื่อ realm ของคุณ ส่วน jq . จะ pretty-print JSON response ออกมา
ข้อแลกเปลี่ยน
หัวข้อที่มีชื่อว่า “ข้อแลกเปลี่ยน”| ตัวเลือก | Benefit | Cost |
|---|---|---|
| Client type: OpenID Connect | มาตรฐานสมัยใหม่ เข้ากันได้กับ library และ SDK ส่วนใหญ่ ตั้งค่าและ debug ง่ายกว่า | ไม่มีประโยชน์เพิ่มเติมสำหรับระบบ legacy ที่ผูกกับ SAML assertion โดยเฉพาะ |
| Valid redirect URI แบบเจาะจง (exact match) | ป้องกัน authorization-code interception attack ได้แน่นหนา ควบคุมชัดเจนว่า Keycloak ส่ง token กลับไปที่ไหนได้บ้าง | ต้องอัปเดตรายการทุกครั้งที่เพิ่ม environment หรือ path ใหม่ เพิ่ม maintenance overhead |
Web origins ตั้งเป็น + (นำมาจาก redirect URIs) | ตั้งค่าครั้งเดียว ไม่ต้อง sync สอง list แยกกัน | หากรายการ redirect URIs กว้างเกินไป Web origins ก็จะกว้างตามไปด้วย |
ข้อผิดพลาดที่พบบ่อย
หัวข้อที่มีชื่อว่า “ข้อผิดพลาดที่พบบ่อย”- ใช้ wildcard
*ทั้งหมดใน Valid redirect URIs บน production client — เปิดช่องให้ Keycloak redirect ไปยังโดเมนใดก็ได้ที่ตรง pattern รวมถึงโดเมนของผู้โจมตี ควรระบุ callback path ที่แน่นอนเท่านั้นใน production - ลงทะเบียน SPA เป็น confidential client แล้วฝัง client secret ไว้ใน frontend bundle — secret ที่ฝังอยู่ใน code ฝั่ง client ถือว่าเปิดเผยต่อสาธารณะเสมอ เพราะใครก็เปิด devtools ดูได้ ควรใช้ public client ร่วมกับ PKCE แทน
- ไม่ตั้งค่า Web origins ให้ตรงกับ origin จริงของ frontend — ทำให้ CORS preflight ล้มเหลวเวลาเรียก token endpoint ตรง ๆ จาก browser หรือถ้าตั้งกว้างเกินไปก็เปิดช่องโหว่โดยไม่จำเป็น
💡 ตัวอย่างจากของจริง
Google Cloud Console — ลงทะเบียน OAuth client แยกกันสำหรับแต่ละ environment (dev, staging, production) พร้อม redirect URI ที่เจาะจงต่อ environment นั้น ๆ เพื่อไม่ให้ authorization code หรือ token รั่วไหลข้าม environment
Stripe Connect — ใช้ confidential client กับ client secret ที่เก็บไว้เฉพาะฝั่ง server เพื่อลงทะเบียน platform application ที่เชื่อมต่อกับบัญชีผู้ใช้จำนวนมาก ไม่มี secret ใดหลุดออกไปยัง browser ของ end-user เลย