ถอดรหัส ตรวจสอบ และสร้าง JWT

Encoded Token172 charsอัปเดตเมื่อ 2026-07
header
payload
signature
Valid JWTHS256
Secret38 chars
Header
{
  "alg": "HS256",
  "typ": "JWT"
}
Payload
{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true,
  "iat": 1516239022
}
Claims details4 items
sub· หัวเรื่อง1234567890
name· NameJohn Doe
admin· Admintrue
iat· เวลาออก token151623902218/01/2561 09:30:22
Header details2 items
algHS256HMAC (สมมาตร)
typ· TypeJWT
All operations run locally in your browser; the Token and key are never sent to any server.

พื้นที่ทำงาน JWT ออนไลน์ฟรี: ถอดรหัส ตรวจสอบ และสร้าง JSON Web Token รองรับ 13 อัลกอริทึม (HS256 / RS256 / ES256 / PS256 / EdDSA ฯลฯ) คีย์ PEM และ JWK สร้างคู่คีย์อัตโนมัติ ถอด exp/iat/nbf โดยอัตโนมัติ 100% ฝั่งไคลเอนต์ — Token ไม่เคยออกจากเบราว์เซอร์ของคุณ

คำแนะนำที่เกี่ยวข้อง

ถอดรหัส ตรวจสอบ และสร้าง JWT คืออะไร?

JWT (JSON Web Token) เป็นมาตรฐานเปิดที่กำหนดโดย IETF ใน RFC 7519 (RFC 7515 อธิบายรูปแบบการเซ็น JWS, RFC 7516 อธิบายการเข้ารหัส JWE, RFC 7517 กำหนดคีย์ JWK) สำหรับการถ่ายโอน 'ข้อมูลที่อ้างถึง' ของผู้ใช้อย่างปลอดภัยระหว่างคำขอ HTTP, กระบวนการ OIDC และการเรียกไมโครเซอร์วิส สตริง JWT มาตรฐานประกอบด้วยสามส่วนที่เข้ารหัส Base64URL: Header (อัลกอริทึมและประเภท), Payload (Claims, ข้อมูลผู้ใช้) และ Signature (ลายเซ็นจากคีย์บนสองส่วนแรก) สามส่วนเชื่อมด้วยจุด `.` เช่น `eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0In0.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c`

**JWT ไม่ใช่การเข้ารหัส** นี่เป็นความเข้าใจผิดที่พบบ่อยที่สุด Payload เป็นข้อความธรรมดาโดยค่าเริ่มต้น — ใครๆ ก็สามารถถอดรหัส Base64URL และอ่านเนื้อหาได้ JWT ให้ **การตรวจจับการแก้ไข** ไม่ใช่ความลับ: เซิร์ฟเวอร์เซ็น Header.Payload ใหม่ด้วยคีย์ร่วมและเปรียบเทียบกับ Signature ของ Token หากตรงกัน แสดงว่า Token ไม่ถูกแก้ไขระหว่างทาง เปรียบเสมือน 'ตั๋วรถไฟพร้อมตราป้องกันการปลอม': ผู้ตรวจสอบสนใจว่าตั๋วเป็นของแท้หรือไม่ ไม่ใช่ QR Code อ่านไม่ออก

JWT แบ่งหน้าที่อย่างชัดเจนระหว่าง 13 อัลกอริทึม **ตระกูล HMAC** (HS256/HS384/HS512) ใช้คีย์สมมาตรสำหรับทั้งเซ็นและตรวจสอบ รวดเร็วและง่าย เหมาะสำหรับเซอร์วิสเดียวหรือคลัสเตอร์ที่เชื่อถือได้; Secret ต้องยาวอย่างน้อยเท่าความยาว digest (เช่น ≥ 32 ไบต์สำหรับ HS256) **ตระกูล RSA** (RS256/RS384/RS512) ใช้ RSASSA-PKCS1-v1_5 ซึ่งเป็นรูปแบบอสมมาตรที่พบบ่อยที่สุด — ผู้เซ็นถือคีย์ส่วนตัว ผู้ตรวจสอบถือคีย์สาธารณะ **ตระกูล RSA-PSS** (PS256/PS384/PS512) ใช้ padding RSA-PSS ที่ใหม่กว่าพร้อมการรับประกันความปลอดภัยที่เข้มแข็งกว่า AWS SigV4 และผู้ให้บริการ OIDC สมัยใหม่เลือกใช้ **ตระกูล ECDSA** (ES256/ES384/ES512) ใช้เส้นโค้งวงรี (P-256/P-384/P-521 ตามลำดับ) พร้อมลายเซ็นที่สั้นกว่าและประสิทธิภาพดีกว่า **EdDSA** (หลักๆ คือ Ed25519) รวดเร็วมากและเป็น deterministic (ข้อความเดิม + คีย์เดิม = ลายเซ็นเดิมทุกครั้ง) และเป็นอัลกอริทึมที่แนะนำใน OAuth 2.1 และโปรโตคอลใหม่

ความปลอดภัยคือจุดที่ JWT มักมีปัญหาในสภาพแวดล้อมการผลิต OWASP JWT Cheat Sheet ระบุกฎสำคัญอย่างน้อยสี่ข้อ: (1) ห้ามใส่รหัสผ่าน, เลขประจำตัวประชาชน, เลขบัตร หรือ API Key เป็นข้อความธรรมดาใน Payload เด็ดขาด; (2) เซิร์ฟเวอร์ต้อง **ไม่เชื่อถือฟิลด์ alg** ที่ประกาศใน Header ของ Token — ต้องตรวจสอบด้วยอัลกอริทึมที่กำหนดไว้ ไม่งั้นผู้โจมตีที่แก้ header เป็น `alg: none` จะผ่านได้ทั้งหมด (นี่คือรากของ CVE ในอดีตเช่น CVE-2015-9235); (3) HMAC Secret ต้องเป็นแบบสุ่มและยาวอย่างน้อย 32 ไบต์ ห้ามเป็นสตริงสั้น; (4) การตรวจสอบไม่ใช่แค่ลายเซ็น — ต้องตรวจสอบ `exp` (วันหมดอายุ), `nbf` (ยังไม่ก่อน), `iss` (ผู้ออก) และ `aud` (ผู้รับ) ด้วย เครื่องมือนี้เน้น Claims เหล่านี้ทั้งหมดใน UI เพื่อให้คุณเห็นได้ในทันทีว่าปัญหาคือลายเซ็น, เวลา หรือ Claims

