เรียนรู้ว่า JWT (JSON Web Token) คืออะไร ส่วนประกอบทั้งสามทำงานอย่างไร ใช้ที่ไหน และเคล็ดลับด้านความปลอดภัยที่สำคัญเพื่อหลีกเลี่ยงข้อผิดพลาด

A JWT (JSON Web Token) เป็นสตริงขนาดกะทัดรัดและ ปลอดภัยสำหรับ URL ที่แทนชุดข้อมูล (มักจะเกี่ยวกับผู้ใช้หรือเซสชัน) ในรูปแบบที่สามารถส่งระหว่างระบบได้ คุณมักจะเห็นเป็นค่าที่ยาวเริ่มต้นด้วยเช่น eyJ... ซึ่งส่งใน HTTP header เช่น Authorization: Bearer \u003ctoken\u003e.
การล็อกอินแบบดั้งเดิมมักพึ่งพา sessions ฝั่งเซิร์ฟเวอร์: เมื่อคุณลงชื่อเข้าใช้ เซิร์ฟเวอร์จะเก็บข้อมูลเซสชันและให้เบราว์เซอร์คุกกี้ ID เซสชัน ทุกคำขอจะส่งคุกกี้นั้น แล้วเซิร์ฟเวอร์จะค้นหาข้อมูลเซสชัน
ด้วย การยืนยันตัวตนด้วยโทเค็น เซิร์ฟเวอร์สามารถหลีกเลี่ยงการเก็บสถานะสำหรับทุกคำขอของผู้ใช้ได้ ดีสำหรับ API เพราะมัน:
ความสำคัญ: “stateless” ไม่ได้แปลว่า “ไม่มีการตรวจสอบฝั่งเซิร์ฟเวอร์เลย” ระบบจริงหลายแห่งยังคงตรวจสอบโทเค็นเทียบกับสถานะผู้ใช้ การหมุนคีย์ หรือกลไกการเพิกถอน
JWT มักจะบรรจุ หลักฐานการพิสูจน์ตัวตน (คุณลงชื่อเข้าใช้แล้ว) และ ข้อมูลช่วยในการอนุญาต เบื้องต้น (บทบาท สิทธิ์ ขอบเขต) — แต่เซิร์ฟเวอร์ของคุณยังต้องบังคับใช้กฎการอนุญาต
คุณจะพบ JWT ใช้เป็น access tokens บ่อยๆ ใน:
JWT เป็นสตริงกะทัดรัดประกอบด้วย สามส่วน แต่ละส่วน เข้ารหัสเป็น base64url และคั่นด้วยจุด:
header.payload.signature
ตัวอย่าง (ตัดทอน):
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwiaWF0IjoxNzAwMDAwMDAwfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c…
Header อธิบายว่าทำโทเค็นอย่างไร—สำคัญที่สุดคือ อัลกอริทึมการเซ็น (เช่น HS256, RS256/ES256) และชนิดของโทเค็น
ฟิลด์ทั่วไป:
typ: มักเป็น "JWT" (มักจะถูกละเลยในทางปฏิบัติ)alg: อัลกอริทึมการเซ็นที่ใช้kid: ตัวระบุคีย์เพื่อช่วยตัวตรวจสอบเลือกคีย์ที่ถูกต้องเมื่อมีการหมุนข้อควรระวังด้านความปลอดภัย: อย่าไว้ใจ header โดยอัตโนมัติ ให้บังคับ allowlist ของอัลกอริทึมที่คุณใช้งานจริง และอย่ารับ alg: "none"
Payload เก็บ “claims” (ฟิลด์) เกี่ยวกับผู้ใช้และบริบทของโทเค็น: ใครเป็นผู้รับ ใครเป็นผู้ออก และเมื่อไหร่ที่หมดอายุ
สำคัญ: JWT ไม่ได้ถูกเข้ารหัสโดยค่าเริ่มต้น การเข้ารหัส base64url ทำให้โทเค็นปลอดภัยสำหรับ URL; มันไม่ได้ซ่อนข้อมูล ใครก็ตามที่ได้โทเค็นสามารถถอดรหัส header และ payload ได้
นั่นคือเหตุผลที่คุณควรหลีกเลี่ยงการใส่ความลับ (รหัสผ่าน คีย์ API) หรือข้อมูลส่วนตัวที่ละเอียดอ่อนลงใน JWT
Signature สร้างโดยการเซ็น header + payload ด้วยคีย์:
Signature ให้ความมั่นใจด้าน integrity: ช่วยให้เซิร์ฟเวอร์ยืนยันว่าโทเค็นไม่ถูกแก้ไขและถูกออกโดยผู้ลงนามที่เชื่อถือได้ มันไม่ให้ความลับ
เพราะ JWT รวม header และ payload ทุกครั้งที่ส่ง โทเค็นใหญ่หมายถึงแบนด์วิดท์และค่าใช้จ่ายที่มากขึ้น เก็บ claims ให้เรียบง่ายและใช้ตัวระบุตัวตนแทนข้อมูลขนาดใหญ่
Claims โดยทั่วไปแบ่งเป็นสองกลุ่ม: registered (ชื่อมาตรฐาน) และ custom (ฟิลด์ของแอปคุณ)
iss (issuer): ผู้สร้างโทเค็นsub (subject): ใครเกี่ยวข้องกับโทเค็น (มักเป็น user ID)aud (audience): ใครเป็นผู้รับที่ตั้งใจ (เช่น API ใด API หนึ่ง)exp (expiration time): เมื่อใดที่โทเค็นต้องไม่ถูกยอมรับอีกต่อไปiat (issued at): เมื่อโทเค็นถูกสร้างnbf (not before): โทเค็นไม่ควรถูกยอมรับก่อนเวลานี้รวมเฉพาะที่บริการรับต้องการจริงๆ เพื่อใช้ในการตัดสินใจการอนุญาต
ตัวอย่างที่ดี:
user_id)หลีกเลี่ยง “claims สะดวก” ที่ทำซ้ำข้อมูลโปรไฟล์มาก ๆ พวกมันทำให้โทเค็นบวม ข้อมูลล้าสมัยเร็ว และเพิ่มผลกระทบหากโทเค็นหลุด
เพราะ payload อ่านได้ อย่าเก็บ:
ถ้าต้องการข้อมูลที่ละเอียดอ่อน ให้เก็บฝั่งเซิร์ฟเวอร์และใส่เฉพาะอ้างอิง (เช่น ID) ในโทเค็น หรือใช้รูปแบบโทเค็นเข้ารหัส (JWE) เมื่อเหมาะสม
การเซ็นไม่ใช่การเข้ารหัส
เมื่อ JWT ถูกออกแล้ว เซิร์ฟเวอร์จะเซ็น header + payload ที่เข้ารหัสไว้ เมื่อโทเค็นถูกนำมาแสดงในภายหลัง เซิร์ฟเวอร์จะคำนวณ signature ใหม่และเปรียบเทียบ ถ้ามีคนเปลี่ยนแม้แต่ตัวอักษรเดียว การยืนยันจะล้มเหลวและโทเค็นจะถูกปฏิเสธ
JWT เป็น รูปแบบของโทเค็น ส่วน OAuth 2.0 และ OpenID Connect (OIDC) เป็น โปรโตคอล ที่อธิบายวิธีที่แอปขอ ออก และใช้โทเค็น
OAuth 2.0 เกี่ยวกับ การอนุญาต: ให้แอปเข้าถึง API ในนามผู้ใช้โดยไม่ต้องแชร์รหัสผ่าน
Access tokens มักจะ มีอายุสั้น (เป็นนาที) เพื่อลดความเสียหายหากโทเค็นหลุด
OIDC เพิ่มการ พิสูจน์ตัวตน (ผู้ใช้คือใคร) บน OAuth 2.0 และแนะนำ ID token ซึ่งมักเป็น JWT
กฎสำคัญ: อย่าใช้ ID token เพื่อเรียก API
หากต้องการบริบทเพิ่มเติมเกี่ยวกับ flows เชิงปฎิบัติ ดู /blog/jwt-authentication-flow.
กระบวนการทั่วไปเป็นดังนี้:
ผู้ใช้ลงชื่อเข้าใช้ (อีเมล/รหัสผ่าน, SSO ฯลฯ) หากสำเร็จ เซิร์ฟเวอร์จะสร้าง JWT (มักเป็น access token) พร้อม claims สำคัญเช่น subject และ expiration
เซิร์ฟเวอร์เซ็นโทเค็นและส่งกลับไปยังไคลเอนต์ (เว็บแอป แอปมือถือ หรือบริการอื่น)
สำหรับ endpoints ที่ป้องกัน ไคลเอนต์รวม JWT ใน header Authorization:
Authorization: Bearer \u003cJWT\u003e
ก่อนให้บริการ คำขอ API มักจะตรวจสอบ:
exp (ยังไม่หมดอายุ)iss (ผู้ที่ออกที่คาดไว้)aud (มุ่งหมายไปยัง API นี้)ถ้าการตรวจสอบทั้งหมดผ่าน API จะถือว่าผู้ใช้ผ่านการพิสูจน์ตัวตนและจะบังคับใช้กฎการอนุญาต (เช่น สิทธิ์ระดับ record)
เพราะนาฬิกาของระบบคลาดเคลื่อน ระบบหลายแห่งจึงอนุญาต clock skew เล็กน้อยเมื่อยืนยัน claims ที่เกี่ยวกับเวลาเช่น exp (และบางครั้ง nbf) ให้เก็บ skew ให้เล็กเพื่อหลีกเลี่ยงการขยายความถูกต้องของโทเค็นมากเกินไป
การเลือกที่เก็บเปลี่ยนสิ่งที่ผู้โจมตีขโมยได้และความง่ายในการ replay
การเก็บในหน่วยความจำ (แนะนำสำหรับ SPA บ่อยครั้ง) เก็บ access token ในสถานะ JS มันจะถูกล้างเมื่อรีเฟรชและลดความเสี่ยงที่ถูกขโมยเก็บไว้ แต่บั๊ก XSS ยังสามารถอ่านได้ขณะหน้าเพจทำงาน จับคู่กับ access token ที่อายุสั้นและ flow การรีเฟรช
localStorage/sessionStorage สะดวกแต่เสี่ยง: XSS ใด ๆ สามารถขโมยโทเค็นจาก storage ได้ หากใช้ ให้ทำการป้องกัน XSS อย่างเคร่งครัด (CSP, การหนีข้อมูลออก, ดูแล dependency) และเก็บโทเค็นให้อายุสั้น
คุกกี้ Secure (มักเป็นค่าเริ่มต้นที่ปลอดภัยที่สุดสำหรับเว็บ) เก็บโทเค็นในคุกกี้ HttpOnly เพื่อให้ JavaScript อ่านไม่ได้—ลดผลกระทบจากการขโมยโทเค็นโดย XSS ข้อแลกเปลี่ยนคือความเสี่ยง CSRF เพราะเบราว์เซอร์แนบคุกกี้โดยอัตโนมัติ
ถ้าใช้คุกกี้ ให้ตั้งค่า:
HttpOnlySecure (เฉพาะ HTTPS)SameSite=Lax หรือ SameSite=Strict (บาง flow ข้ามไซต์อาจต้อง SameSite=None; Secure)พิจารณาใช้ CSRF tokens สำหรับคำขอที่เปลี่ยนสถานะ
บน iOS/Android ให้เก็บโทเค็นใน secure storage ของแพลตฟอร์ม (Keychain / Keystore-backed storage) หลีกเลี่ยงไฟล์ธรรมดาหรือ preferences หากภัยคุกคามของคุณรวมถึงอุปกรณ์ที่รูท/เจลเบรค ให้สมมติว่าการสกัดข้อมูลเป็นไปได้และพึ่งพา access token ที่อายุสั้นและการควบคุมฝั่งเซิร์ฟเวอร์
จำกัดสิ่งที่โทเค็นทำได้: ใช้ scopes/claims ที่น้อยที่สุด ทำให้ access tokens มีอายุสั้น และหลีกเลี่ยงการฝังข้อมูลที่ละเอียดอ่อน
JWT สะดวก แต่หลายเหตุการณ์เกิดจากความผิดพลาดที่คาดเดาได้ ปฏิบัติกับ JWT เหมือนเงินสด: ใครได้ไปมักจะใช้ได้
ถ้าโทเค็นมีอายุหลายวันหรือหลายสัปดาห์ การรั่วไหลให้ผู้โจมตีช่วงเวลายาว
แนะนำให้ใช้ access tokens ที่อายุสั้น (เป็นนาที) และรีเฟรชผ่านกลไกที่ปลอดภัย หากต้องการ “จำฉันไว้” ให้ใช้ refresh tokens และการควบคุมฝั่งเซิร์ฟเวอร์
ลายเซ็นที่ถูกต้องไม่พอ ตรวจสอบ iss และ aud และตรวจสอบ claims ที่เกี่ยวกับเวลาเช่น exp และ nbf
การถอดรหัสไม่ใช่การยืนยัน เสมอตรวขสอบลายเซ็นฝั่งเซิร์ฟเวอร์และบังคับใช้สิทธิ์ฝั่งเซิร์ฟเวอร์เสมอ
หลีกเลี่ยงการใส่ JWT ใน query params มันอาจจบลงในประวัติของเบราว์เซอร์ บันทึกของเซิร์ฟเวอร์ เครื่องมือวิเคราะห์ และ header referrer
ใช้ Authorization: Bearer ... แทน
สมมติว่าคีย์และโทเค็นอาจรั่ว หมุนคีย์การเซ็น ใช้ kid เพื่อรองรับการหมุนอย่างราบรื่น และมีแผนเพิกถอน (อายุสั้น + ความสามารถปิดบัญชี/เซสชัน) สำหรับคำแนะนำการเก็บ ดู /blog/where-to-store-jwts-safely.
JWT มีประโยชน์ แต่ไม่ใช่คำตอบที่ดีที่สุดเสมอ คำถามจริงคือคุณได้ประโยชน์จากโทเค็นที่ตรวจสอบได้ด้วยตนเองโดยไม่ต้อง lookup ฐานข้อมูลในทุกคำขอหรือไม่
สำหรับเว็บที่เรนเดอร์ฝั่งเซิร์ฟเวอร์แบบดั้งเดิมที่ต้องการการเพิกถอนง่าย ๆ server-side sessions กับ HttpOnly cookies มักเป็นค่าเริ่มต้นที่ง่ายและปลอดภัยกว่า
เลือก JWT ถ้าคุณต้องการการยืนยันแบบ stateless ข้ามบริการและสามารถทำให้โทเค็นมีอายุสั้น
หลีกเลี่ยง JWT ถ้าคุณต้องการเพิกถอนทันที ต้องเก็บข้อมูลละเอียดอ่อนในโทเค็น หรือสามารถใช้ session cookies ได้โดยไม่เกิดปัญหา
ตรวจสอบโดยใช้คีย์ที่ถูกต้องและอัลกอริทึมที่ Allowlist ปฏิเสธลายเซ็นที่ไม่ถูกต้อง—ไม่มีข้อยกเว้น
exp (expiration)ตรวจสอบว่าโทเค็นยังไม่หมดอายุ
nbf (not before)ถ้ามี ให้แน่ใจว่าโทเค็นยังไม่ถูกใช้งานก่อนเวลา
aud (audience)ยืนยันว่าโทเค็นมุ่งหมายสำหรับ API/เซอร์วิสของคุณ
iss (issuer)ยืนยันว่าโทเค็นมาจาก issuer ที่คาดไว้
ตรวจสอบรูปแบบโทเค็น บังคับขนาดสูงสุด และปฏิเสธชนิด claim ที่ไม่คาดคิดเพื่อลดบั๊กมุมแปลกๆ
HS256 (คีย์สมมาตร): secret เดียวใช้เซ็นและยืนยัน
RS256 / ES256 (คีย์ไม่สมมาตร): private key เซ็น; public key ยืนยัน
กฎทั่วไป: หากระบบมากกว่าหนึ่งระบบต้องยืนยันโทเค็นหรือคุณไม่ไว้วางใจ verifier ทุกตัว ให้เลือก RS256/ES256
iss, aud, และ user ID ถ้านโยบายอนุญาต)Is JWT encrypted?
Not by default. Most JWTs are signed, not encrypted, meaning the contents can be read by anyone who has the token. Use JWE or keep sensitive data out of JWTs.
Can I revoke a JWT?
Not easily if you rely only on self-contained access tokens. Common approaches include short-lived access tokens, deny-lists for high-risk events, or refresh tokens with rotation.
How long should exp be?
As short as your UX and architecture allow. Many APIs use minutes for access tokens, paired with refresh tokens for longer sessions.
ถ้าคุณกำลังนำ JWT มาใช้ใน API ใหม่หรือ SPA งานหลายอย่างซ้ำๆ: ต่อสาย middleware, ตรวจสอบ iss/aud/exp, ตั้งค่า cookie flags, และหลีกเลี่ยงการเก็บโทเค็นในบันทึก
ด้วย Koder.ai คุณสามารถสร้างเว็บแอป (React), บริการแบ็คเอนด์ (Go + PostgreSQL), หรือแอปมือถือ Flutter ผ่าน workflow แบบ chat—จากนั้นปรับซ้ำใน planning mode, ใช้ snapshots and rollback ขณะปรับแต่งความปลอดภัย และส่งออกซอร์สโค้ดเมื่อพร้อม มันเป็นวิธีที่เป็นประโยชน์ในการเร่งการสร้าง flows การยืนยันตัวตนด้วย JWT ในขณะที่ยังคงควบคุมการตรวจสอบกฎ การหมุนคีย์ และการตั้งค่า deployment/hosting (รวมถึง custom domains).
A JWT (JSON Web Token) is a compact, URL-safe string that carries claims (data fields) and can be verified by a server. It’s commonly sent on API requests via:
Authorization: Bearer \u003ctoken\u003eThe key idea: the server can validate the token’s integrity (via its signature) without needing a per-user session record for every request.
Session auth typically stores state on the server (a session record keyed by a cookie/session ID). With JWT-based auth, the client presents a signed token each request, and the API validates it.
JWTs are popular for APIs and multi-service architectures because verification can be done locally, reducing shared session storage needs.
“Stateless” still often includes server-side checks like revocation lists, user status checks, or key rotation handling.
A JWT is three Base64URL-encoded parts separated by dots:
header.payload.signatureThe header describes how it was signed, the payload contains claims (like sub, exp, aud), and the signature lets the server detect tampering.
No. Standard JWTs are usually signed, not encrypted.
If you need confidentiality, consider JWE (encrypted tokens) or keep sensitive data server-side and store only an identifier in the JWT.
The signature lets the server verify the token hasn’t been altered and was minted by someone with the signing key.
It does not:
expTreat the token like a credential: if it leaks, it can often be replayed until it expires.
alg tells the verifier which algorithm was used (e.g., HS256 vs RS256). kid is a key identifier that helps pick the right verification key during key rotation.
Security rules of thumb:
Start with standard registered claims and keep custom ones minimal.
Common registered claims:
JWT is a token format; OAuth 2.0 and OpenID Connect are protocols.
Typical mapping:
For browser-based apps, common options are:
localStorage/sessionStorage: convenient, but any XSS can exfiltrate tokens.At minimum, validate:
exp (not expired)iss (expected issuer)aud (meant for your API)nbf (if present)Also add practical guardrails:
alg values.alg: "none".kid value cause unsafe key lookup behavior.iss (issuer)sub (subject / user identifier)aud (audience / intended API)exp (expiration)iat (issued at)nbf (not before)Avoid putting secrets or sensitive personal data in the payload, since it’s readable if the token is exposed.
Important: don’t use an ID token to call an API just because it “looks like” a JWT access token.
SameSiteWhatever you choose, keep access tokens short-lived and minimize token privileges.