[P5] Nhập môn Authentication: OAuth 2.0

[P5] Nhập môn Authentication: OAuth 2.0

Đây là phần 5 trong series Giải ngố authentication. Nếu các bạn chưa xem phần 1, 2, 3, 4 thì có thể xem ở đây:

Nhiều khi tự hỏi OAuth 2.0 là gì? Nghe cao siêu thế nhỉ?

Thực ra thì nó cũng không phải gì cao siêu đâu, nó là cái giao thức để làm mấy chức năng như: Đăng nhập bằng tài khoản Google, Facebook, Github,... đó 😁.

Shopee cũng có OAuth 2 với việc cho phép đăng nhập bằng Google, Facebook

Shopee cũng có OAuth 2 với việc cho phép đăng nhập bằng Google, Facebook

OAuth 2.0, viết tắt của “Open Authorization”, là một tiêu chuẩn được thiết kế để cho phép một trang web hoặc ứng dụng thay mặt người dùng truy cập các tài nguyên được lưu trữ bởi các ứng dụng web khác

Trước đây thì có OAuth 1.0, nhưng nó có nhiều vấn đề nên đã được thay thế bằng OAuth 2.0.

Về lý thuyết của OAuth 2 mình sẽ để ở cuối bài, vì bây giờ các bạn đọc cũng mơ hồ lắm.

Các bạn làm cái demo cùng với mình, đăng ký Google OAuth, đọc flow hoạt động của nó, chạy thử code trong repository của mình cung cấp ở dưới là hiểu.

Oke, bắt đầu nhé.


🥇 Đăng ký dịch vụ Google OAuth

Muốn thực hiện chức năng đăng ký / đăng nhập bằng một bênh thứ 3 như Google, Facebook, Github,... thì chúng ta cần phải đăng ký dịch vụ của họ trước, để họ biết App chúng ta là gì, cần truy cập vào thông tin gì,...

Dưới đây mình sẽ hướng dẫn mọi người đăng ký trong môi trường test, nghĩa là chúng ta sẽ đăng ký dịch vụ Google OAuth để chạy trên localhost.

Sau này muốn chạy trên domain thật thì nó có button Publish App, bạn làm theo hướng dẫn của họ là được thôi.

Ở đây mình giả sử URL của mình như sau

  • Client: http://localhost:3000

  • Server: http://localhost:4000

🥈 1. Tạo project trên Google Cloud Console

Lên google gõ Google Cloud Console và click vào kết quả đầu tiên hoặc click vào link này cho nhanh

Chọn Apis & Services

Chọn Apis & Services

Hoặc nếu đây là lần đầu tiên bạn vào thì UI nó sẽ như dưới đây

Chọn Apis & Services

Chọn Apis & Services

Tiếp theo chúng ta sẽ tiến hành tạo một project mới.

Tạo project mới

Tạo project mới

Nếu lần đầu tiên thì làm như hình dưới đây

Tạo project mới

Tạo project mới

Điền tên dự án vào đây, mình sẽ không chọn Organization

Điền tên dự án vào đây, mình sẽ không chọn Organization

🥈 2. Tạo OAuth Consen Screen

Chọn OAuth Consen Screen -> User TypeExternal -> Create

Tạo OAuth Consen Screen

Tạo OAuth Consen Screen

Tại bước 1, chúng ta điền thông tin cách mà App hiển thị khi người dùng đăng nhập bằng Google OAuth

Điền thông tin ở step 1

Điền thông tin ở step 1

Dưới đây là thông tin của mình, các bạn có thể tham khảo:

App information:

  • App name: Google OAuth MMO

  • User support email: nroduc.contact@gmail.com

App Logo:

  • Logo file to upload: upload logo app bạn lên

App Domain

  • Application home page: http://localhost:3000

  • Application privacy policy link: http://localhost:3000/privacy-policy (chưa có route này cũng không sao, cứ ghi vào là được)

  • Application terms of service link: http://localhost:3000/terms-of-service (chưa có route này cũng không sao, cứ ghi vào là được)

Authorized domains: Mình sẽ bỏ qua cái này

Developer contact information:

  • Email addresses: nroduc.contact@gmail.com

Chọn Save and Continue

Chọn phạm vi data truy cập vào thông tin người dùng

Chọn phạm vi data truy cập vào thông tin người dùng

Ở đây các bạn nhấn Add or Remove Scopes để chọn phạm vi data truy cập vào thông tin người dùng.

Mình sẽ chọn userinfo.emailuserinfo.profile và nhấn Update.

Tiếp tục nhấn Save and Continue

Vì chúng ta đang ở trạng thái là Testing, nên chúng ta sẽ thêm một số gmail vào để test chức năng đăng nhập bằng google. Chỉ nhưng gmail được thêm vào đây mới có thể đăng nhập được.

Thêm user test vào đây

Thêm user test vào đây

Chọn Save and Continue

Cuối cùng là review lại thông tin và nhấn Back to Dashboard

Step 4 Sumary

Step 4 Sumary

🥈 3. Tạo Credential

Chọn Credentials -> Create Credentials -> OAuth client ID

OAuth client ID

OAuth client ID

Application type: Web application

Name: Google OAuth MMO Credential

Authorized JavaScript origins: mình sẽ bỏ qua cái này

Authorized redirect URIs: điền vào đây một số url để Google OAuth có thể redirect về sau khi đăng nhập thành công. Mình sẽ điền API end point của mình, Ví dụ: http://localhost:4000/api/oauth/google

Cuối cùng nhấn Create