JWT ไม่ใช่ตัวแทนของ session Session เก็บสถานะผู้ใช้บนเซิร์ฟเวอร์ (Redis หรือฐานข้อมูล); JWT บรรจุสถานะใน Token สถาปัตยกรรมไมโครเซอร์วิส, API แบบ stateless, ไคลเอนต์มือถือ และการตั้งค่าที่ใช้ CORS มากได้รับประโยชน์จาก JWT; ระบบองค์กรแบบดั้งเดิมและกระบวนการที่ต้องยกเลิกทันที (เช่น 'เตะผู้ใช้ออกตอนนี้') ยังเหมาะกับ session มากกว่า เครื่องมือนี้ครอบคลุมทั้งการดีบัก JWT ล้วนๆ และขั้นตอนการแยกวิเคราะห์ Token / ตรวจสอบลายเซ็น / แก้ไข Payload ในการย้ายจาก session เป็น JWT

กรณีการใช้งาน

  • ถอดรหัส JWT ออนไลน์: แยก Token อย่างรวดเร็วขณะดีบักการเข้าสู่ระบบ OAuth 2.0 / OIDC เพื่อดูอัลกอริทึม Header และ Claims ใน Payload
  • ตรวจสอบลายเซ็น JWT: ใช้ Secret / คีย์สาธารณะเพื่อตรวจสอบลายเซ็น Token แบบเรียลไทม์ และตัดสินใจว่า 401 เกิดจาก 'ลายเซ็นผิด', 'หมดอายุ' หรือ 'อัลกอริทึมไม่ตรงกัน'
  • สร้าง JWT ทดสอบระหว่างเชื่อมต่อ: ออก JWT บนเบราว์เซอร์ด้วยคู่คีย์ทดสอบ ไม่ต้องขอให้ Backend แก้โค้ดชั่วคราวเพื่อสร้าง Token
  • แปลง PEM ↔ JWK: OIDC IdP ให้ JWK แต่เซิร์ฟเวอร์ต้องการ PEM (หรือกลับกัน) — แปลงทันทีโดยไม่ต้องเขียนสคริปต์ OpenSSL
  • วินิจฉัย 401 Unauthorized: ตรวจสอบวันหมดอายุ, ความตรงกับ gateway ของ alg, ความตรงของคีย์ และการจัดรูปแบบ PEM ทีละขั้นตอน
  • เปรียบเทียบ RS256 กับ PS256: ผู้ให้บริการ OIDC หลายรายใช้ RS256 เป็นค่าเริ่มต้น ในขณะที่ AWS SigV4 ใช้ PS256 — สลับอัลกอริทึมด้วยคู่คีย์ RSA เดียวกันและเปรียบเทียบผลลัพธ์
  • เรียนรู้โครงสร้างภายใน JWT: เปลี่ยน alg, แก้ไข Payload, สลับคีย์บนเบราว์เซอร์และดูลายเซ็นพังแบบเรียลไทม์ — เร็วกว่าอ่าน RFC มาก

วิธีการใช้งาน

  1. วางหรือป้อน Token: วางสตริง JWT ในช่องป้อนข้อมูล เครื่องมือจะแยก Header, Payload และ Signature อัตโนมัติ และแสดงแต่ละส่วนเป็น JSON ที่จัดรูปแบบสวยงาม
  2. เลือกอัลกอริทึม: สลับระหว่าง HS256 / RS256 / ES256 / PS256 / EdDSA; เครื่องมือจะอนุมานจาก Header.alg และแจ้งเตือนหากไม่ตรงกัน
  3. นำเข้าคีย์: วาง HMAC Secret, สตริง PEM หรือ JWK JSON; สำหรับอัลกอริทึมแบบอสมมาตร คลิก 'สร้างคู่คีย์' เพื่อรับคีย์ทดสอบทันที
  4. ตรวจสอบหรือเซ็นใหม่: ในโหมด Decode ตรวจสอบด้วยคีย์สาธารณะและดู '✅ ลายเซ็นถูกต้อง / ❌ ลายเซ็นไม่ถูกต้อง'; ในโหมด Encode แก้ไข Claims และเซ็นด้วยคีย์ส่วนตัวเพื่อสร้าง Token ใหม่

Output Example

A real MP3 file encoded to a Data URI — copy-ready:

Header (Base64URL):  eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
Payload(Base64URL):  eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkphbmUgRG9lIiwiaWF0IjoxNzE2MjM5MDIyfQ
Signature:           kZJfaYjK3iCkVFL5EL9zGRZ5SmD8_x2h6B5c7pVFfVGo

ถอดรหัส Header:
  {
    "alg": "HS256",
    "typ": "JWT"
  }

ถอดรหัส Payload:
  {
    "sub": "1234567890",
    "name": "Jane Doe",
    "iat": 1716239022        // 2024-05-20 14:23:42 UTC
  }

