Google sắp loại bỏ API xác thực cũ và tôi phải sửa lại một lỗi đăng nhập bằng tài khoản Github trên blog

Google sắp loại bỏ API xác thực cũ và tôi phải sửa lại một lỗi đăng nhập bằng tài khoản Github trên blog

Tin ngắn hàng ngày dành cho bạn
  • swapy là một thư viện giúp bạn tạo ra thao tác kéo thả để hoán đổi vị trí của các thành phần một cách dễ dàng.

    Thư viện hỗ trợ rất nhiều nền tảng, rất thích hợp để xây dựng một cái gì đó mang tính cá nhân hoá như trang Dashboard của người dùng.

    » Xem thêm
  • Ui! Blog đang dính một lỗi bảo mật khá nghiêm trọng. Không biết có bạn nào phát hiện ra chưa. Dù chưa ảnh hưởng đến người dùng nhưng thông qua quá trình Eating your own dog food thì mới phát hiện ra á. Để sửa xong thì mình kể chi tiết.

    » Xem thêm
  • Ngủ dậy thấy bảng tin ngập tràn bài viết về việc Microsoft vừa viết lại trình biên dịch Typescript - tsc bằng Go, hiệu suất cho ra nhanh hơn gấp 10 lần so với cái hiện tại. Wow!

    Nhưng khi nhìn thấy tin này thì trong đầu nảy luôn ra câu hỏi "Tại sao không phải là Rust?". Bạn biết đấy, phong trào viết lại mọi thứ bằng Rust đang nóng hơn bao giờ hết, không ngoa khi nói rằng nó đang càn quét bảng xếp hạng của những công cụ kỳ cựu trước đó.

    Điều thú vị hơn nữa là viêc lựa chọn Go - mang lại hiệu suất tốt nhất cho đến thời điểm hiện tại - như họ nói. Thì rất nhiều người tỏ ra thất vọng vì tại sao không phải là C# 😆. Đấy khi bản nổi tiếng quá làm gì cũng bị xét nét từng tí một, nói chưa chắc ai cũng nghe 🥶

    Why Go? #411

    » Xem thêm

Vấn đề

Ngay từ lúc đầu làm blog, tôi đã nghĩ đến trường hợp người đọc có thể để lại bình luận trong bài viết. Việc phát triển một module đăng ký/đăng nhập không nằm ngoài dự tính. Nhưng thay vì làm thêm màn đăng ký, tôi dành ít thời gian để suy nghĩ về việc làm cách nào để rút ngắn thời gian đăng nhập xuống. Vì giả dụ người dùng chưa có tài khoản, họ muốn thảo luận ngay lập tức mà lại bắt phải nhập nhiều thông tin trong bước đăng ký thì chắc chắn ít nhiều, họ sẽ nao núng và thôi không nói nữa. Cho nên, thời gian là cực kỳ quan trọng trong tình huống này, càng phức tạp, càng tốn thời gian, bạn đọc của tôi sẽ chẳng buồn làm gì thêm nữa. Đối tượng tôi nhắm đến là "dân dev", mà đã là dev thì chắc hẳn phải có tài khoản Google hoặc Github.

Cả hai đều cung cấp cơ chế Oauth, nghĩa là cho phép chúng ta tạo các ứng dụng trên nền tảng và thông qua nó, xác thực & ủy quyền người dùng. Nếu làm theo cách này, đồng nghĩa với việc người dùng chỉ cần thao tác tối thiểu 3 cú bấm chuột là đã có thể đăng nhập được vào trang web. Đó là một sự tiện lợi cho cả hai, khi tôi không cần phải thêm bước đăng ký còn người dùng chỉ cần có tài khoản Google hay Github là đã có thể đăng nhập.

Cứ ngỡ sau một lần viết, code chạy mãi mãi, chức năng này hoạt động trong một khoảng thời gian cho đến khi tôi phát hiện ra điều bất thường. Cụ thể là trường hợp một người dùng lại bình luận được dưới một danh nghĩa của một người dùng khác!?. Họ đang đăng nhập bằng tài khoản Github A nhưng bình luận lại hiện ra thông tin của họ dưới tài khoản B. Ngay lập tức, tôi tạm thời tắt tính năng đăng nhập bằng Github và điều tra nguyên nhân. Sau khoảng vài ngày, tôi dường như phát hiện ra một sai lầm trong mã của mình và những gì sau đó là sắp xếp thời gian để sửa lỗi.

