JWT (JSON Web Token) คือรูปแบบขนาดกะทัดรัดสำหรับการถ่ายโอนข้อมูลระหว่างฝ่ายต่างๆ ในรูปแบบวัตถุ JSON ที่ได้รับการป้องกันด้วยลายเซ็นดิจิทัล โทเค็นสามารถลงนามได้โดยใช้ HMAC (คีย์สมมาตร) หรือ RSA/ECDSA (คู่อสมมาตร) ซึ่งรับประกันความสมบูรณ์และความถูกต้องของข้อมูล ตาม IETF RFC 7519, 2015 JWT ถูกใช้ในแอปพลิเคชันนับล้านสำหรับการยืนยันตัวตน การแลกเปลี่ยน claims อย่างปลอดภัย และเป็นรูปแบบ ID Token ใน OpenID Connect
ประเด็นสำคัญ
JSON Web Token (JWT) คือมาตรฐานเปิด (RFC 7519) ที่กำหนดวิธีการส่งข้อมูลระหว่างฝ่ายต่างๆ ในรูปแบบวัตถุ JSON ที่กะทัดรัดและพึ่งพาตนเองได้ ข้อมูลใน JWT เรียกว่า claims — ข้อความเกี่ยวกับหัวเรื่อง (ผู้ใช้) และคุณลักษณะเพิ่มเติม แต่ละ claim คือคู่คีย์-ค่า: ตัวระบุผู้ใช้ บทบาท เวลาหมดอายุ ผู้ออก
JWT ถูกเรียกว่าพึ่งพาตนเองได้เพราะข้อมูลทั้งหมดที่จำเป็นสำหรับการตรวจสอบอยู่ภายในโทเค็นเอง เซิร์ฟเวอร์ไม่จำเป็นต้องเข้าถึงฐานข้อมูลหรือพื้นที่จัดเก็บภายนอกเพื่อตรวจสอบความถูกต้องของโทเค็น — เพียงแค่ตรวจสอบลายเซ็น คุณสมบัตินี้ทำให้ JWT เหมาะสำหรับ ระบบกระจาย และสถาปัตยกรรมไมโครเซอร์วิส ซึ่งบริการหลายรายการต้องยืนยันตัวตนคำขอโดยไม่มีพื้นที่จัดเก็บเซสชันร่วมกัน
ตาม Auth0, 2025 มากกว่า 65% ของแอปพลิเคชันมือถือและเว็บใช้ JWT เป็นรูปแบบโทเค็นหลักสำหรับการยืนยันตัวตน API แซงหน้าโทเค็นทึบแสงและตัวระบุเซสชัน
JWT ประกอบด้วยสามส่วนคั่นด้วยจุด: header.payload.signature แต่ละส่วนคือ JSON ที่เข้ารหัส Base64url มาดูแต่ละส่วนโดยละเอียด
Header ประกอบด้วยสองฟิลด์ที่จำเป็น: alg (algorithm — อัลกอริทึมการลงนาม) และ typ (type — ประเภทโทเค็น, เสมอ “JWT”) อัลกอริทึมสามารถสมมาตร (HS256 — HMAC กับ SHA-256) หรืออสมมาตร (RS256 — RSA กับ SHA-256, ES256 — ECDSA กับ P-256) อัลกอริทึมอสมมาตรเป็นที่นิยมเพราะอนุญาตให้ไคลเอนต์ตรวจสอบลายเซ็นโดยไม่ต้องมีคีย์ลับ
ตัวอย่างของ header ที่ถอดรหัสแล้ว:
{
"alg": "RS256",
"typ": "JWT",
"kid": "key-id-1"
}
Payload ประกอบด้วย claims — ข้อความเกี่ยวกับหัวเรื่อง Claims แบ่งออกเป็นสามประเภท: ลงทะเบียน (iss, sub, aud, exp, nbf, iat, jti), สาธารณะ (กำหนดโดยนักพัฒนาใน IANA Registry) และส่วนตัว (ตกลงกันระหว่างฝ่าย) sub (subject) คือตัวระบุผู้ใช้ที่ไม่ซ้ำกัน exp (expiration) คือการประทับเวลาหมดอายุของโทเค็น iss (issuer) คือผู้ออกโทเค็น
{
"sub": "user-abc-123",
"iss": "https://auth.example.com",
"aud": "my-mobile-app",
"exp": 1812345678,
"iat": 1812342078,
"role": "premium_user"
}
Signature ถูกสร้างขึ้นโดยใช้อัลกอริทึมการลงนามกับการต่อกันของ header และ payload โดยใช้คีย์ลับหรือคีย์ส่วนตัว สูตร: HMACSHA256(base64UrlEncode(header) + “.” + base64UrlEncode(payload), secret) สำหรับ HMAC หรือ RSASHA256(...) สำหรับอัลกอริทึมอสมมาตร ผู้รับคำนวณลายเซ็นด้วยวิธีเดียวกันและเปรียบเทียบกับลายเซ็นที่ได้รับ — หากตรงกัน แสดงว่าข้อมูลไม่ถูกเปลี่ยนแปลง
ขั้นตอนการทำงาน กับ JWT ประกอบด้วยสองระยะ: การสร้าง (การออก) โทเค็นโดยเซิร์ฟเวอร์ยืนยันตัวตนและการตรวจสอบโทเค็นโดยไคลเอนต์หรือเซิร์ฟเวอร์ทรัพยากร เซิร์ฟเวอร์ยืนยันตัวตนรับข้อมูลรับรองผู้ใช้ สร้าง payload พร้อม claims และลงนาม JWT ที่ได้จะถูกส่งไปยังไคลเอนต์เพื่อตอบสนองต่อคำขอเข้าสู่ระบบหรือในเนื้อหาการตอบสนอง OAuth 2.0 / OpenID Connect
ในแอปพลิเคชันมือถือ JWT ถูกใช้ดังนี้: หลังจากการเข้าสู่ระบบสำเร็จ ผู้ใช้จะได้รับโทเค็นการเข้าถึงในรูปแบบ JWT แอปพลิเคชันจัดเก็บไว้ในพื้นที่จัดเก็บที่ปลอดภัย (Keychain บน iOS, EncryptedSharedPreferences บน Android) ทุกคำขอ API แอปพลิเคชันจะเพิ่มส่วนหัว Authorization: Bearer <token> เซิร์ฟเวอร์ API ตรวจสอบลายเซ็น JWT ดึง claims และตัดสินใจการเข้าถึงตาม claims เหล่านั้น — โดยไม่ต้องสอบถามฐานข้อมูล
ตาม Google Codelabs, 2025 การใช้ JWT ใน Firebase Authentication ช่วยลดจำนวนคำขอไปยังเซิร์ฟเวอร์ยืนยันตัวตนลง 40–60% เมื่อเทียบกับโทเค็นเซสชัน เนื่องจากข้อมูลถูกตรวจสอบในเครื่องบนแต่ละไมโครเซอร์วิส ซึ่งสำคัญโดยเฉพาะสำหรับสถาปัตยกรรมที่มีโหลดสูง ทุกมิลลิวินาทีของความหน่วงส่งผลต่อประสบการณ์ผู้ใช้ ที่ 50,000 คำขอต่อนาที การเปลี่ยนไปใช้ JWT สามารถประหยัดอินสแตนซ์เซิร์ฟเวอร์ได้ถึง 10 ตัวที่จัดการคำขอตรวจสอบภายใน
JWT และ Session Token แก้ปัญหาเดียวกัน — การยืนยันตัวตนคำขอ — แต่แตกต่างกันโดยพื้นฐานในสถาปัตยกรรม Session Token คือสตริงตัวระบุแบบสุ่มที่อ้างถึงข้อมูลเซสชันที่เก็บไว้บนเซิร์ฟเวอร์ (มีสถานะ) JWT คือโทเค็นแบบพึ่งพาตนเองได้ซึ่งมีข้อมูลทั้งหมดอยู่ภายใน (ไร้สถานะ)
| พารามิเตอร์ | JWT | Session Token |
|---|---|---|
| การจัดเก็บข้อมูล | ภายในโทเค็น (พึ่งพาตนเอง) | บนเซิร์ฟเวอร์ (พื้นที่เก็บเซสชัน) |
| การปรับขนาด | ไม่ต้องการพื้นที่เก็บข้อมูลร่วมกัน | ต้องการ Redis/ฐานข้อมูลสำหรับหลายเซิร์ฟเวอร์ |
| การเพิกถอนโทเค็น | ซับซ้อน (ต้องการบัญชีดำ) | ง่าย (ลบเซสชันจากฐานข้อมูล) |
| ขนาด | ใหญ่ (500–2000 ไบต์) | เล็ก (16–64 ไบต์) |
| การตรวจสอบลายเซ็น | การเข้ารหัส | ไม่มี (การเปรียบเทียบสตริง) |
JWT ชนะในระบบกระจาย: ไมโครเซอร์วิสสามารถตรวจสอบโทเค็นในเครื่องโดยไม่ต้องมีพื้นที่เก็บข้อมูลร่วมกัน ตัวอย่างเช่น ในสถาปัตยกรรมที่มีห้าไมโครเซอร์วิส แต่ละบริการตรวจสอบ JWT ใน 1–2 มิลลิวินาทีโดยไม่ต้องเรียกเครือข่าย ในขณะที่ session token ต้องการการสอบถาม Redis จากส่วนกลางทุกคำขอ เพิ่มความหน่วง 10–30 มิลลิวินาที อย่างไรก็ตาม JWT ยากต่อการเพิกถอน — เมื่อออกแล้วจะใช้ได้จนกว่าจะหมดอายุ Session Token สามารถเพิกถอนได้ง่ายโดยการลบเรกคอร์ดจากฐานข้อมูลหรือ Redis
สำหรับแอปพลิเคชันมือถือ วิธีการแบบผสมผสาน — JWT อายุสั้น (15–30 นาที) และ Refresh Token — ให้ความสมดุลระหว่างประสิทธิภาพและความปลอดภัย JWT ใช้สำหรับการเข้าถึง API ในขณะที่ refresh token (มักทึบแสง) ใช้เพื่อรับ JWT ใหม่ หาก JWT ถูกบุกรุก ผู้โจมตีสามารถเข้าถึงได้ 15–30 นาที หาก refresh token ถูกบุกรุก เซสชันจะถูกบล็อกผ่านการหมุนเวียนและการตรวจจับการใช้ซ้ำ
ความปลอดภัย ของ JWT ขึ้นอยู่กับการใช้งานที่ถูกต้อง ช่องโหว่ที่พบบ่อยที่สุดคือการโจมตี “alg none”: ผู้โจมตีเปลี่ยน header ของโทเค็นเป็น “alg”: “none” และเซิร์ฟเวอร์โดยไม่ตรวจสอบอัลกอริทึม ยอมรับโทเค็นปลอม การป้องกัน: ตรวจสอบเสมอว่าอัลกอริทึมใน header ตรงกับที่คาดไว้ (RS256, ES256) และปฏิเสธโทเค็นที่มี alg: none
ช่องโหว่ของ JWT ยังรวมถึง: คีย์ลับที่อ่อนแอสำหรับ HMAC (ถูกรู้ในไม่กี่นาที), การรั่วไหลของคีย์ส่วนตัว (การลงนามข้อมูลใดๆ ในนามของเซิร์ฟเวอร์), การจัดเก็บข้อมูลที่ละเอียดอ่อนใน payload (JWT ไม่ได้เข้ารหัส ลงนามเท่านั้น), การโจมตีแบบฉีด JWK header (การฉีดคีย์สาธารณะที่กำหนดเอง) การใช้ไลบรารีที่เชื่อถือได้ — Nimbus JOSE + JWT, jjwt (io.jsonwebtoken), PyJWT — ลดความเสี่ยงของการใช้ประโยชน์จากช่องโหว่เหล่านี้
มาตรการรักษาความปลอดภัยเพิ่มเติมคือ JWK Thumbprint (RFC 7638): การผูกคีย์สาธารณะกับโทเค็นผ่านลายนิ้วมือ (thumbprint) ใน header หากเซิร์ฟเวอร์จัดเก็บลายนิ้วมือที่คาดไว้สำหรับแต่ละไคลเอนต์ การฉีด JWK header จะเป็นไปไม่ได้ — เซิร์ฟเวอร์ปฏิเสธคีย์ใดๆ ที่ไม่ตรงกับที่ลงทะเบียนไว้ OAuth Security Workshop 2025 แนะนำ JWK Thumbprint เป็นการป้องกันบังคับสำหรับ JWT ทั้งหมดที่ใช้ในแอปพลิเคชันทางการเงินและการแพทย์
ไลบรารี jjwt (auth0/java-jwt) ช่วยให้สร้างและตรวจสอบ JWT ในแอปพลิเคชัน Android ได้ในไม่กี่บรรทัด ในตัวอย่างด้านล่าง เซิร์ฟเวอร์สร้างโทเค็นด้วย sub และ role และไคลเอนต์ตรวจสอบลายเซ็น สำหรับการจัดเก็บคีย์ลับบนเซิร์ฟเวอร์อย่างปลอดภัย ให้ใช้ตัวแปรสภาพแวดล้อมหรือ HSM (โมดูลความปลอดภัยฮาร์ดแวร์) — การจัดเก็บคีย์ในโค้ดหรือไฟล์การกำหนดค่าเป็นข้อผิดพลาดด้านความปลอดภัยที่ร้ายแรง
val secret = "my-256-bit-secret-key-here"
val token = JWT.create()
.withSubject("user-abc-123")
.withIssuer("auth.example.com")
.withClaim("role", "premium_user")
.withExpiresAt(Date(System.currentTimeMillis() + 3600000))
.sign(Algorithm.HMAC256(secret))
// กำลังส่งโทเค็นไปยังไคลเอนต์
println("JWT: $token")
fun verifyToken(token: String): Boolean {
return try {
val decoded = JWT.require(Algorithm.HMAC256(secret))
.withIssuer("auth.example.com")
.build()
.verify(token)
// ลายเซ็นถูกต้อง, claims ถูกดึงออกมาแล้ว
println("Subject: ${decoded.subject}")
true
} catch (e: Exception) {
println("โทเค็นไม่ถูกต้อง: ${e.message}")
false
}
}
คำถามที่พบบ่อย
ไม่ JWT ถูกลงนาม ไม่ได้ถูกเข้ารหัส — ทุกคนสามารถถอดรหัส Base64 payload และอ่านข้อมูลได้ ข้อมูลที่ละเอียดอ่อน (รหัสผ่าน หมายเลขบัตร ข้อมูลส่วนบุคคล) ต้องถูกส่งในรูปแบบที่เข้ารหัสเท่านั้นผ่าน JWE (JSON Web Encryption)
แนะนำ ES256 (ECDSA กับ P-256) — ให้ระดับความปลอดภัยเทียบเท่า RSA 2048-bit โดยมีขนาดลายเซ็นเล็กกว่าอย่างมีนัยสำคัญ RS256 เหมาะสำหรับความเข้ากันได้กับระบบเดิม HS256 (HMAC) ต้องการการแลกเปลี่ยนคีย์ลับที่ปลอดภัย ซึ่งยากกว่าในสถาปัตยกรรมแบบกระจาย
JWT ไม่สามารถเพิกถอนได้โดยตรง — ใช้ได้จนถึง exp วิธีแก้ไข: ใช้อายุสั้น (15–30 นาที) ดูแล บัญชีดำของ jti (JWT ID) ที่ถูกเพิกถอนบนเซิร์ฟเวอร์ หรือผูกโทเค็นกับเวอร์ชันคีย์ลับ Refresh token จะถูกเพิกถอนด้วยวิธีมาตรฐาน — โดยการลบออกจากพื้นที่จัดเก็บ
Bearer token เป็นแนวคิด: โทเค็นใดๆ ที่ผู้ถือสามารถใช้เพื่อการเข้าถึง JWT เป็นรูปแบบโทเค็นเฉพาะ Bearer token อาจเป็น JWT หรือสตริงทึบแสง JWT เพิ่มความสามารถในการพึ่งพาตนเองและการตรวจสอบด้วยการเข้ารหัสให้กับแนวคิด Bearer
JWT ทั่วไปที่มีลายเซ็น RS256 มีขนาด 500–2000 ไบต์ หาก payload มี claims ที่กำหนดเองจำนวนมากหรือใช้ลายเซ็นอสมมาตรกับคีย์ขนาดใหญ่ ขนาดอาจถึง 4–5 KB ซึ่งใหญ่กว่า session token (16–64 ไบต์) อย่างมีนัยสำคัญ ส่งผลต่อขนาดของส่วนหัว HTTP
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ
อ่านเพิ่มเติม