คุณสมบัติ

  • ถอดรหัส + ตรวจสอบ + สร้าง ในที่เดียว: วาง Token เพื่อแยก Header/Payload/Signature สลับอัลกอริทึมและคีย์เพื่อตรวจสอบลายเซ็น แก้ไข Claims และเซ็นใหม่เพื่อสร้าง Token ใหม่ — ครอบคลุมทุกขั้นตอนการแก้ปัญหา JWT
  • รองรับ 13 อัลกอริทึม: HS256/HS384/HS512 (HMAC), RS256/RS384/RS512 (RSA-PKCS1-v1_5), ES256/ES384/ES512 (ECDSA), PS256/PS384/PS512 (RSA-PSS), EdDSA — ครอบคลุม OAuth 2.0, OIDC, JWS, API gateway และ SSO องค์กร
  • รูปแบบ PEM และ JWK: คีย์ RSA, ECDSA และ Ed25519 รองรับสตริง PEM (พร้อมส่วนหัว -----BEGIN PUBLIC KEY-----) และ JWK JSON (ฟิลด์ kid/kty/n/e) — วางเอาต์พุต OIDC /.well-known/jwks.json ได้โดยตรง
  • รูปแบบการป้อน HMAC Secret หลายแบบ: สตริง UTF-8, ไบต์ Hex หรือ Secret แบบ Base64/Base64URL — สลับได้ด้วยคลิกเดียว ไม่มีปัญหา 'ดูเหมือนเดิมแต่ลายเซ็นไม่ผ่าน'
  • สร้างคู่คีย์อัตโนมัติ: สร้างคู่คีย์ RSA-2048, RSA-4096, P-256, P-384 และ Ed25519 บนเบราว์เซอร์ แสดงทั้งรูปแบบ PEM และ JWK สำหรับใช้งานทดสอบทันที
  • เน้น Claims ตามความหมาย: แปลง exp / iat / nbf เป็นเวลาที่อ่านได้โดยอัตโนมัติ พร้อมเน้นสถานะ หมดอายุ / ยังไม่ใช้ได้ / ออกแล้ว; แยกแสดง alg / typ / kid ใน Header
  • 100% ฝั่งไคลเอนต์ ไม่อัปโหลด: การแยกวิเคราะห์ ตรวจสอบ และเซ็นทั้งหมดทำงานผ่าน Web Crypto API ของเบราว์เซอร์ — Token, คีย์ และ payload ไม่เคยออกจากเบราว์เซอร์ สอดคล้องกับหลักการ 'ไม่วาง Token ผลิตในเครื่องมือออนไลน์ที่ไม่รู้จัก'
  • คัดลอกด้วยคลิกเดียว: Header, Payload, Signature และ Token ที่สร้างใหม่สามารถคัดลอกแยกกันสำหรับเอกสาร,ตั๋ว และคำสั่ง curl

ตัวอย่างโค้ด

Node.js 50 บรรทัด: เซ็นและตรวจสอบ HS256 ด้วยมือ

javascript

สรุปกลไกหลักของ JWT: เข้ารหัส Header และ Payload เป็น Base64URL แล้วทำ HMAC-SHA256 บนสตริง `header.payload` ในสภาพแวดล้อมการผลิต ใช้ไลบรารีเช่น jsonwebtoken หรือ jose — โค้ดสั้นนี้มีไว้เพื่อให้ปัญหาเรื่องลายเซ็นสามารถดีบักได้

const crypto = require('node:crypto')

function b64url(input) {
  return Buffer.from(input)
    .toString('base64')
    .replace(/\+/g, '-')
    .replace(/\//g, '_')
    .replace(/=+$/, '')
}

function hmacSign(data, secret) {
  return b64url(crypto.createHmac('sha256', secret).update(data).digest())
}

function sign(payload, secret) {
  const header = b64url(JSON.stringify({ alg: 'HS256', typ: 'JWT' }))
  const body = b64url(JSON.stringify(payload))
  const signature = hmacSign(`${header}.${body}`, secret)
  return `${header}.${body}.${signature}`
}

function verify(token, secret) {
  const [h, p, s] = token.split('.')
  const expected = hmacSign(`${h}.${p}`, secret)
  const a = Buffer.from(s)
  const b = Buffer.from(expected)
  return a.length === b.length && crypto.timingSafeEqual(a, b)
}

const SECRET = 'my-super-secret-key'
const payload = { userId: 42, role: 'admin', exp: Math.floor(Date.now() / 1000) + 3600 }
const token = sign(payload, SECRET)

console.log(token)
console.log(verify(token, SECRET))       // true
console.log(verify(token, 'wrong-key'))  // false

ฝั่งเบราว์เซอร์: Web Crypto API สำหรับเซ็น HMAC

html

แนวคิดหลักของส่วนหน้าเครื่องมือนี้: ใช้ crypto.subtle ดั้งเดิมของเบราว์เซอร์สำหรับ HMAC, RSA, ECDSA, RSA-PSS และการตรวจสอบ Ed25519 — ไม่ต้องใช้ไลบรารีภายนอก วางโค้ดนี้ในหน้า HTML ใดๆ เพื่อสร้าง Token HS256

<!doctype html>
<html>
  <body>
    <pre id="out"></pre>
    <script>
      const out = document.getElementById('out')

      const b64url = buf =>
        btoa(String.fromCharCode(...new Uint8Array(buf)))
          .replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '')

      const b64urlStr = str => b64url(new TextEncoder().encode(str))

      async function sign(payload, secret) {
        const header = b64urlStr(JSON.stringify({ alg: 'HS256', typ: 'JWT' }))
        const body = b64urlStr(JSON.stringify(payload))
        const data = new TextEncoder().encode(`${header}.${body}`)

        const key = await crypto.subtle.importKey(
          'raw',
          new TextEncoder().encode(secret),
          { name: 'HMAC', hash: 'SHA-256' },
          false,
          ['sign']
        )

        const sig = await crypto.subtle.sign('HMAC', key, data)
        return `${header}.${body}.${b64url(sig)}`
      }

      ;(async () => {
        const token = await sign({ user: 'alice', role: 'admin' }, 'browser-demo-secret')
        out.textContent = token
      })()
    </script>
  </body>
</html>

Node.js: ตรวจสอบ RS256 ด้วย jose (วิธีที่ถูกต้อง)

javascript

ในโค้ดจริง ใช้ไลบรารีที่สมบูรณ์เช่น jose, jsonwebtoken หรือ PyJWT — อย่าเขียนเอง โค้ดสั้นนี้แสดงวิธี jose ตรวจสอบ Token RS256 และพิมพ์เหตุผลความล้มเหลวเมื่อเกิดข้อผิดพลาด (alg ไม่ตรง, ลายเซ็นผิด, หมดอายุ, ไม่พบ kid ฯลฯ)

import { jwtVerify, importSPKI } from 'jose'
import { readFile } from 'node:fs/promises'

const token = 'eyJhbGciOiJSUzI1NiIsImtpZCI6IjEifQ.payload.signature'
const publicKeyPem = await readFile('public.pem', 'utf8')