Cùng lúc đó, Google có gửi nhiều email thông báo đến các tài khoản đang sử dụng dịch vụ xác thực là ngày 31/03/2023, họ sẽ chính thức ngừng cung cấp API đăng nhập bằng tài khoản Google theo cách cũ. Buộc quản trị trang web phải chuyển sang một API mới để tiếp tục sử dụng. Thời đến cản không kịp thế là tôi ngồi lại sửa lại cả hai cùng một lúc.

Trong quá trình sửa lỗi, tôi có rút ra được một vài bài học và cảm thấy có thể chia sẻ được cho bạn đọc, để nếu như bạn có đang xử lý giống tôi thì hãy chú ý, hoặc cho những bạn nào chuẩn bị làm tính năng này thì cũng có thêm kinh nghiệm xử lý.

Cơ chế Oauth

Đầu tiên, tôi xin nhắc lại một chút về cơ chế Oauth xem nó là cái gì. Hẳn là bạn đọc đã nghe hoặc quá quen thuộc với khái niệm của Oauth, hoặc chỉ cần hiểu đơn giản bất kỳ ứng dụng phần mềm nào mà có mục "đăng nhập bằng tài khoản Google/Github"... là đã thấy sự hiện diện của Oauth trong đó. Nếu bấm vào nút, một cửa sổ trình duyệt hiện ra hỏi bạn có đồng ý cho phép ứng dụng ABC truy cập vào tài khoản hay không. Nếu có, bạn được đăng nhập, còn nếu không thì chẳng có gì xảy ra cả.

Cơ chế của Oauth có thể phức tạp, trong bài viết ngắn này tôi không tiện nêu ra, thay vào đó bạn đọc có thể tìm đọc các bài mô tả về luồng, cách hoạt động của Oauth trên mạng. Nhưng để nói vắn tắt, quá trình Oauth sẽ bao gồm 2 bước là xác thực & ủy quyền.

Nếu để ý, mỗi khi bấm vào nút Đăng nhập bằng Google, sẽ có một màn hình hiện ra bảo rằng "Ứng dụng ABC đang yêu cầu quyền truy cập vào Email/Drive/Docs..." và hỏi bạn có cho phép không? Nếu chọn "có" thì tức là bạn đã ủy quyền cho ứng dụng ABC có những quyền hạn như đọc/ghi vào các dịch vụ mà nó vừa hỏi. Hay nói sâu hơn, lúc đó lập trình viên của ứng dụng ABC sẽ lấy được Access Token tài khoản của bạn để qua đó, gọi các API được cung cấp để truy cập vào chúng.

Còn quá trình trước khi vào được đến màn hình ủy quyền là quá trình xác thực. Hiểu đơn giản, quá trình đăng nhập vào tài khoản là quá trình xác thực. Xác thực bạn là chủ tài khoản trước bằng cách đăng nhập rồi ủy quyền sau bằng cách cấp quyền.

Lỗi đăng nhập bằng tài khoản Github

Lỗi tôi gặp phải là đã quá vội vàng nên lấy nhầm hoặc không lấy được địa chỉ email của tài khoản. Cụ thể là đối với Github, sau khi tôi lấy được Access Token của người dùng, tôi sẽ dùng nó để gọi đến một API là /user để lấy thông tin người dùng. Trong dữ liệu trả về, ngoài một vài thông tin như tên, avatar... thì còn có cả email, không chần chừ gì tôi lấy ngay email này và coi nó như là email đăng nhập của người dùng. Đó là gốc rễ của vấn đề.

