Xin chào tất cả các bạn, mình là Quân, hôm nay chúng ta sẽ cùng nhau đi tìm hiểu một tính năng bảo mật rất thú vị và phổ biến trong các ứng dụng ngày nay đó là xác thực bảo mật 2 lớp – Two-Factor Authentication (2FA) cũng như làm một cái ứng dụng thực tiễn Demo 2FA chuyên nghiệp bằng NodeJS và ReactJS nhé.
“Bài này nằm trong chuỗi: Xây dựng ứng dụng xác thực 2 lớp: Two-Factor Authentication (2FA) trên trang blog chính thức trungquandev.com cũng như kênh YouTube: TrungQuanDev – Một Lập Trình Viên“
Những nội dung có trong bài:
- Đào sâu vào lý thuyết một chút
- Phân tích & triển khai sơ đồ xác thực / bảo mật
- Demo ứng dụng bảo mật 2 lớp cũng như hướng dẫn Code chi tiết từ A-Z
1. Đào sâu vào lý thuyết một chút
Vẫn là phong cách quen thuộc của mình, tuy rằng việc đọc lý thuyết khá dễ buồn ngủ nhưng mà trước khi lao đầu vào code thì chúng ta nên phân tích, tìm hiểu kỹ lý thuyết một chút, để có thể hiểu sâu bản chất của việc mà chúng ta đang làm là gì nhé.
Phần lý thuyết này mình sẽ giải thích cho các bạn một cách cực kỳ dễ hiểu về những loại thuật ngữ sau:
Two-Factor Authentication (2FA)
One-time Password (OTP)
HMAC-based One-Time Password (HOTP)
Time-based One-time Password (TOTP)
Chắc hẳn đa phần các bạn đều đã từng gặp trường hợp đăng nhập vào tài khoản facebook hoặc google thì sau bước nhập email + password, các bạn vẫn phải nhập thêm một cái mã token (thường là 6 chữ số và có thời gian hiệu lực 30 giây -> 1 phút) thì mới có thể đăng nhập được vào tài khoản. Có nhiều cách để nhận được mã này ví dụ như thông qua email, số điện thoại hoặc là được gennerate từ một ứng dụng tạo mã bên thứ ba như Google Authenticator hoặc Authy. Hình thức bảo mật trên được gọi là Xác thực 2 lớp – Two-Factor Authentication.
Vậy về mặt lý thuyết thì Two-Factor Authentication là gì?
Two-Factor Authentication (thường viết tắt là 2FA hoặc TFA) là một phương pháp xác thực người dùng dựa trên 2 yếu tố, một là mật khẩu (thứ phổ biến nhất) và thứ hai là một thứ mà người dùng sở hữu, có quyền truy cập đến, ví dụ như dấu vân tay, tin nhắn SMS, gửi mã token tới Email hoặc tốt hơn nữa là One-time Password (OTP) (mật khẩu một lần có giới hạn hiệu lực theo thời gian).
One-Time Password sẽ là thứ mà chúng ta bàn đến trong ngày hôm nay, SMS và Email thì mình sẽ làm ở những bài riêng biệt khác sau. Và đúng như cái tên của nó, One-time Password hay còn được viết tắt là OTP là một loại mã token mà chỉ có thể được sử dụng một lần rồi sau đó nó sẽ bị hủy, không được phép sử dụng tới lần thứ hai.
Lúc này, câu hỏi tiếp theo mà chúng ta đặt ra ở đây là, làm sao để đảm bảo chúng ta có thể tạo một mã token mà thỏa mãn điều kiện là duy nhất (unique)?
Và câu trả lời sẽ tiếp tục dẫn dắt chúng ta đến với một khái niệm khác đó là: Thuật toán HMAC-based One-Time Password, hay còn được viết tắt là HOTP.
HMAC-based One-Time Password – HOTP là một thuật toán sinh mã OTP dựa trên hàm băm HMAC_SHA-1, nó sử dụng 2 thành phần: thứ nhất là một Chuỗi Secret cố định, còn thành phần thứ hai là một bộ đếm (Counter) bộ đếm này dùng một cái là “Moving-Factor” (mình tạm dịch ra là một yếu tố di chuyển, các bạn cũng có thể coi nó tương tự một chuỗi random ngẫu nhiên cho dễ hiểu cũng được.)
Để mà đi sâu vào cái HOTP trên thì nó lại là cả một bầu trời kiến thức về thuật toán khác, mình sẽ để link chính thức ở đây cho các bạn tham khảo thêm rồi tập trung tiếp vào nội dung của chúng ta nhé.
https://tools.ietf.org/html/rfc4226
– Tiếp theo, vì kết quả output của hàm băm HMAC_SHA-1 ở trên là một giá trị có độ dài 160 bit = 20 bytes nên chúng ta sẽ cần thêm một bước làm ngắn gọn output để mắt người dùng có thể dễ dàng đọc được. Việc cắt ngắn này sẽ dẫn chúng ta đến với thuật toán TOTP – Time-based One-time Password algorithm để tạo ra chuỗi có độ dài như chúng ta mong muốn, ví dụ "170 795"
mà các bạn thường thấy ở app Google Authenticator hoặc Authy.
Time-based One-time Password – TOTP về cơ bản chỉ khác HOTP ở chỗ là TOTP sẽ sử dụng “thời gian” (Time) để làm bộ đếm (Counter) thay vì “Moving Factor” như HOTP. Chính vì việc sử dụng counter là thời gian nên phía Server lẫn Client khi đã có chung Secret Key rồi thì không cần có sự tương tác qua lại nữa. Vì cả 2 phía đều có quyền truy cập vào thời gian. Điều này cũng trả lời luôn cho một thắc mắc khá thú vị mà lâu nay mình vẫn tự hỏi, đó là tại sao khi mình thử tắt mạng, không kết nối internet cho cái điện thoại vậy mà Token sinh ra của mấy cái app Google Authenticator hay Authy vẫn sử dụng được ngon lành chả vấn đề gì =))
Giải thích cụ thể hơn cho các bạn đó là: phía Server sẽ so sánh giá trị token mà người dùng submit từ phía client lên với tất cả các token được sinh ra trong cùng một khoảng thời gian nhất định trên Server. (thường là 30 giây cho đến 1 phút), và dĩ nhiên là nếu trùng nhau thì bạn sẽ pass qua vòng xác thực 2 lớp này. Đọc đến đây nhiều bạn có thể sẽ thắc mắc tiếp là: Ủa thế server và client khác múi giờ (Time zone) thì làm sao mà khoảng thời gian của 2 phía có thể đồng nhất được nhỉ?
Giải pháp là chúng ta có thể convert thời gian của cả 2 phía về dạng Unix Timestamp (hay còn gọi với tên khác là Epoch Time) rồi so sánh chúng. Hiểu một cách đơn giản thì Unix Timestamp là số giây đếm tăng dần từ một điểm thời gian cố định trong quá khứ đó là ngày 01/01/1970 (UTC) 00:00:00
Mình sẽ để link tham khảo về Unix Time cho các bạn tìm hiểu thêm ở đây https://www.unixtimestamp.com/
Mình cũng sẽ để link tài liệu chính thức của TOTP cho các bạn nào muốn tìm hiểu chuyên sâu về thuật toán nhé, chứ nói thật viết ra mớ lý thuyết dài dòng theo ý hiểu của mình tới tận khúc này là mình cũng oải + buồn ngủ lắm rồi =)))
https://tools.ietf.org/html/rfc6238
Và tiếp theo, tới phần thú vị đỡ buồn ngủ hơn rồi, chúng ta sẽ đi code một ví dụ demo bảo mật 2 lớp với NodeJS như tiêu đề của bài viết nhé. Mình có làm giao diện ứng dụng rất sát với thực tế cho các bạn dễ hình dung đấy, cứ kéo xuống dưới là thấy 😀
(Ngoài lề quen thuộc: Cảnh báo này dành cho mấy bạn admin của mấy trang TopDev, TechBlog… chuyên đi copy rồi xào bài, hoặc bất kể trang nào khác mà đã đi copy bài không phải của các bạn thì hãy tôn trọng người viết bài chân chính, tuyệt đối không được xào nấu, chỉnh sửa linh tinh bài viết của mình, cấm xóa những liên kết (link) trong bài của mình cũng như tự ý xóa các câu thoại của mình trong toàn bộ bài viết rồi post lại lên trang của các bạn như kiểu đây là bài của các bạn vậy, mình sẽ thường xuyên dùng tool để check, và nếu phát hiện ra thì cứ đơn giản là chắc chắn sẽ ăn report DMCA nhé.)
2. Phân tích & triển khai sơ đồ xác thực / bảo mật
Trước khi vào code, mình đã phân tích cũng như vẽ lại workflow tổng quát của ứng dụng cho các bạn dễ hình dung nhất với 2 ảnh như sau:
3. Demo ứng dụng bảo mật 2 lớp cũng như hướng dẫn Code chi tiết từ A-Z
Dĩ nhiên tới bước này không thể viết bằng text được nữa rồi, hãy xem đầy đủ video hướng dẫn chi tiết ở playlist này của mình nhé:
Xây dựng ứng dụng xác thực, bảo mật 2 lớp: Two-Factor Authentication (2FA) – TrungQuanDev
Cảm ơn các bạn đã dành thời gian theo dõi bài viết.
Xin chào và hẹn gặp lại các bạn ở những bài viết tiếp theo.
Wishing you a wonderful day!
Trungquandev – Một Lập Trình Viên
Một vài thông tin về mình và những cộng đồng lập trình nếu bạn quan tâm thì join cùng mình nhé, cảm ơn các bạn!
• YouTube: https://www.youtube.com/@trungquandev
• Discord : https://discord.gg/ycSbhP6gDu
• Page Facebook: https://www.facebook.com/trungquandev
• Group Facebook: https://www.facebook.com/groups/laptrinhwebvietnam
Mình trên các nền tảng Podcasts:
• Spotify: https://podcasters.spotify.com/pod/show/trungquandev-official
• Apple: https://podcasts.apple.com/vn/channel/trungquandev/id6475606935