try {
  const { payload, protectedHeader } = await jwtVerify(
    token,
    await importSPKI(publicKeyPem, 'RS256'),
    {
      issuer: 'https://idp.example.com',
      audience: 'my-app',
      algorithms: ['RS256'],     // สำคัญ: รายการอนุญาตอัลกอริทึมบล็อกการโจมตี alg:none และแทนที่ HS256
    }
  )
  console.log('alg =', protectedHeader.alg)
  console.log('sub  =', payload.sub)
} catch (err) {
  console.error('verify failed:', err.code, err.message)
  // พบบ่อย: ERR_JWT_EXPIRED / ERR_JWS_INVALID / ERR_JWS_SIGNATURE_VERIFICATION_FAILED
}

Python: แยกวิเคราะห์ Token และพิมพ์ Claims ด้วย PyJWT

python

วิธีที่พบบ่อยที่สุดในการดีบัก JWT ฝั่ง Python decode() ของ PyJWT จะตรวจสอบ exp / nbf / iat โดยค่าเริ่มต้นและส่งคืนผลลัพธ์เป็น dict ธรรมดา

import jwt

token = 'eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0In0.SflKxw'

# แยกวิเคราะห์ (ไม่ตรวจสอบลายเซ็น แค่ดู Header และ Payload)
print(jwt.get_unverified_header(token))
# {'alg': 'HS256', 'typ': 'JWT'}

print(jwt.decode(token, options={'verify_signature': False}))
# {'sub': '1234'}

# ตรวจสอบเต็มรูปแบบ
claims = jwt.decode(
    token,
    'my-super-secret-key',
    algorithms=['HS256'],
    audience='my-app',
    issuer='my-service',
)
print(claims['sub'])

เปรียบเทียบอัลกอริทึมลายเซ็น JWT 5 ประเภท: ควรเลือกอันไหน?

JWT ไม่ใช่อัลกอริทึมเดียว — 5 ประเภทของอัลกอริทึมมีข้อดีข้อเสียต่างกันในด้านกุญแจ ประสิทธิภาพ ความปลอดภัย และความเข้ากันได้ กำหนดสถานการณ์ก่อนแล้วค่อยเลือกอัลกอริทึมจะช่วยหลีกเลี่ยงการหลงทางได้มาก

อัลกอริทึมประเภทกุญแจประสิทธิภาพสถานการณ์ทั่วไปข้อควรระวัง
HS256HMAC แบบสมมาตรSecret เดียวกันเร็วมากภายในคลัสเตอร์บริการ สภาพแวดล้อมที่เชื่อถือได้ แอปแบบโมโนลิธห้ามเปิดเผย Secret ให้ฝ่ายตรวจสอบ; ต้องสุ่มอย่างน้อย 32 ไบต์
RS256RSA แบบอสมมาตรลายเซ็นด้วยกุญแจส่วนตัว / ตรวจสอบด้วยกุญแจสาธารณะปานกลางOIDC, API Gateway, SSO องค์กร, ต้องแยกกุญแจสาธารณะ-ส่วนตัวใช้ RSASSA-PKCS1-v1_5 ต้องกำหนด padding ให้คงที่ข้ามภาษา
PS256RSA-PSS แบบอสมมาตรลายเซ็นด้วยกุญแจส่วนตัว / ตรวจสอบด้วยกุญแจสาธารณะปานกลางAWS SigV4, AWS Cognito, OIDC IdP ยุคใหม่ต้องระบุ saltLength อย่างชัดเจน (OpenSSL/jose=32, Go=ความยาว hash)
ES256ECDSA แบบอสมมาตรลายเซ็นด้วยกุญแจส่วนตัว / ตรวจสอบด้วยกุญแจสาธารณะเร็ว + ลายเซ็นสั้นApple Sign in with Apple, มือถือ, สถานการณ์แบนด์วิดท์ต่ำเส้นโค้ง (P-256/P-384/P-521) ต้องตรงกับเซิร์ฟเวอร์
EdDSAEd25519/Ed448ลายเซ็นด้วยกุญแจส่วนตัว / ตรวจสอบด้วยกุญแจสาธารณะเร็วมาก (ลายเซ็นเชิงกำหนด)OAuth 2.1, โปรโตคอลใหม่, การตรวจสอบความถี่สูงWeb Crypto รองรับ Ed25519; Ed448 ยังไม่เปิดใช้ในทุกแพลตฟอร์ม

Best Practices

อย่าวาง Secret / กุญแจส่วนตัวของระบบจริงในเครื่องมือออนไลน์ใดๆ

แม้เครื่องมือนี้ทำงาน 100% ภายในเบราว์เซอร์ (ไม่อัปโหลด Token หรือกุญแจใดๆ) แต่เมื่อติดนิสัยการดีบักแล้ว มักเกิดการวาง Secret / กุญแจส่วนตัว / Access Token ระยะยาวของระบบจริงลงในเครื่องมือออนไลน์ที่ไม่รู้จัก หรือรั่วไหลผ่านภาพหน้าจอโดยไม่ตั้งใจ Token ระยะยาว (Refresh Token, กุญแจส่วนตัวของระบบจริง, API Key) ต้องจัดการในสภาพแวดล้อมที่ควบคุมได้ในเครื่องส่วนตัว เครื่องมือนี้เหมาะสำหรับดีบัก Access Token ระยะสั้น คู่กุญแจทดสอบ และเรียนรู้โครงสร้าง JWT เท่านั้น

OWASP JSON Web Token Cheat Sheet (ภาษาอังกฤษ)

เซิร์ฟเวอร์ต้องกำหนด allowlist ของอัลกอริทึม ไม่ควรเชื่อ Token Header.alg