Bởi vì email trả về trong API này nó mang tính thông tin là chủ yếu, nói cách khác, đó không phải là email thật của người dùng. Muốn lấy được email thật, buộc bạn phải xin quyền đọc được địa chỉ email ở bước ủy quyền. Sau đó, tiếp tục gọi đến một API khác để lấy danh sách địa chỉ email, trong đó bao gồm email chính (primary) và nhiều email phụ nếu có, bao gồm cả các email mà họ chưa xác thực (confirm).

Có thể dạo gần đây, khi mà vấn đề rò rỉ thông tin người dùng ngày càng được quan tâm thì các dịch vụ cung cấp xác thực & ủy quyền họ càng làm chặt hơn về đòi hỏi quyền đọc được địa chỉ email của người dùng.

Tương tự đối với Google, sau khi nhận được mã ID Google Token. Tôi sẽ xác thực đoạn mã đó và giải mã bên trong nó chứa địa chỉ email của người dùng, bao gồm một trường đánh dấu là email đó đã được xác thực hay chưa (email_verified). Thực tế, tôi không hiểu rõ việc đánh dấu tài khoản là đã được xác thực lắm, nhưng nếu việc Google hoặc Github đánh dấu một tài khoản là "chưa xác thực" thì rõ ràng có một vấn đề gì đó mà tôi không nên "tin" vào những tài khoản như vậy. Vì thế tôi nghĩ cách tốt nhất là từ chối đăng nhập với những trường hợp như vậy.

Khắc phục

Sau khi biết được nguồn cơn của vấn đề, chúng ta sẽ tìm cách khắc phục. Như tôi đã trình bày như trên, đó là kiểm tra lại thật kỹ tài liệu để biết làm cách nào để lấy được email thật của người dùng chứ không phải là email mang tính chất thông tin hiển thị. Bên cạnh đó, tôi cũng nhấn mạnh hai lưu ý về việc xác thực & ủy quyền.

Đầu tiên, cũng là bước quan trọng nhất, chúng ta phải xin được đúng quyền (scope), trong đó bao gồm quyền đọc địa chỉ email. Ví dụ như trong Github, việc xin quyền email thể hiện ngay trong url chuyển hướng đăng nhập. Bạn đọc xem thêm ở Request a user's GitHub identity.

Thứ hai, xác định được vị trí để lấy ra được email chính. Ví dụ như trong Github, cần gọi một API lấy danh sách địa chỉ email và kiểm tra xem đâu là email chính, đã xác thực hay là chưa. Bạn đọc xem thêm ở List email addresses for the authenticated user.

Còn đối với Google, họ đang khuyến kích chúng ta chuyển sang Sign in with Google for Web, bởi vì cách cũ Google Sign-In for Web sẽ bị ngừng vào ngày 31/03 tới đây.

Tổng kết

Oauth là một cách nhanh chóng để người dùng có thể đăng nhập vào trang web của bạn bằng tài khoản Google, Github... mà không cần phải qua nhiều bước đăng ký rườm rà. Tuy nhiên, khi sử dụng Oauth cần chú ý đến việc xác thực được địa chỉ email của người dùng để tránh những lỗi lầm tai hại như trong bài viết nhé.

Cao cấp
Hello

Bí mật ngăn xếp của Blog

Là một lập trình viên, bạn có tò mò về bí mật công nghệ hay những khoản nợ kỹ thuật về trang blog này? Tất cả bí mật sẽ được bật mí ngay bài viết dưới đây. Còn chờ đợi gì nữa, hãy bấm vào ngay!

Là một lập trình viên, bạn có tò mò về bí mật công nghệ hay những khoản nợ kỹ thuật về trang blog này? Tất cả bí mật sẽ được bật mí ngay bài viết dưới đây. Còn chờ đợi gì nữa, hãy bấm vào ngay!

Xem tất cả

Đăng ký nhận thông báo bài viết mới

hoặc
* Bản tin tổng hợp được gửi mỗi 1-2 tuần, huỷ bất cứ lúc nào.

Bình luận (1)

Nội dung bình luận...
Avatar
Nguyễn Huyền Diệu1 năm trước
Klq con mèo nhìn ngộ quá :))
Trả lời
Avatar
Xuân Hoài Tống1 năm trước
@gif [blPpTGDhn6hEI]