Sau đó chúng ta sẽ nhận được Client IDClient Secret.

Các bạn lưu lại 2 cái này để mà dùng nhé (hoặc chọn Download JSON để tải về file json chứa 2 cái này)

Bây giờ thì đọc thử cái flow của Google OAuth nhé, phía dưới có link Github, bạn chỉ cần thay thế các giá trị trong file .env của 2 folder clientserver là test được.


🥇 Flow của Google OAuth

Mặc dù mình nói là flow Google nhưng Facebook, Github, Twitter, ... cũng tương tự như vậy. Mấy ông mạng xã hội này đều dùng chung flow OAuth 2.0 mà.

Giả sử

  • Website React.js của mình là https://phamhongduc.com

  • Server API Express.js của mình là https://api.phamhongduc.com

Thì flow đăng nhập bằng Google OAuth sẽ như sau:

  1. Người dùng truy cập vào https://phamhongduc.com/login và click vào nút Đăng nhập bằng Google

  2. Website của mình sẽ redirect người dùng đến https://accounts.google.com/o/oauth2/v2/auth/oauthchooseaccount?redirect_uri=http%3A%2F%2Flocalhost%3A4000%2Fapi%2Foauth%2Fgoogle&client_id=480331042606-gm573du1155724l8f780em2fel1a5dd3.apps.googleusercontent.com&access_type=offline&response_type=code&prompt=consent&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email&service=lso&o2v=2&flowName=GeneralOAuthFlow để người dùng chọn tài khoản đăng nhập vào Google. Các bạn để ý có mấy tham số query trên url là do website mình tự config và truyền vào. Google sẽ xác thực cái các query này để xem thử đây là App nào, đã đăng ký Consent hay chưa, có được phép truy cập vào thông tin người dùng hay không.

  3. Người dùng chọn tài khoản Google để đăng nhập, khi đăng nhập thành công sẽ được google cho redirect về https://api.phamhongduc.com/api/oauth/google?code=4%2F0AbUR2VPc2mJ0zoSxvWVI2XwyCV-8PwkVpIoUu1SBfV3CSYJ30orHOff_fse9GzsG0UpTtw&scope=email+profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+openid&authuser=0&prompt=consent. Đây là url api server của mình. Lúc này các bạn cũng để ý các query phía sau url như code, scope, đây là những tham số do google tự sinh ra và gửi lại cho mình.

  4. Server sẽ lấy được giá trị code thông qua query và tiến hành gọi lên Google API để lấy thông tin id_tokenaccess_token.

  5. Server sẽ lấy thông tin id_tokenaccess_token để gọi lên Google API 1 lần nữa để lấy thông tin người dùng như email, name, avatar, ...

  6. Có được email người dùng rồi thì kiểm tra trong database xem thử email này đã được đăng ký chưa. Nếu chưa thì tạo mới user (mật khẩu có thể cho random, sau này người dùng reset mật khẩu để đổi mật khẩu cũng được)

  7. Tạo access_tokenrefresh_token

  8. Server redirect về https://phamhongduc.com/login?access_token=...&refresh_token=...

  9. Website của mình nhận được access_tokenrefresh_token qua query và tiến hành lưu vào local storage để sử dụng cho các request sau. Dùng cookie thì tại bước 8 chúng ta sẽ redirect về https://phamhongduc.com/login và set cookie ở đây.

Đấy, nói chung flow cơ bản sẽ diễn ra như thế, còn biến tấu gì thêm là tùy vào hệ thống mỗi người.

🎉Đây là link github demo: https://github.com/phamhongduc-dev/OAuth-Google

Các bạn cứ clone về, sau đó vào file .env của folder clientserver để thay đổi các giá trị tương ứng với các giá trị của các bạn nhé.

Source code trên mình làm thuần, nghĩa là không dùng Passport hay googleapis, để các bạn hiểu flow hoạt động nó như thế nào.

Bây giờ thì chúng ta học lý thuyết thôi 😆


🥇 Nguyên tắc của OAuth 2.0

OAuth 2.0 là một giao thức ủy quyền (authorization protocol) chứ không phải là một giao thức xác thực (authentication protocol).

OAuth 2.0 sử dụng access token để ủy quyền cho các ứng dụng truy cập vào các tài nguyên người dùng. Thường thì access token này sẽ theo format JWT (JSON Web Token).


🥇 Các bên trong OAuth 2.0

Một hệ thống OAuth 2.0 bao gồm 4 bên:

  • Resource Owner: là người sở hữu tài nguyên, ví dụ như người dùng của ứng dụng.

  • Resource Server: là nơi lưu trữ tài nguyên, ví dụ như server API của ứng dụng.

  • Client: là ứng dụng muốn truy cập vào tài nguyên của người dùng.

  • Authorization Server: là nơi cấp phát access token cho client (thường là cùng một server với Resource Server).


🥇 Phạm vi của OAuth 2.0

Phạm vi (Scopes) là concept quan trọng của OAuth 2.0. Nó cho phép người dùng có thể chọn xem ứng dụng sẽ được phép truy cập vào những tài nguyên nào. Lúc mà chúng ta login thì sẽ thấy có một popup hiện lên thông báo ứng dụng sẽ truy cập vào những thông tin gì của người dùng.


🥇 Tài nguyên tham khảo thêm

Nguồn bài viết: https://duthanhduoc.com

Phạm Hồng Đức
Phạm Hồng Đức
Một developer thích nghiên cứu và chia sẻ kiến thức lập trình, phần mềm mã nguồn mở (open-source), và cuộc sống.