การโจมตีแบบ alg: none (CVE-2015-9235 เป็นต้น) และการโจมตีแบบสลับ HS256 (ใช้กุญแจสาธารณะเป็น Secret เพื่อหลอกเซิร์ฟเวอร์ RSA) มีรากมาจากเซิร์ฟเวอร์ที่เลือกตรรกะการตรวจสอบตามอัลกอริทึมที่ระบุใน Header โค้ดของระบบจริงต้อง hardcode allowlist เช่น `algorithms: ['RS256']` ห้ามให้ Token เป็นคนเลือกอัลกอริทึมเอง ระหว่างดีบักหากพบว่า Header.alg ไม่ตรงกับที่เซิร์ฟเวอร์คาดไว้ ให้สงสัยการตั้งค่าเซิร์ฟเวอร์ก่อน ไม่ใช่เนื้อหาของ Token

HS256 Secret ต้องเป็นค่าสุ่มอย่างน้อย 32 ไบต์

HS256 ใช้ HMAC-SHA256 หากความยาวกุญแจสั้นกว่าความยาว digest (32 ไบต์) ต้นทุนของการ brute-force จะลดลงอย่างมาก ห้ามใช้สตริงสั้นๆ เช่น `'my-secret'`, `'password123'` หรือการต่อชื่อธุรกิจ/ชื่อบริษัท/ปี วิธีมาตรฐาน: สร้างด้วย `openssl rand -base64 32` หรือ `crypto.randomBytes(32).toString('base64url')` เก็บไว้ใน environment variable / KMS / บริการจัดการกุญแจ ห้ามเขียนลงในโค้ดโดยเด็ดขาด

สามารถเก็บข้อมูลที่ละเอียดอ่อนใน JWT ได้ไหม?

JWT ระบบจริงต้องตรวจ exp / nbf / iat / iss / aud ไม่ใช่แค่ลายเซ็น

ลายเซ็นผ่านพิสูจน์แค่ว่า "ยังไม่ถูกแก้ไข" แต่ไม่ได้พิสูจน์ว่า "ยังไม่หมดอายุ", "ออกโดย IdP นี้จริง", "ออกให้แอปนี้จริง" ในระบบจริงต้องบังคับตรวจ Claim ที่เกี่ยวข้องทั้งหมด exp (หมดอายุ), nbf (เวลาเริ่มมีผล), iat (เวลาออก), iss (ผู้ออก), aud (ผู้รับ) ขาดไม่ได้แม้แต่ข้อเดียว OWASP กำหนดให้ 4-5 รายการนี้เป็นข้อตรวจสอบบังคับ การตรวจแค่ลายเซ็นโดยไม่ตรวจเวลาเป็นรากเหง้าของเหตุการณ์รั่วไหลของ Token จำนวนมาก (refresh token ไม่มีวันหมดอายุ)

แบ่งชั้นเวลาหมดอายุของ Token: Access 15-30 นาที, Refresh 7-30 วัน

Access Token ใช้สำหรับเรียก API ยิ่งหมดอายุเร็วยิ่งปลอดภัย (หากรั่วไหลก็ใช้ไม่ได้อีกทันที) Refresh Token ใช้สำหรับแลก Access Token อาจมีอายุยาวได้แต่ต้องเก็บฝั่งเซิร์ฟเวอร์และเพิกถอนได้ ค่าประสบการณ์ทั่วไป: Access 15-30 นาที, Refresh 7-30 วัน ใช้ร่วมกับ Refresh Token Rotation (ทุกครั้งที่ใช้ Refresh แลก Access ให้ออก Refresh ใหม่ด้วย และเพิกถอน Refresh เก่าทันที) จะช่วยสมดุลระหว่างการตรวจจับการรั่วไหลกับประสบการณ์ผู้ใช้

Stateless vs Stateful: JWT ไม่ใช่ตัวทดแทน Session

JWT ใส่สถานะไว้ใน Token จึงรองรับการขยายแนวนอนของไมโครเซอร์วิสและข้ามโดเมน CORS ได้อย่างเป็นธรรมชาติ แต่ต้นทุนการเพิกถอนสูง (ต้องใช้ blacklist หรืออายุสั้น) Session เก็บสถานะไว้ที่ Redis/DB ฝั่งเซิร์ฟเวอร์ ทำให้ "เตะผู้ใช้ออกได้" แต่ต้องมีพื้นที่จัดเก็บร่วม **ไม่ใช่เลือกอย่างใดอย่างหนึ่ง**: Access JWT ระยะสั้น + บันทึกเซสชัน Refresh Token ฝั่งเซิร์ฟเวอร์ เป็นรูปแบบไฮบริดที่พบบ่อยที่สุด ซึ่งได้ทั้งการขยายแบบ stateless และการเพิกถอนทันที ระบบหลักของการเงิน/รัฐบาลที่ต้องเพิกถอนได้ทันทีควรใช้ JWT ล้วนอย่างระมัดระวัง

สามารถเก็บข้อมูลที่ละเอียดอ่อนใน JWT ได้ไหม?

Payload เป็นข้อความธรรมดาที่อ่านได้ตามค่าเริ่มต้น ห้ามใส่ข้อมูลละเอียดอ่อนลงใน JWT

JWT (JWS) ไม่เข้ารหัส Payload โดยค่าเริ่มต้น ผู้ที่มี Token สามารถถอดรหัส Base64URL แล้วอ่านเนื้อหาได้ทันที **ห้ามเด็ดขาด** ใส่รหัสผ่าน เลขประจำตัวประชาชน เลขบัตรเครดิต API Key Access Token หรือ Refresh Token ลงใน Payload JWT เหมาะกับ Claim ที่ไม่ละเอียดอ่อน (รหัสผู้ใช้ บทบาท เวลาหมดอายุ รหัสผู้เช่า) ข้อมูลละเอียดอ่อนควรให้เซิร์ฟเวอร์ค้นจาก `sub` หากต้องเข้ารหัส Payload ให้ใช้ JWE (RFC 7516) แต่ประสิทธิภาพช้าลง 2-5 เท่า และการจัดการกุญแจยุ่งยากขึ้น — ให้เลือกรูปแบบ "Claim ที่ไม่ละเอียดอ่อน + การค้นฝั่งเซิร์ฟเวอร์" ก่อน

JWT คืออะไร?

RSA-PSS (PS256/PS384/PS512) เมื่อทำงานข้ามภาษา ต้องกำหนด saltLength ให้แน่นอนก่อน

