Thư viện JavaScript google.accounts.oauth2
giúp bạn nhắc người dùng đồng ý và lấy mã truy cập để xử lý dữ liệu người dùng. Thư viện này dựa trên quy trình cấp quyền ngầm OAuth 2.0 và được thiết kế để cho phép bạn gọi trực tiếp các API của Google bằng cách sử dụng REST và CORS, hoặc sử dụng thư viện ứng dụng API của Google cho JavaScript (còn gọi là gapi.client
) để truy cập đơn giản và linh hoạt vào các API phức tạp hơn của chúng tôi.
Trước khi truy cập vào dữ liệu người dùng được bảo vệ từ trình duyệt, người dùng trên trang web của bạn sẽ kích hoạt quy trình chọn tài khoản, đăng nhập và đồng ý dựa trên web của Google, sau cùng, các máy chủ OAuth của Google sẽ phát hành và trả về mã truy cập cho ứng dụng web của bạn.
Trong mô hình uỷ quyền dựa trên mã thông báo, bạn không cần lưu trữ mã làm mới cho mỗi người dùng trên máy chủ phụ trợ.
Bạn nên làm theo phương pháp được trình bày ở đây thay vì các kỹ thuật được đề cập trong hướng dẫn cũ hơn về OAuth 2.0 cho ứng dụng web phía máy khách.
Điều kiện tiên quyết
Làm theo các bước được mô tả trong phần Thiết lập để định cấu hình Màn hình đồng ý OAuth, lấy mã ứng dụng và tải thư viện ứng dụng.
Khởi chạy ứng dụng mã thông báo
Gọi initTokenClient()
để khởi chạy một ứng dụng mã thông báo mới bằng mã ứng dụng khách của ứng dụng web. Bạn cần thêm một danh sách gồm một hoặc nhiều phạm vi mà người dùng cần truy cập:
const client = google.accounts.oauth2.initTokenClient({
client_id: 'YOUR_GOOGLE_CLIENT_ID',
scope: 'https://www.googleapis.com/auth/calendar.readonly',
callback: (response) => {
...
},
});
Kích hoạt quy trình mã thông báo OAuth 2.0
Sử dụng phương thức requestAccessToken()
để kích hoạt quy trình trải nghiệm người dùng mã thông báo và lấy mã truy cập. Google nhắc người dùng:
- Chọn tài khoản của họ,
- đăng nhập vào Tài khoản Google nếu chưa đăng nhập,
- cấp sự đồng ý cho ứng dụng web của bạn để truy cập vào từng phạm vi được yêu cầu.
Một cử chỉ của người dùng sẽ kích hoạt luồng mã thông báo: <button onclick="client.requestAccessToken();">Authorize me</button>
Sau đó, Google sẽ trả về một TokenResponse
chứa mã truy cập và danh sách các phạm vi mà người dùng đã cấp quyền truy cập hoặc một lỗi cho trình xử lý lệnh gọi lại của bạn.
Người dùng có thể đóng trình chọn tài khoản hoặc cửa sổ đăng nhập. Trong trường hợp đó, hàm gọi lại của bạn sẽ không được gọi.
Cách xử lý sự đồng ý
Bạn chỉ nên triển khai thiết kế và trải nghiệm người dùng cho ứng dụng sau khi xem xét kỹ lưỡng Chính sách OAuth 2.0 của Google. Những chính sách này bao gồm việc sử dụng nhiều phạm vi, thời điểm và cách xử lý sự đồng ý của người dùng, v.v.
Uỷ quyền gia tăng là một chính sách và phương pháp thiết kế ứng dụng được dùng để yêu cầu quyền truy cập vào tài nguyên, chỉ sử dụng các phạm vi khi cần chứ không phải ngay từ đầu và tất cả cùng một lúc. Người dùng có thể phê duyệt hoặc từ chối chia sẻ từng tài nguyên mà ứng dụng của bạn yêu cầu. Đây được gọi là quyền chi tiết.
Trong quá trình này, Google sẽ nhắc người dùng đồng ý, liệt kê riêng từng phạm vi được yêu cầu, người dùng chọn những tài nguyên sẽ được chia sẻ với ứng dụng của bạn và cuối cùng, Google sẽ gọi hàm gọi lại của bạn để trả về một mã truy cập và các phạm vi được người dùng phê duyệt. Sau đó, ứng dụng của bạn sẽ xử lý an toàn nhiều kết quả có thể xảy ra với các quyền chi tiết.
Tuy nhiên, vẫn có một số trường hợp ngoại lệ. Các ứng dụng Google Workspace Enterprise có quyền uỷ quyền trên toàn miền hoặc các ứng dụng được đánh dấu là Đáng tin cậy, sẽ bỏ qua màn hình đồng ý cấp quyền chi tiết. Đối với những ứng dụng này, người dùng sẽ không thấy màn hình yêu cầu sự đồng ý cấp quyền chi tiết. Thay vào đó, ứng dụng của bạn sẽ nhận được tất cả các phạm vi đã yêu cầu hoặc không nhận được phạm vi nào.
Để biết thêm thông tin chi tiết, hãy xem bài viết Cách xử lý các quyền ở cấp độ chi tiết.
Uỷ quyền gia tăng
Đối với các ứng dụng web, 2 trường hợp cấp cao sau đây minh hoạ việc uỷ quyền gia tăng bằng cách sử dụng:
- Một ứng dụng Ajax trang đơn, thường sử dụng
XMLHttpRequest
với quyền truy cập động vào các tài nguyên. - Nhiều trang web, tài nguyên được tách biệt và quản lý trên cơ sở mỗi trang.
Hai trường hợp này được trình bày để minh hoạ các yếu tố và phương pháp thiết kế cần cân nhắc, nhưng không nhằm mục đích đưa ra các đề xuất toàn diện về cách tích hợp sự đồng ý vào ứng dụng của bạn. Các ứng dụng trong thực tế có thể sử dụng một biến thể hoặc kết hợp các kỹ thuật này.
Ajax
Thêm tính năng hỗ trợ uỷ quyền gia tăng vào ứng dụng của bạn bằng cách thực hiện nhiều lệnh gọi đến requestAccessToken()
và sử dụng tham số scope
của đối tượng OverridableTokenClientConfig
để yêu cầu các phạm vi riêng lẻ tại thời điểm cần thiết và chỉ khi cần thiết. Trong ví dụ này, các tài nguyên sẽ được yêu cầu và chỉ hiển thị sau khi người dùng mở rộng một phần nội dung bị thu gọn bằng cử chỉ.
Ứng dụng Ajax |
---|
Khởi chạy ứng dụng mã thông báo khi tải trang:
const client = google.accounts.oauth2.initTokenClient({ client_id: 'YOUR_GOOGLE_CLIENT_ID', callback: "onTokenResponse", }); Tài liệu để đọcHiện các tài liệu gần đây client.requestAccessToken( overrideConfig = ({ scope = 'https://www.googleapis.com/auth/documents.readonly' }) ); Sự kiện sắp tớiHiện thông tin lịch client.requestAccessToken( overrideConfig = ({ scope = 'https://www.googleapis.com/auth/calendar.readonly' }) ); Băng chuyền ảnhHiển thị ảnh client.requestAccessToken( overrideConfig = ({ scope = 'https://www.googleapis.com/auth/photoslibrary.readonly' }) ); |
Mỗi lệnh gọi đến requestAccessToken
sẽ kích hoạt một thời điểm đồng ý của người dùng, ứng dụng của bạn sẽ chỉ có quyền truy cập vào những tài nguyên mà phần người dùng chọn mở rộng yêu cầu, do đó hạn chế việc chia sẻ tài nguyên thông qua lựa chọn của người dùng.
Nhiều trang web
Khi thiết kế để uỷ quyền gia tăng, nhiều trang được dùng để chỉ yêu cầu(các) phạm vi cần thiết để tải một trang, giảm độ phức tạp và nhu cầu thực hiện nhiều lệnh gọi để có được sự đồng ý của người dùng và truy xuất mã truy cập.
Ứng dụng nhiều trang | ||||||||
---|---|---|---|---|---|---|---|---|
|
Mỗi trang yêu cầu phạm vi cần thiết và nhận mã truy cập bằng cách gọi initTokenClient()
và requestAccessToken()
tại thời điểm tải. Trong trường hợp này, các trang web riêng lẻ được dùng để tách biệt rõ ràng chức năng và tài nguyên của người dùng theo phạm vi. Trong tình huống thực tế, các trang riêng lẻ có thể yêu cầu nhiều phạm vi liên quan.
Quyền chi tiết
Quyền chi tiết được xử lý theo cách tương tự trong mọi trường hợp; sau khi requestAccessToken()
gọi hàm gọi lại của bạn và mã truy cập được trả về, hãy kiểm tra để đảm bảo rằng người dùng đã phê duyệt các phạm vi được yêu cầu bằng cách sử dụng hasGrantedAllScopes()
hoặc hasGrantedAnyScope()
. Ví dụ:
const client = google.accounts.oauth2.initTokenClient({
client_id: 'YOUR_GOOGLE_CLIENT_ID',
scope: 'https://www.googleapis.com/auth/calendar.readonly \
https://www.googleapis.com/auth/documents.readonly \
https://www.googleapis.com/auth/photoslibrary.readonly',
callback: (tokenResponse) => {
if (tokenResponse && tokenResponse.access_token) {
if (google.accounts.oauth2.hasGrantedAnyScope(tokenResponse,
'https://www.googleapis.com/auth/photoslibrary.readonly')) {
// Look at pictures
...
}
if (google.accounts.oauth2.hasGrantedAllScopes(tokenResponse,
'https://www.googleapis.com/auth/calendar.readonly',
'https://www.googleapis.com/auth/documents.readonly')) {
// Meeting planning and review documents
...
}
}
},
});
Mọi yêu cầu hoặc lần cấp quyền đã được chấp nhận trước đó trong các phiên trước cũng sẽ được đưa vào phản hồi. Hồ sơ về sự đồng ý của người dùng được duy trì cho mỗi người dùng và Mã nhận dạng ứng dụng, đồng thời vẫn tồn tại trên nhiều lệnh gọi đến initTokenClient()
hoặc requestAccessToken()
. Theo mặc định, người dùng chỉ cần đồng ý vào lần đầu tiên truy cập vào trang web của bạn và yêu cầu một phạm vi mới, nhưng có thể được yêu cầu đồng ý trên mỗi lần tải trang bằng cách sử dụng prompt=consent
trong các đối tượng cấu hình Token Client.
Làm việc với mã thông báo
Trong mô hình Mã thông báo, hệ điều hành hoặc trình duyệt không lưu trữ mã thông báo truy cập, thay vào đó, mã thông báo mới sẽ được lấy lần đầu tiên vào thời gian tải trang hoặc sau đó bằng cách kích hoạt một lệnh gọi đến requestAccessToken()
thông qua một cử chỉ của người dùng, chẳng hạn như nhấn nút.
Sử dụng REST và CORS với các API của Google
Bạn có thể dùng mã truy cập để gửi các yêu cầu đã xác thực đến API của Google bằng cách sử dụng REST và CORS. Điều này cho phép người dùng đăng nhập, đồng ý, Google cấp mã truy cập và trang web của bạn xử lý dữ liệu của người dùng.
Trong ví dụ này, hãy xem các sự kiện sắp tới trong lịch của người dùng đã đăng nhập bằng mã truy cập do tokenRequest()
trả về:
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://www.googleapis.com/calendar/v3/calendars/primary/events');
xhr.setRequestHeader('Authorization', 'Bearer ' + tokenResponse.access_token);
xhr.send();
Hãy xem bài viết Cách sử dụng CORS để truy cập vào các API của Google để biết thêm thông tin.
Mục tiếp theo trình bày cách dễ dàng tích hợp với các API phức tạp hơn.
Làm việc với thư viện JavaScript của API Google
Ứng dụng mã thông báo hoạt động với Thư viện ứng dụng Google API cho JavaScript. Hãy xem đoạn mã bên dưới.
const client = google.accounts.oauth2.initTokenClient({
client_id: 'YOUR_GOOGLE_CLIENT_ID',
scope: 'https://www.googleapis.com/auth/calendar.readonly',
callback: (tokenResponse) => {
if (tokenResponse && tokenResponse.access_token) {
gapi.client.setApiKey('YOUR_API_KEY');
gapi.client.load('calendar', 'v3', listUpcomingEvents);
}
},
});
function listUpcomingEvents() {
gapi.client.calendar.events.list(...);
}
Thời hạn của mã thông báo
Theo thiết kế, mã truy cập có thời gian tồn tại ngắn. Nếu mã truy cập hết hạn trước khi phiên hoạt động của người dùng kết thúc, hãy lấy mã thông báo mới bằng cách gọi requestAccessToken()
từ một sự kiện do người dùng kích hoạt, chẳng hạn như khi người dùng nhấn nút.
Sử dụng mã truy cập để thu hồi sự đồng ý
Gọi phương thức google.accounts.oauth2.revoke
để xoá sự đồng ý của người dùng và quyền truy cập vào tài nguyên cho tất cả các phạm vi được cấp cho ứng dụng của bạn. Bạn cần có mã truy cập hợp lệ để thu hồi quyền này:
google.accounts.oauth2.revoke('414a76cb127a7ece7ee4bf287602ca2b56f8fcbf7fcecc2cd4e0509268120bd7', done => {
console.log(done);
console.log(done.successful);
console.log(done.error);
console.log(done.error_description);
});