28/01/2026
2FA
ทำ 2FA บนเว็บแบบทำตามได้ (TOTP/Authenticator + Backup Codes) 🔐📱
ภาพรวมที่ควรรู้ก่อนลงมือ 🧠
1) รหัสผ่านอย่างเดียวพังได้จากรั่วไหลหรือฟิชชิง 🕳️
2) 2FA ที่ทำง่ายและนิยมสุดคือ TOTP (รหัส 6 หลักเปลี่ยนทุก ~30 วิ) ⏱️
3) TOTP ไม่พึ่ง SMS ลดปัญหา SIM swap 📵
4) 2FA ที่ดีต้องมีทางกู้คืนด้วย (Backup Codes) 🧾
5) ต้องทำ “สมัคร → เปิดใช้ → ยืนยัน → เก็บโค้ดสำรอง → ล็อกอิน → กู้คืน” ให้ครบวงจร ✅
ส่วนประกอบระบบที่ต้องมี 🧩
1) ตาราง users: เก็บบัญชีและสถานะ 2FA 👤
2) ตาราง user_2fa หรือฟิลด์เพิ่ม: secret (เข้ารหัส), enabled_at, verified_at 🔒
3) ตาราง backup_codes: เก็บ hash ของโค้ดสำรองหลายชุดต่อผู้ใช้ 🧾
4) บันทึกเหตุการณ์ security_log: เปิดใช้/ปิดใช้/ใช้โค้ดสำรอง/พยายามยืนยันผิด 🧷
ขั้นตอนสมัคร (Signup) 📝
1) สมัครด้วยอีเมล/พาสเวิร์ดตามปกติ ✉️
2) บังคับใช้รหัสผ่านที่ยาวและเดายาก + rate limit การลองผิด 🔐
3) หลังสมัครเสร็จ แนะนำให้ตั้งค่า 2FA ทันที แต่ไม่ควรบังคับทันทีถ้าไม่มี flow กู้คืนพร้อม 🧭
ขั้นตอนเปิดใช้ 2FA (Setup TOTP) ทีละขั้น 🛠️
1) ผู้ใช้กด “เปิดใช้ 2FA” ในหน้า Settings ⚙️
2) เซิร์ฟเวอร์สร้าง TOTP secret ใหม่ (สุ่มแรง) 🎲
3) เก็บ secret แบบเข้ารหัส (encryption at rest) ไม่เก็บเป็น plain text 🔒
4) สร้าง otpauth URI เพื่อนำไปทำ QR ให้ Authenticator สแกน 🧾
5) แสดง QR + แสดง secret แบบตัวอักษรเผื่อสแกนไม่ได้ (ต้องซ่อน/กดดู) 👀
6) ให้ผู้ใช้กรอกรหัส 6 หลักจากแอปเพื่อ “ยืนยันการเปิดใช้” ✅
7) ฝั่งเซิร์ฟเวอร์ตรวจรหัส TOTP (อนุญาตเวลาเหลื่อม 1 ช่วง) ⏱️
8) ถ้าถูกต้อง: mark ว่า 2FA enabled + เวลาที่เปิดใช้ 🟢
9) จากนั้น “สร้าง Backup Codes” ทันที และบังคับให้ผู้ใช้บันทึกก่อนออกจากหน้า 🧾
การตรวจ TOTP ที่ควรทำ (ฝั่งเซิร์ฟเวอร์) 🧰
1) ใช้ไลบรารีมาตรฐาน (เช่น speakeasy / otplib / pyotp) 📦
2) ตรวจช่วงเวลา window 1 (ป้องกัน clock drift) ⏲️
3) ใส่ rate limit ต่อบัญชีและต่อ IP ป้องกันเดารหัส 6 หลัก 🚦
4) ถ้ากรอกผิดหลายครั้งให้หน่วงเวลาเพิ่มหรือบล็อกชั่วคราว 🧱
Backup Codes ที่ควรทำให้ถูก 🧾
1) สร้าง 8–12 โค้ด แบบสุ่มยาวพอ (เช่น 10–12 ตัว) 🎟️
2) แสดงให้ผู้ใช้ครั้งเดียว (หลังจากนั้นดูไม่ได้) 👁️🗨️
3) เก็บในฐานข้อมูลเป็น hash แบบ slow hash (Argon2/bcrypt/scrypt) ไม่เก็บ plain 🧂
4) 1 โค้ดใช้ได้ครั้งเดียว ใช้แล้วต้อง mark used_at ✅
5) ทำปุ่ม “สร้างชุดใหม่” แล้ว invalidate ชุดเก่า 🔁
ขั้นตอนล็อกอินเมื่อเปิดใช้ 2FA แล้ว 🔐➡️📱
1) ผู้ใช้ใส่ email + password ตามปกติ 🧑💻
2) ถ้าพาสเวิร์ดถูก: อย่าเพิ่งสร้าง session เต็ม ให้เข้าสถานะ “pending_2fa” 🕗
3) ส่งไปหน้า “กรอกรหัสจาก Authenticator” 📲
4) ถ้ารหัสถูก: ค่อยยกระดับเป็น session จริง + ออก token/cookie 🍪
5) จำอุปกรณ์ได้ (Remember device) ทำได้ แต่ต้องเก็บเป็น device token แบบผูกกับเครื่องและเพิกถอนได้ 🧷
ขั้นตอนกู้คืนเมื่อทำมือถือหาย (Recovery) 🆘
1) หน้า 2FA ให้มีตัวเลือก “ใช้ Backup Code” แทน TOTP 🧾
2) ถ้ากรอก Backup Code ถูก: ล็อกอินได้ และทำเครื่องหมายว่าโค้ดนี้ถูกใช้แล้ว ✅
3) หลังล็อกอินด้วย Backup Code ควรบังคับให้ผู้ใช้ตั้งค่า 2FA ใหม่ทันที 🔁
4) ถ้าผู้ใช้ไม่มี Backup Code ด้วย: ต้องมี flow กู้คืนบัญชีด้วยการยืนยันตัวตน (อีเมล + เวลารอ + ตรวจความเสี่ยง) 🕵️
กันฟิชชิงให้ดีขึ้น (แม้ใช้ TOTP ก็ยังโดนได้) 🎣🛡️
1) TOTP ถูกขโมยได้ถ้าผู้ใช้กรอกในเว็บปลอมแบบ real-time 🧨
2) ใส่ “หน้าคอนเฟิร์มโดเมน” ใน UX: โชว์โดเมน/ชื่อแอปชัดเจนตอน setup 2FA 🧭
3) แจ้งเตือนความปลอดภัยเมื่อมีการล็อกอินจากอุปกรณ์/ประเทศใหม่ ✉️
4) จำกัดการลองรหัส + ตรวจ IP reputation + bot detection 🤖
5) ผูก session หลังผ่าน 2FA แล้วเท่านั้น และหมุน session id หลังยืนยัน (session rotation) 🔄
6) ใช้ HTTPS ทุกหน้า + HSTS + ตั้งค่า cookie แบบ HttpOnly/SameSite/Secure 🍪
7) เพิ่มปุ่ม “ดูอุปกรณ์ที่เคยล็อกอิน” และ “ออกจากระบบทุกอุปกรณ์” 🧹
ทริคที่คนมักพลาด แต่สำคัญมาก ⚠️
1) เปิด 2FA แล้วแต่ยังอนุญาต login API บางจุดโดยไม่เช็ค 2FA (ช่องโหว่ยอดฮิต) 🕳️
2) เก็บ TOTP secret แบบไม่เข้ารหัส ทำให้ DB หลุดทีเดียวจบ 🔓
3) เปิดใช้ 2FA โดยไม่ให้ verify ครั้งแรก ทำให้ผู้ใช้ติด lockout ได้ 🧷
4) ไม่มี Backup Codes หรือกู้คืนไม่ได้ ทำให้ support งานบาน 🧯
5) ไม่บันทึก security log ทำให้ตามเหตุการณ์ไม่ได้ 🔎
ตัวอย่างโครงสร้างข้อมูลแบบจำง่าย 🗂️
1) user.twofa_enabled (boolean)
2) user.twofa_secret_enc (encrypted string)
3) backup_codes: user_id, code_hash, used_at, created_at
4) security_events: user_id, event_type, ip, ua, created_at
สรุปแนวทางทำให้ “ปลอดภัย + ใช้งานได้จริง” 🎯
1) setup ต้องมี verify ก่อนเปิดใช้จริง ✅
2) login ต้องแยกสถานะ pending_2fa ชัดเจน 🕗
3) backup codes ต้อง hash และใช้ครั้งเดียว 🧾
4) ป้องกันฟิชชิงด้วย UX + แจ้งเตือน + session hygiene 🛡️
5) ทำให้ผู้ใช้กู้คืนได้ ไม่งั้น 2FA กลายเป็นกับดัก 🚪
ถ้าจะอัปเกรดความปลอดภัยไปอีกขั้นในอนาคต ให้เพิ่ม passkeys (WebAuthn) เพราะกันฟิชชิงได้ดีกว่า TOTP มาก 🔑🚀