RS256 และ PS256 ไม่สามารถตรวจสอบซึ่งกันและกันได้ (padding ต่างกัน) PS256 ยังมีกับดักที่พบบ่อยอีกอย่าง: พารามิเตอร์ `saltLength` OpenSSL ค่าเริ่มต้น 32 ไบต์, Node jose ค่าเริ่มต้น 32 ไบต์, Python PyJWT ค่าเริ่มต้นเท่ากับความยาว hash (SHA-256=32), Go ค่าเริ่มต้น `rsa.PSSSaltLengthEqualsHash` เมื่อทำงานข้ามภาษา ต้องกำหนดค่าเดียวกันก่อน (แนะนำ 32 ไบต์) มิฉะนั้น PS256 Token ที่ลงนามด้วยคู่กุญแจ RSA เดียวกันจะตรวจสอบไม่ผ่านในภาษาอื่น

การตรวจสอบลายเซ็น RS256 และ PS256 ล้มเหลวข้ามภาษา

ขั้นตอนการดีบัก: ใช้คู่กุญแจทดสอบ อย่าแตะระบบจริง

ระหว่างการเชื่อมต่อหรือพัฒนาในเครื่อง ต้องสร้างคู่กุญแจทดสอบใหม่เสมอ (HS256 ใช้ Secret แบบสุ่ม, RS256/ES256/EdDSA ใช้คู่กุญแจที่เครื่องมือสร้างให้ด้วยปุ่มเดียว) ห้ามนำกุญแจส่วนตัวของ IdP ระบบจริงหรือ Secret โดเมนบริษัทกลับมาใช้ซ้ำ เมื่อดีบักหรือทดสอบในเครื่องเสร็จแล้ว ให้ทำลายกุญแจทดสอบทันที ฟีเจอร์ "สร้างคู่กุญแจ" ของเครื่องมือนี้ออกแบบมาเพื่อจุดประสงค์นี้โดยเฉพาะ — RSA-2048/4096, P-256/P-384, Ed25519 สร้างได้ด้วยปุ่มเดียว พร้อมใช้งาน และทิ้งได้ทันทีหลังการเชื่อมต่อเสร็จสิ้น

การสร้าง JWT ทดสอบสำหรับเชื่อมต่อ

คำถามที่พบบ่อย

JWT ประกอบด้วยสามส่วนอะไรบ้าง?

สตริง JWT ประกอบด้วยสามส่วน `Header.Payload.Signature` แต่ละส่วนเข้ารหัส Base64URL Header ประกาศอัลกอริทึม (เช่น HS256, RS256) และประเภท Token (typ: JWT); Payload นำ Claims ของผู้ใช้ ฟิลด์ทั่วไปคือ sub (ID ผู้ใช้), iat (เวลาออก), exp (เวลาหมดอายุ), nbf (ยังไม่ก่อน), aud (ผู้รับ), iss (ผู้ออก); Signature เป็นผลลัพธ์ของการเซ็นสองส่วนแรกด้วยคีย์ มีวัตถุประสงค์เพื่อ 'ตรวจจับการแก้ไข' ไม่ใช่ 'ป้องกันการดักฟัง'

สามารถแก้ไข Payload หลังจากถอดรหัส JWT ได้ไหม?

ดูและแก้ไขได้ แต่ **ไม่สามารถปลอมแปลงได้** เมื่อคุณเปลี่ยน Header หรือ Payload, Signature เดิมจะกลายเป็นไม่ถูกต้องทันทีและเซิร์ฟเวอร์จะปฏิเสธ หากต้องการให้ Token ที่แก้ไขแล้วใช้งานได้ ต้อง **เซ็นใหม่** ด้วยอัลกอริทึมและคีย์เดียวกัน — นี่คือเหตุผลที่เครื่องมือนี้มี 'ถอดรหัส + แก้ไข + สร้าง' ในที่เดียว: ถอดรหัสเพื่อดู แก้ไขสิ่งที่ต้องการ และสร้าง Token ใหม่สำหรับทดสอบทันที ไม่ต้องขอให้ Backend แก้โค้ดชั่วคราว

HS256, RS256, ES256, PS256 และ EdDSA ต่างกันอย่างไร?

HS256 ใช้ HMAC กับ Secret ร่วม (สมมาตร) รวดเร็วแต่ต้องจัดการ Secret อย่างปลอดภัย; RS256 ใช้คีย์ RSA ส่วนตัว/สาธารณะ (อสมมาตร) เหมาะสำหรับสถานการณ์ที่ผู้เซ็นและผู้ตรวจสอบแยกกัน; PS256 ใช้ padding RSA-PSS ปลอดภัยกว่า RS256; ES256 ใช้เส้นโค้งวงรี P-256 ลายเซ็นสั้นกว่าและประสิทธิภาพดีกว่า; EdDSA (ปกติคือ Ed25519) รวดเร็วมากและเป็น deterministic แนะนำสำหรับโปรโตคอลใหม่เช่น OAuth 2.1

ทำไม JWT ของฉันแสดงลายเซ็นไม่ถูกต้อง?

สาเหตุที่พบบ่อยที่สุดคือคีย์, รูปแบบ Secret, อัลกอริทึม หรือการเข้ารหัส Base64URL ไม่ตรงกันพอดี ช่องว่างเพิ่มเติม, ขึ้นบรรทัดใหม่ PEM, สับสน Base64 กับ Base64URL หรือเซิร์ฟเวอร์ใช้ RS256 ในขณะที่เครื่องมือใช้ HS256 จะทำให้การตรวจสอบล้มเหลว ใช้เครื่องมือนี้สลับอัลกอริทึมและรูปแบบ Secret เพื่อทดสอบทีละอย่าง

คีย์ RSA เดียวกันใช้ตรวจสอบ RS256 และ PS256 ได้ไหม?

ไม่ได้ RS256 และ PS256 ใช้รูปแบบ padding ต่างกัน (PKCS1-v1_5 vs PSS) แม้คีย์ RSA จะเหมือนกัน แต่ไม่สามารถตรวจสอบข้ามกันได้ ผู้เซ็นและผู้ตรวจสอบต้องใช้อัลกอริทึมเดียวกัน

