ข้ามไปยังเนื้อหา

Token Endpoint ภาคปฏิบัติ

Direct Access Grant (หรือ password grant) ช่วยให้ client แลก username และ password ของผู้ใช้เป็น token โดยตรงที่ token endpoint โดยไม่ต้องผ่านการ redirect ของ browser

เนื่องจาก credential ของผู้ใช้ถูกส่งตรงไปยัง client ก่อนแล้วค่อยส่งต่อไปยัง Keycloak grant นี้จึงเหมาะสำหรับ testing script, CLI tool และสภาพแวดล้อมการพัฒนาเท่านั้น — ไม่ใช่แอปที่ใช้งานจริง

ใช้ Direct Access Grant สำหรับ:

  • Test script ที่ต้องการ token โดยไม่มี browser
  • CLI tool ที่ authenticate ด้วย credential ของผู้ใช้ชั่วคราว
  • การทดสอบ API ในสภาพแวดล้อม development

อย่าใช้สำหรับแอปที่ผู้ใช้ใช้งานจริง ให้ใช้ Authorization Code + PKCE แทน

curl -X POST https://${KC_URL}/realms/${REALM}/protocol/openid-connect/token \
  -d "grant_type=password" \
  -d "client_id=${CLIENT_ID}" \
  -d "username=${USERNAME}" \
  -d "password=${PASSWORD}"

Keycloak จะส่งคืน JSON object ที่มี token ต่างๆ ดังนี้:

{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"expires_in": 300,
"refresh_expires_in": 1800,
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"id_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"session_state": "abc123",
"scope": "openid profile email"
}

ส่ง access token ไปยัง API ด้วย Authorization header แบบ Bearer:

Authorization: Bearer <access_token>
echo ${ACCESS_TOKEN} | cut -d. -f2 | base64 -d | jq .
ตัวเลือกBenefitCost
ทดสอบด้วย curl ตรง ๆ ที่ token endpointเห็น request/response ดิบ ๆ ชัดเจน เข้าใจ protocol จริง ๆ ไม่มี abstraction บังต้องจัดการ token lifecycle เอง (refresh, expiry, storage) และเสี่ยง credential หลุดถ้าไม่ระวัง
ใช้ OIDC client library (เช่น openid-client, Keycloak adapter)Library จัดการ token refresh, validation, และ security best practice ให้อัตโนมัติเพิ่ม dependency และมี abstraction ที่ต้องเรียนรู้ ไม่เห็น raw protocol ตรง ๆ เหมือน curl
  • พิมพ์ password หรือ client secret ตรง ๆ ใน curl command — คำสั่งที่พิมพ์ในเทอร์มินัลจะถูกบันทึกลง shell history (.bash_history, .zsh_history) แบบ plaintext ควรใช้ environment variable หรือไฟล์ .env ที่ไม่ commit เข้า git แทนการพิมพ์ credential ตรง ๆ
  • แปะ access token ลงใน log หรือแชร์ใน chat เพื่อ debug — access token และ refresh token คือของมีค่าเทียบเท่า password ใครก็ตามที่มี token ก่อน expire สามารถเรียก API แทนผู้ใช้ได้เลย ไม่ควร log token แบบเต็ม ควร mask หรือ log แค่บางส่วน
  • ใช้ Direct Access Grant (password grant) กับแอป production จริง — grant นี้เหมาะสำหรับ testing script และ CLI tool เท่านั้น เพราะต้องส่ง username/password ตรงให้ client ก่อน ถ้าใช้ในแอปจริงเท่ากับเปิดเผย credential ผู้ใช้ให้กับ client โดยไม่จำเป็น
  • ไม่ปิด HISTCONTROL หรือลืมลบ history หลังทดสอบด้วย curl — เมื่อ debug เสร็จแล้วลืมล้าง credential ที่หลุดไปอยู่ใน shell history ทำให้ secret ค้างอยู่ในเครื่องระยะยาวโดยไม่รู้ตัว

💡 ตัวอย่างจากของจริง

Postman หรือ Insomnia ใน dev workflow — ทีม dev มักใช้เครื่องมือเหล่านี้แทน curl ตรง ๆ เพื่อเก็บ credential ใน encrypted vault แทนที่จะพิมพ์ผ่าน command line ที่เสี่ยงหลุดไปอยู่ใน shell history

kubectl และ CLI tool อื่น ๆ ที่คุย OIDC — เบื้องหลังใช้หลักการเดียวกับ curl ต่อ token endpoint แต่ห่อด้วย library ที่จัดการ token caching, refresh, และ secure storage ให้อัตโนมัติ ต่างจาก script curl ดิบ ๆ ที่ต้องทำเองทุกขั้นตอน

Direct Access Grant (password grant) ใช้ทำอะไรเป็นหลัก?
ใช้ header ใดในการส่ง access token ไปยัง API?
expires_in ในผลลัพธ์ token หมายถึงอะไร?
เหตุใดจึงควรหลีกเลี่ยง password grant ในแอปจริง?