[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:
-
[P2] Nhập môn Authentication: Cookie và Session Authentication
-
[P4] Nhập môn Authentication: Lưu JWT token ở local storage hay cookie?
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
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
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
Tiếp theo chúng ta sẽ tiến hành tạo một 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
Đ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 Type là External -> Create
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
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
Ở đâ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.email và userinfo.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
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
🥈 3. Tạo Credential
Chọn Credentials -> Create Credentials -> 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 ID và Client 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 client
và server
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:
-
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 -
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. -
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. -
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 tinid_token
vàaccess_token
. -
Server sẽ lấy thông tin
id_token
vàaccess_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, ... -
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)
-
Tạo
access_token
vàrefresh_token
-
Server redirect về
https://phamhongduc.com/login?access_token=...&refresh_token=...
-
Website của mình nhận được
access_token
vàrefresh_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 client
và server
để 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