การโจมตี alg:none คืออะไร?

ผู้โจมตีเปลี่ยน Header เป็น `{"alg":"none"}` บอกให้เซิร์ฟเวอร์ไม่ต้องตรวจสอบลายเซ็น หรือเปลี่ยน RS256 เป็น HS256 และใช้คีย์สาธารณะเป็น HMAC Secret เพื่อหลอกเซิร์ฟเวอร์ เซิร์ฟเวอร์ต้องใช้รายการอนุญาตอัลกอริทึม (เช่น `algorithms: ['RS256']`) และห้ามเชื่อถือ Header.alg ของ Token เพื่อตัดสินใจอัลกอริทึมตรวจสอบ

แปลงระหว่าง PEM และ JWK อย่างไร?

PEM เป็นรูปแบบ OpenSSL แบบดั้งเดิมพร้อมบรรทัด BEGIN/END พบบ่อยในการตั้งค่าดั้งเดิม; JWK เป็นรูปแบบ JSON พบบ่อยใน OAuth 2.0 / OIDC IdP หลายรายเผยแพร่คีย์สาธารณะที่ `/.well-known/jwks.json` เครื่องมือนี้รองรับทั้งสองรูปแบบและสลับระหว่างกันได้

เบราว์เซอร์สามารถตรวจสอบลายเซ็น JWT ได้โดยตรงหรือไม่?

ได้ Web Crypto API รองรับ HMAC, RSA, ECDSA, RSA-PSS และ Ed25519 ในเบราว์เซอร์สมัยใหม่ ดังนั้นเครื่องมือนี้จึงตรวจสอบลายเซ็นโดยตรงบนเบราว์เซอร์โดยไม่ต้องอัปโหลด Token

Token ของฉันถูกส่งไปเซิร์ฟเวอร์หรือไม่?

ไม่ การแยกวิเคราะห์ ตรวจสอบ และเซ็นทำบนเบราว์เซอร์ แผง Network ไม่ควรแสดงคำขอใดๆ ที่มี Token

สามารถเก็บข้อมูลที่ละเอียดอ่อนใน JWT ได้ไหม?

ไม่ Payload อ่านได้โดยค่าเริ่มต้น (แค่ถอดรหัส Base64URL) รหัสผ่าน, เลขประจำตัวประชาชน, เลขบัตร, API Key, Access Token หรือ Refresh Token ไม่ควรใส่ใน JWT มาตรฐาน หากต้องการความลับ ให้พิจารณา JWE (JSON Web Encryption)

การแก้ไขปัญหา

ลายเซ็นไม่ถูกต้อง: 'signature is invalid'

Token และคีย์ตรวจสอบไม่ตรงกัน สาเหตุที่พบบ่อย: (1) คีย์ของเซิร์ฟเวอร์และคีย์ที่คุณวางในเครื่องมือต่างกัน (พบบ่อยที่สุด); (2) คีย์มีตัวอักษรที่มองไม่เห็น (ช่องว่างต่อท้าย, ขึ้นบรรทัดใหม่, ตัวอักษรความกว้างศูนย์); (3) ใช้ Base64 และ Base64URL ปนกัน; (4) เลือกอัลกอริทึมผิด (Header บอก HS256 แต่เซิร์ฟเวอร์ตรวจสอบเป็น RS256 หรือกลับกัน) ก่อนอื่นตรวจสอบว่าคีย์ตรงกันทุกไบต์: สังเกตขึ้นบรรทัดใหม่ต่อท้ายของ PEM, ช่องว่างต่อท้ายของ HMAC Secret และค่า `k` ของ JWK ที่อาจถูก URL-decode ผิด ตรวจสอบว่าอัลกอริทึมในเครื่องมือตรงกับ Header.alg ของ Token ใช้ฟังก์ชันถอดรหัสพร้อมตรวจสอบของเครื่องมือนี้เพื่อทำซ้ำข้อผิดพลาดและยืนยันว่าเกิดขึ้นระหว่าง 'ถอดรหัสสำเร็จ' กับ 'ตรวจสอบล้มเหลว'

HTTP 401 Unauthorized: Token หมดอายุหรือ iat อยู่ในอนาคต

การตรวจสอบลายเซ็นผ่านแล้ว แต่ `exp` อยู่ในอดีต (Token หมดอายุ), `nbf` ยังอยู่ในอนาคต (ยังไม่ก่อน) หรือ `iat` อยู่หลังเวลาปัจจุบันของเซิร์ฟเวอร์ (มักเกิดจากนาฬิกาไม่ตรงกัน) อีกกรณีทั่วไปคือ `aud` (ผู้รับ) ไม่ตรง: Token ออกให้ App A แต่ App B ตรวจสอบ ใช้พื้นที่เน้น Claims ของเครื่องมือนี้เพื่อดูสถานะ exp / nbf / iat ได้ในพริบตา exp สีแดง = หมดอายุ โปรดออกใหม่ nbf สีแดง = ยังไม่ใช้ได้ ตรวจสอบว่า iat เป็นเวลาในอนาคต aud สีแดง = ผู้รับผิด ตรวจสอบว่าเซิร์ฟเวอร์ตั้งค่าผู้รับถูกต้อง

ข้อผิดพลาดการนำเข้า PEM หรือ JWK

PEM มีบรรทัดว่างเพิ่มเติมหรือขาดตัวระบุส่วนหัว/ส่วนท้าย (`-----BEGIN PUBLIC KEY-----`); JWK ขาดฟิลด์ที่จำเป็น (`kty` / `n` / `e` / `kid`); ค่า `k` ของ JWK ขาด padding Base64URL (ต้องเติม `=` หรือลบ `=` อย่างเคร่งครัด); คีย์ส่วนตัว RSA ถูกรับเข้าเป็นคีย์สาธารณะ; คีย์ส่วนตัว Ed25519 (seed 32 ไบต์) ถูกป้อนเป็น 64 ไบต์ ส่งออก PEM PKIX มาตรฐานด้วย `openssl rsa -in key.pem -pubout -outform PEM` หรือ `openssl ec -in key.pem -pubout`; สำหรับ JWK ใช้เอาต์พุตดิบจาก endpoint OIDC Discovery `/.well-known/jwks.json` แทนการเข้ารหัสเอง เครื่องมือนี้ตรวจจับส่วนหัว PEM, padding ที่ขาด และฟิลด์ JWK ที่ขาดอัตโนมัติและแสดงคำแนะนำ

ความล้มเหลวการเซ็น RS256 กับ PS256 ข้ามภาษา

RS256 ใช้ RSASSA-PKCS1-v1_5, PS256 ใช้ RSA-PSS ทั้งสอง **ไม่สามารถตรวจสอบข้ามกัน** — Token ที่เซ็นด้วย RS256 ด้วยคีย์ RSA ที่กำหนดจะล้มเหลวในการตรวจสอบ PS256 เสมอ และลายเซ็นอาจยาวต่างกันไม่กี่ไบต์ ตรวจสอบว่าผู้เซ็นและผู้ตรวจสอบใช้อัลกอริทึมเดียวกัน AWS SigV4 ใช้ PS256, OIDC IdP ส่วนใหญ่ใช้ RS256 RSA-PSS ยังมีพารามิเตอร์ `saltLength` — OpenSSL ค่าเริ่มต้น 32, jose 32, `rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash}` ของ Go คือค่าที่เทียบเท่าที่ถูกต้อง กำหนดค่านี้ก่อนทดสอบเชื่อมต่อข้ามภาษา

การโจมตี alg:none และการโจมตีแทนที่คีย์ HS256

เซิร์ฟเวอร์เลือกอัลกอริทึมตรวจสอบตาม alg ที่ประกาศใน Header ของ Token ผู้โจมตีแก้ header เป็น `alg: none` (ไม่มีลายเซ็น) หรือแก้ Token RS256 เป็น HS256 (ใช้คีย์สาธารณะเสมือนเป็น HMAC Secret ร่วม) และข้ามการตรวจสอบ CVE ในอดีตเช่น CVE-2015-9235 (jsonwebtoken) และ CVE-2022-23529 (ไลบรารี Node หลายตัว) มีรากจากแพทเทิร์นนี้ เซิร์ฟเวอร์ต้องบังคับใช้รายการอนุญาตอัลกอริทึม — เช่น `algorithms: ['RS256']` — และห้ามให้ Token บอกเซิร์ฟเวอร์ว่าใช้อัลกอริทึมใด UI ของเครื่องมือนี้แสดงทั้ง Header.alg และอัลกอริทึมที่คุณเลือกจริง และแจ้งเตือนเมื่อไม่ตรงกัน: นั่นคือการสาธิตสดว่า 'ไคลเอนต์ต้องไม่เชื่อถือ Header.alg'

Privacy & Security

พื้นที่ทำงาน JWT นี้ทำงาน 100% ในเบราว์เซอร์ของคุณ รองรับโดย Web Crypto API ดั้งเดิมของเบราว์เซอร์ Token ที่คุณวาง, Header, Payload, Signature, HMAC Secret, คีย์ส่วนตัว RSA/ECDSA, คู่คีย์ที่สร้าง และการคำนวณลายเซ็น/ตรวจสอบทั้งหมดอยู่บนอุปกรณ์ของคุณ — ไม่ส่งไปเซิร์ฟเวอร์ ไม่บันทึก ไม่วิเคราะห์ และไม่แคช หน้าเว็บสามารถใช้แบบออฟไลน์ได้หลังจากโหลด วิธีปฏิบัติที่ดี: ห้ามวาง Token ผลิตที่มีอายุยาวหรือคีย์ส่วนตัวผลิตในเครื่องมือออนไลน์ใดๆ รวมถึงเครื่องมือนี้ เครื่องมือนี้เหมาะสำหรับการดีบัก ทดสอบเชื่อมต่อ เรียนรู้ และสร้าง Token ทดสอบ — Secret ผลิตและคีย์ส่วนตัวควรจัดการในสภาพแวดล้อมท้องถิ่นที่ควบคุม

Supported Video Formats

FormatMIMEBrowser supportWhen to use
HS256 / HS384 / HS512HMAC + SHA-256/384/512Universalอัลกอริทึมคีย์สมมาตร Secret เดียวกันใช้เซ็นและตรวจสอบ ง่ายและรวดเร็ว เหมาะสำหรับคลัสเตอร์เซอร์วิสภายในขอบเขตที่เชื่อถือได้ Secret ต้องยาวอย่างน้อย 32 ไบต์แบบสุ่ม
RS256 / RS384 / RS512RSASSA-PKCS1-v1_5 + SHA-2Web Crypto APIอัลกอริทึมอสมมาตรที่พบบ่อยที่สุด เซ็นด้วยคีย์ส่วนตัว ตรวจสอบด้วยคีย์สาธารณะ เป็นค่าเริ่มต้นสำหรับ OIDC IdP, API gateway และ SSO องค์กรส่วนใหญ่
PS256 / PS384 / PS512RSA-PSS + SHA-2Web Crypto APIRSA-PSS เป็นการแทนที่ RS256 ที่ใหม่กว่าและปลอดภัยกว่า AWS SigV4, AWS Cognito และผู้ให้บริการ OIDC สมัยใหม่มักเลือกใช้ ต้องระบุ saltLength อย่างชัดเจน
ES256 / ES384 / ES512ECDSA + P-256/P-384/P-521Web Crypto APIลายเซ็นเส้นโค้งวงรี ลายเซ็นสั้น (ES256 เพียง 64 ไบต์) ประสิทธิภาพดี JWT เล็กลง Apple Sign in with Apple ใช้ ES256 เป็นค่าเริ่มต้น
EdDSA (Ed25519)Ed25519 / Ed448Web Crypto APIอัลกอริทึมลายเซ็นประสิทธิภาพสูงรุ่นใหม่ ลายเซ็นแบบ deterministic (ข้อความเดิม + คีย์เดิม = ผลลัพธ์เดิมทุกครั้ง) ไม่มีความเสี่ยง nonce-reuse เป็นอัลกอริทึมที่แนะนำโดย OAuth 2.1

Authoritative References