Tổng quan
Để lấy mã thông báo truy cập cho mỗi người dùng nhằm gọi API của Google, Google cung cấp nhiều thư viện JavaScript:
Hướng dẫn này cung cấp hướng dẫn di chuyển từ các thư viện này sang thư viện Dịch vụ nhận dạng của Google.
Bằng cách làm theo hướng dẫn này, bạn sẽ:
- thay thế Thư viện nền tảng đã ngừng hoạt động bằng thư viện Dịch vụ nhận dạng và
- nếu sử dụng Thư viện ứng dụng API, hãy xoá mô-đun
gapi.auth2
không dùng nữa, các phương thức và đối tượng của mô-đun đó, thay thế bằng các phương thức và đối tượng tương đương của Dịch vụ nhận dạng.
Để biết nội dung mô tả về những thay đổi đối với thư viện JavaScript của Dịch vụ nhận dạng, hãy đọc phần tổng quan và cách hoạt động của tính năng uỷ quyền người dùng để xem lại các thuật ngữ và khái niệm chính.
Nếu bạn đang tìm cách xác thực để người dùng đăng ký và đăng nhập, hãy xem phần Di chuyển từ tính năng Đăng nhập bằng Google.
Xác định quy trình uỷ quyền
Có thể có hai quy trình uỷ quyền cho người dùng: mã ngầm ẩn và mã uỷ quyền.
Xem xét ứng dụng web của bạn để xác định loại quy trình uỷ quyền đang được sử dụng.
Dấu hiệu cho thấy ứng dụng web của bạn đang sử dụng luồng ngầm ẩn:
- Ứng dụng web của bạn hoàn toàn dựa trên trình duyệt, không có nền tảng phụ trợ.
- Người dùng phải có mặt để gọi API của Google, ứng dụng của bạn chỉ sử dụng mã thông báo truy cập và không yêu cầu mã thông báo làm mới.
- Ứng dụng web của bạn tải
apis.google.com/js/api.js
. - Quá trình triển khai của bạn dựa trên OAuth 2.0 cho Ứng dụng web phía máy khách.
- Ứng dụng của bạn dùng các mô-đun
gapi.client
hoặcgapi.auth2
có trong Thư viện ứng dụng API của Google dành cho JavaScript.
Các dấu hiệu cho thấy ứng dụng web của bạn đang sử dụng quy trình mã uỷ quyền:
Phương thức triển khai của bạn dựa trên:
Ứng dụng của bạn thực thi cả trong trình duyệt của người dùng và trên nền tảng phụ trợ.
Nền tảng phụ trợ của bạn lưu trữ một điểm cuối mã uỷ quyền.
Nền tảng phụ trợ của bạn thay mặt người dùng gọi các API của Google mà không yêu cầu họ phải có mặt, còn gọi là chế độ ngoại tuyến.
Mã làm mới do nền tảng phụ trợ của bạn quản lý và lưu trữ.
Trong một số trường hợp, cơ sở mã của bạn có thể hỗ trợ cả hai luồng.
Chọn quy trình uỷ quyền
Trước khi bắt đầu di chuyển, bạn cần xác định xem nên tiếp tục sử dụng quy trình hiện tại hay áp dụng một quy trình khác phù hợp nhất với nhu cầu của mình.
Xem xét chọn một quy trình uỷ quyền để tìm hiểu những điểm khác biệt và đánh đổi chính giữa hai quy trình này.
Trong hầu hết các trường hợp, bạn nên sử dụng quy trình mã uỷ quyền vì quy trình này cung cấp mức độ bảo mật cao nhất cho người dùng. Việc triển khai quy trình này cũng cho phép nền tảng của bạn dễ dàng thêm các chức năng mới khi không có mạng hơn, chẳng hạn như tìm nạp nội dung cập nhật để thông báo cho người dùng về những thay đổi đáng chú ý đối với lịch, ảnh, gói thuê bao, v.v.
Chọn một luồng uỷ quyền bằng cách sử dụng bộ chọn bên dưới.
Luồng ngầm ẩn
Lấy mã truy cập để sử dụng trong trình duyệt khi có người dùng.
Ví dụ về luồng ngầm ẩn cho thấy các ứng dụng web trước và sau khi di chuyển sang Dịch vụ nhận dạng.
Quy trình sử dụng mã uỷ quyền
Mã uỷ quyền cho mỗi người dùng do Google phát hành sẽ được phân phối đến nền tảng phụ trợ của bạn, sau đó được trao đổi lấy mã truy cập và mã làm mới.
Ví dụ về quy trình mã uỷ quyền cho thấy các ứng dụng web trước và sau khi di chuyển sang Dịch vụ nhận dạng.
Trong suốt hướng dẫn này, hãy làm theo hướng dẫn được in đậm để Thêm, Xoá, Cập nhật hoặc Thay thế chức năng hiện có.
Các thay đổi đối với ứng dụng web trong trình duyệt
Phần này xem xét những thay đổi mà bạn sẽ thực hiện đối với ứng dụng web trong trình duyệt khi di chuyển sang thư viện JavaScript Dịch vụ nhận dạng của Google.
Xác định mã bị ảnh hưởng và hoạt động kiểm thử
Cookie gỡ lỗi có thể giúp xác định vị trí mã bị ảnh hưởng và kiểm thử hành vi sau khi ngừng sử dụng.
Trong các ứng dụng lớn hoặc phức tạp, bạn có thể khó tìm thấy tất cả mã bị ảnh hưởng khi mô-đun gapi.auth2
không còn được dùng nữa. Để ghi lại hoạt động sử dụng hiện có của chức năng sắp bị ngừng sử dụng vào bảng điều khiển, hãy đặt giá trị của cookie G_AUTH2_MIGRATION
thành informational
. Nếu muốn, hãy thêm dấu hai chấm, theo sau là một giá trị khoá để cũng ghi nhật ký vào bộ nhớ phiên. Sau khi đăng nhập và nhận thông tin xác thực, hãy xem xét hoặc gửi nhật ký đã thu thập đến phần phụ trợ để phân tích sau. Ví dụ: informational:showauth2use
lưu nguồn gốc và URL vào khoá bộ nhớ phiên có tên showauth2use
.
Để xác minh hành vi của ứng dụng khi mô-đun gapi.auth2
không còn tải nữa, hãy đặt giá trị của cookie G_AUTH2_MIGRATION
thành enforced
. Điều này cho phép kiểm thử hành vi sau khi ngừng sử dụng trước ngày thực thi.
Có thể có G_AUTH2_MIGRATION
giá trị cookie:
enforced
Không tải mô-đungapi.auth2
.informational
Ghi lại việc sử dụng chức năng không dùng nữa vào bảng điều khiển JS. Đồng thời ghi vào bộ nhớ phiên khi đặt tên khoá không bắt buộc:informational:key-name
.
Để giảm thiểu tác động đến người dùng, trước tiên, bạn nên đặt cookie này trên máy trong quá trình phát triển và kiểm thử, trước khi sử dụng cookie này trong môi trường phát hành chính thức.
Thư viện và mô-đun
Mô-đun gapi.auth2
quản lý việc xác thực người dùng để đăng nhập và luồng ngầm ẩn để uỷ quyền, thay thế mô-đun đã ngừng hoạt động này cũng như các đối tượng và phương thức của mô-đun đó bằng thư viện Dịch vụ nhận dạng của Google.
Thêm thư viện Dịch vụ nhận dạng vào ứng dụng web bằng cách đưa thư viện đó vào tài liệu:
<script src="https://accounts.google.com/gsi/client" async defer></script>
Xoá mọi thực thể tải mô-đun auth2
bằng gapi.load('auth2',
function)
.
Thư viện Dịch vụ nhận dạng của Google thay thế việc sử dụng mô-đun gapi.auth2
.
Bạn có thể yên tâm tiếp tục sử dụng mô-đun gapi.client
trong Thư viện ứng dụng API của Google dành cho JavaScript, đồng thời tận dụng tính năng tự động tạo các phương thức JS có thể gọi từ một tài liệu khám phá, phân lô nhiều lệnh gọi API và chức năng quản lý CORS.
Bánh quy
Việc uỷ quyền cho người dùng không yêu cầu sử dụng cookie.
Xem bài viết Di chuyển từ phương thức Đăng nhập bằng Google để biết thông tin chi tiết về cách quy trình xác thực người dùng sử dụng cookie và Cách Google sử dụng cookie để sử dụng cookie trong các sản phẩm và dịch vụ khác của Google.
Thông tin xác thực
Dịch vụ nhận dạng của Google tách hoạt động xác thực và uỷ quyền người dùng thành 2 hoạt động riêng biệt, đồng thời thông tin đăng nhập của người dùng là riêng biệt: mã thông báo mã nhận dạng dùng để xác định người dùng sẽ được trả về riêng biệt với mã truy cập dùng để uỷ quyền.
Để xem những thay đổi này, hãy xem thông tin xác thực mẫu.
Luồng ngầm ẩn
Tách biệt quy trình xác thực và uỷ quyền người dùng bằng cách xoá hoạt động xử lý hồ sơ người dùng khỏi luồng uỷ quyền.
Xoá các thông tin tham chiếu ứng dụng JavaScript Đăng nhập bằng Google sau:
Phương thức
GoogleUser.getBasicProfile()
GoogleUser.getId()
Quy trình sử dụng mã uỷ quyền
Dịch vụ danh tính tách thông tin đăng nhập trong trình duyệt thành mã thông báo nhận dạng và mã thông báo truy cập. Thay đổi này không áp dụng cho thông tin xác thực thu được thông qua các lệnh gọi trực tiếp đến các điểm cuối OAuth 2.0 của Google từ nền tảng phụ trợ hoặc thông qua các thư viện chạy trên một máy chủ bảo mật trên nền tảng của bạn, chẳng hạn như Ứng dụng Node.js của API Google.
Trạng thái phiên
Trước đây, tính năng Đăng nhập bằng Google giúp bạn quản lý trạng thái đăng nhập của người dùng bằng cách sử dụng:
- Trình xử lý gọi lại để Theo dõi trạng thái phiên của người dùng.
- Trình nghe đối với các sự kiện và thay đổi đối với trạng thái đã đăng nhập của Tài khoản Google của người dùng.
Bạn chịu trách nhiệm quản lý trạng thái đăng nhập và phiên người dùng cho ứng dụng web của mình.
Xoá các thông tin tham chiếu ứng dụng JavaScript Đăng nhập bằng Google sau:
Đối tượng:
gapi.auth2.SignInOptions
Phương thức:
GoogleAuth.attachClickHandler()
GoogleAuth.isSignedIn()
GoogleAuth.isSignedIn.get()
GoogleAuth.isSignedIn.listen()
GoogleAuth.signIn()
GoogleAuth.signOut()
GoogleAuth.currentUser.get()
GoogleAuth.currentUser.listen()
GoogleUser.isSignedIn()
Cấu hình ứng dụng
Cập nhật ứng dụng web để khởi tạo ứng dụng khách mã thông báo cho luồng mã uỷ quyền hoặc ngầm ẩn.
Xoá các thông tin tham chiếu ứng dụng JavaScript Đăng nhập bằng Google sau:
Đối tượng:
gapi.auth2.ClientConfig
gapi.auth2.OfflineAccessOptions
Phương thức:
gapi.auth2.getAuthInstance()
GoogleUser.grant()
Luồng ngầm ẩn
Thêm đối tượng TokenClientConfig
và lệnh gọi initTokenClient()
để định cấu hình ứng dụng web, theo ví dụ trong phần khởi chạy ứng dụng mã thông báo.
Thay thế tệp tham chiếu ứng dụng JavaScript Đăng nhập bằng Google bằng Dịch vụ nhận dạng của Google:
Đối tượng:
gapi.auth2.AuthorizeConfig
vớiTokenClientConfig
Phương thức:
gapi.auth2.init()
vớigoogle.accounts.oauth2.initTokenClient()
Các thông số:
gapi.auth2.AuthorizeConfig.login_hint
vớiTokenClientConfig.login_hint
.gapi.auth2.GoogleUser.getHostedDomain()
vớiTokenClientConfig.hd
.
Quy trình sử dụng mã uỷ quyền
Thêm đối tượng CodeClientConfig
và lệnh gọi initCodeClient()
để định cấu hình ứng dụng web, theo ví dụ trong phần khởi chạy ứng dụng mã.
Khi chuyển từ trạng thái ngầm ẩn sang quy trình mã uỷ quyền:
Xoá các tệp tham chiếu ứng dụng JavaScript Đăng nhập bằng Google
Đối tượng:
gapi.auth2.AuthorizeConfig
Phương thức:
gapi.auth2.init()
Các thông số:
gapi.auth2.AuthorizeConfig.login_hint
gapi.auth2.GoogleUser.getHostedDomain()
Yêu cầu mã thông báo
Một cử chỉ của người dùng, chẳng hạn như một lượt nhấp vào nút, sẽ tạo ra một yêu cầu dẫn đến việc mã thông báo truy cập được trả về trực tiếp cho trình duyệt của người dùng bằng luồng ngầm ẩn hoặc cho nền tảng phụ trợ của bạn sau khi trao đổi mã uỷ quyền cho mỗi người dùng để lấy mã thông báo truy cập và mã thông báo làm mới.
Luồng ngầm ẩn
Bạn có thể lấy và sử dụng mã thông báo truy cập trong trình duyệt khi người dùng đã đăng nhập và có phiên hoạt động với Google. Đối với chế độ ngầm ẩn, người dùng phải thực hiện một cử chỉ để yêu cầu mã thông báo truy cập, ngay cả khi đã có yêu cầu trước đó.
Thay thế tệp tham chiếu ứng dụng JavaScript Đăng nhập bằng Google: bằng Dịch vụ nhận dạng của Google:
Phương thức:
gapi.auth2.authorize()
vớiTokenClient.requestAccessToken()
GoogleUser.reloadAuthResponse()
vớiTokenClient.requestAccessToken()
Thêm đường liên kết hoặc nút để gọi requestAccessToken()
nhằm bắt đầu quy trình trải nghiệm người dùng bật lên để yêu cầu mã thông báo truy cập hoặc để lấy mã thông báo mới khi mã thông báo hiện tại hết hạn.
Cập nhật cơ sở mã của bạn thành:
- Kích hoạt quy trình mã thông báo OAuth 2.0 bằng
requestAccessToken()
. - Hỗ trợ uỷ quyền gia tăng bằng cách sử dụng
requestAccessToken
vàOverridableTokenClientConfig
để tách một yêu cầu cho nhiều phạm vi thành nhiều yêu cầu nhỏ hơn. - Yêu cầu mã thông báo mới khi mã thông báo hiện có hết hạn hoặc bị thu hồi.
Khi xử lý nhiều phạm vi, bạn có thể phải thay đổi cấu trúc cơ sở mã để chỉ yêu cầu quyền truy cập vào các phạm vi khi cần thiết thay vì tất cả cùng một lúc. Đây được gọi là uỷ quyền dần. Mỗi yêu cầu phải chứa càng ít phạm vi càng tốt và tốt nhất là một phạm vi duy nhất. Hãy xem phần cách xử lý sự đồng ý của người dùng để biết thêm về cách cập nhật ứng dụng của bạn nhằm tăng cường tính năng uỷ quyền.
Khi mã thông báo truy cập hết hạn, mô-đun gapi.auth2
sẽ tự động lấy một mã thông báo truy cập mới, hợp lệ cho ứng dụng web của bạn. Để cải thiện tính bảo mật cho người dùng, thư viện Dịch vụ nhận dạng của Google không hỗ trợ quy trình làm mới mã thông báo tự động này. Bạn phải cập nhật ứng dụng web để phát hiện mã thông báo truy cập đã hết hạn và yêu cầu mã mới. Hãy xem phần Xử lý mã thông báo bên dưới để biết thêm thông tin.
Quy trình sử dụng mã uỷ quyền
Thêm đường liên kết hoặc nút để gọi requestCode()
nhằm yêu cầu mã uỷ quyền từ Google. Ví dụ: hãy xem phần Kích hoạt quy trình mã OAuth 2.0.
Hãy xem phần Xử lý mã thông báo bên dưới để biết thêm về cách phản hồi mã thông báo truy cập đã hết hạn hoặc bị thu hồi.
Xử lý mã thông báo
Thêm tính năng xử lý lỗi để phát hiện các lệnh gọi API Google không thành công khi sử dụng mã truy cập đã hết hạn hoặc bị thu hồi, đồng thời yêu cầu mã truy cập mới, hợp lệ.
API của Google sẽ trả về mã trạng thái HTTP là 401 Unauthorized
và thông báo lỗi invalid_token
khi bạn sử dụng mã thông báo truy cập đã hết hạn hoặc bị thu hồi. Để biết ví dụ, hãy xem phần Phản hồi mã thông báo không hợp lệ.
Mã thông báo đã hết hạn
Mã thông báo truy cập có thời hạn ngắn và thường chỉ hợp lệ trong vài phút.
Thu hồi mã thông báo
Chủ sở hữu Tài khoản Google có thể thu hồi sự đồng ý đã cấp bất cứ lúc nào. Việc này sẽ vô hiệu hoá các mã truy cập và mã làm mới hiện có. Việc thu hồi có thể được kích hoạt từ nền tảng của bạn bằng cách sử dụng revoke()
hoặc thông qua Tài khoản Google.
Thay thế tệp tham chiếu ứng dụng JavaScript Đăng nhập bằng Google: bằng Dịch vụ nhận dạng của Google:
Phương thức:
getAuthInstance().disconnect()
vớigoogle.accounts.oauth2.revoke()
GoogleUser.disconnect()
vớigoogle.accounts.oauth2.revoke()
Gọi revoke
khi người dùng xoá tài khoản của họ trên nền tảng của bạn hoặc muốn xoá sự đồng ý chia sẻ dữ liệu với ứng dụng của bạn.
Lời nhắc đồng ý của người dùng
Google sẽ hiển thị hộp thoại đồng ý cho người dùng khi ứng dụng web hoặc nền tảng phụ trợ của bạn yêu cầu mã thông báo truy cập. Hãy xem ví dụ về hộp thoại đồng ý mà Google hiển thị cho người dùng.
Trước khi phát hành mã truy cập cho ứng dụng, bạn phải có một phiên Google hiện có và đang hoạt động để nhắc người dùng đồng ý và ghi lại kết quả. Người dùng có thể được yêu cầu đăng nhập vào Tài khoản Google nếu chưa có phiên hoạt động nào.
Đăng nhập của người dùng
Người dùng có thể đăng nhập vào Tài khoản Google trong một thẻ trình duyệt riêng hoặc đăng nhập nguyên gốc thông qua một trình duyệt hoặc hệ điều hành. Bạn nên thêm tính năng Đăng nhập bằng Google vào trang web của mình để thiết lập một phiên hoạt động giữa một Tài khoản Google và trình duyệt khi người dùng mở ứng dụng của bạn lần đầu tiên. Việc này mang lại những lợi ích sau:
- Giảm thiểu số lần người dùng phải đăng nhập, yêu cầu mã truy cập sẽ bắt đầu quy trình đăng nhập vào Tài khoản Google nếu phiên đang hoạt động chưa tồn tại.
- Trực tiếp sử dụng trường
email
thông tin xác thực mã nhận dạng JWT làm giá trị của tham sốlogin_hint
trong đối tượngCodeClientConfig
hoặcTokenClientConfig
. Điều này đặc biệt hữu ích nếu nền tảng của bạn không duy trì hệ thống quản lý tài khoản người dùng. - Tìm và liên kết Tài khoản Google với tài khoản người dùng cục bộ hiện có trên nền tảng của bạn, giúp giảm thiểu số lượng tài khoản trùng lặp trên nền tảng của bạn.
- Khi tạo một tài khoản cục bộ mới, bạn có thể tách biệt rõ ràng hộp thoại và quy trình đăng ký với hộp thoại và quy trình xác thực người dùng, giảm số bước bắt buộc và cải thiện tỷ lệ bỏ ngang.
Sau khi đăng nhập và trước khi cấp mã truy cập, người dùng phải đồng ý với ứng dụng của bạn trong các phạm vi đã yêu cầu.
Mã thông báo và phản hồi về sự đồng ý
Sau khi người dùng đồng ý, hệ thống sẽ trả về một mã thông báo truy cập cùng với danh sách các phạm vi mà người dùng đã phê duyệt hoặc từ chối.
Quyền chi tiết cho phép người dùng phê duyệt hoặc từ chối từng phạm vi. Khi yêu cầu quyền truy cập vào nhiều phạm vi, mỗi phạm vi sẽ được cấp hoặc bị từ chối độc lập với các phạm vi khác. Dựa trên lựa chọn của người dùng, ứng dụng của bạn sẽ bật các tính năng và chức năng một cách có chọn lọc, tuỳ thuộc vào phạm vi riêng lẻ.
Luồng ngầm ẩn
Thay thế các tệp tham chiếu ứng dụng JavaScript Đăng nhập bằng Google bằng Dịch vụ nhận dạng của Google:
Đối tượng:
gapi.auth2.AuthorizeResponse
vớiTokenClient.TokenResponse
gapi.auth2.AuthResponse
vớiTokenClient.TokenResponse
Phương thức:
GoogleUser.hasGrantedScopes()
bằnggoogle.accounts.oauth2.hasGrantedAllScopes()
GoogleUser.getGrantedScopes()
vớigoogle.accounts.oauth2.hasGrantedAllScopes()
Xoá các tệp tham chiếu ứng dụng JavaScript Đăng nhập bằng Google:
Phương thức:
GoogleUser.getAuthResponse()
Cập nhật ứng dụng web bằng hasGrantedAllScopes()
và hasGrantedAnyScope()
bằng cách làm theo ví dụ về quyền chi tiết này.
Quy trình sử dụng mã uỷ quyền
Cập nhật hoặc Thêm điểm cuối của mã uỷ quyền vào nền tảng phụ trợ bằng cách làm theo hướng dẫn trong phần xử lý mã xác thực.
Cập nhật nền tảng của bạn để làm theo các bước được mô tả trong hướng dẫn Sử dụng mô hình mã nhằm xác thực yêu cầu và lấy mã truy cập cũng như mã làm mới.
Cập nhật nền tảng của bạn để bật hoặc tắt các tính năng và chức năng một cách có chọn lọc dựa trên các phạm vi riêng lẻ mà người dùng đã phê duyệt bằng cách làm theo hướng dẫn về quyền uỷ quyền gia tăng và kiểm tra phạm vi truy cập do người dùng cấp.
Ví dụ về luồng ngầm ẩn
Cách cũ
Thư viện ứng dụng GAPI
Ví dụ về Thư viện ứng dụng API của Google cho JavaScript chạy trong trình duyệt bằng cách sử dụng hộp thoại bật lên để người dùng đồng ý.
Mô-đun gapi.auth2
được gapi.client.init()
tự động tải và sử dụng, do đó bị ẩn.
<!DOCTYPE html>
<html>
<head>
<script src="https://apis.google.com/js/api.js"></script>
<script>
function start() {
gapi.client.init({
'apiKey': 'YOUR_API_KEY',
'clientId': 'YOUR_CLIENT_ID',
'scope': 'https://www.googleapis.com/auth/cloud-translation',
'discoveryDocs': ['https://www.googleapis.com/discovery/v1/apis/translate/v2/rest'],
}).then(function() {
// Execute an API request which is returned as a Promise.
// The method name language.translations.list comes from the API discovery.
return gapi.client.language.translations.list({
q: 'hello world',
source: 'en',
target: 'de',
});
}).then(function(response) {
console.log(response.result.data.translations[0].translatedText);
}, function(reason) {
console.log('Error: ' + reason.result.error.message);
});
};
// Load the JavaScript client library and invoke start afterwards.
gapi.load('client', start);
</script>
</head>
<body>
<div id="results"></div>
</body>
</html>
Thư viện ứng dụng JS
OAuth 2.0 cho ứng dụng web phía máy khách chạy trong trình duyệt bằng cách sử dụng hộp thoại bật lên để người dùng đồng ý.
Mô-đun gapi.auth2
được tải theo cách thủ công.
<!DOCTYPE html>
<html><head></head><body>
<script>
var GoogleAuth;
var SCOPE = 'https://www.googleapis.com/auth/drive.metadata.readonly';
function handleClientLoad() {
// Load the API's client and auth2 modules.
// Call the initClient function after the modules load.
gapi.load('client:auth2', initClient);
}
function initClient() {
// In practice, your app can retrieve one or more discovery documents.
var discoveryUrl = 'https://www.googleapis.com/discovery/v1/apis/drive/v3/rest';
// Initialize the gapi.client object, which app uses to make API requests.
// Get API key and client ID from API Console.
// 'scope' field specifies space-delimited list of access scopes.
gapi.client.init({
'apiKey': 'YOUR_API_KEY',
'clientId': 'YOUR_CLIENT_ID',
'discoveryDocs': [discoveryUrl],
'scope': SCOPE
}).then(function () {
GoogleAuth = gapi.auth2.getAuthInstance();
// Listen for sign-in state changes.
GoogleAuth.isSignedIn.listen(updateSigninStatus);
// Handle initial sign-in state. (Determine if user is already signed in.)
var user = GoogleAuth.currentUser.get();
setSigninStatus();
// Call handleAuthClick function when user clicks on
// "Sign In/Authorize" button.
$('#sign-in-or-out-button').click(function() {
handleAuthClick();
});
$('#revoke-access-button').click(function() {
revokeAccess();
});
});
}
function handleAuthClick() {
if (GoogleAuth.isSignedIn.get()) {
// User is authorized and has clicked "Sign out" button.
GoogleAuth.signOut();
} else {
// User is not signed in. Start Google auth flow.
GoogleAuth.signIn();
}
}
function revokeAccess() {
GoogleAuth.disconnect();
}
function setSigninStatus() {
var user = GoogleAuth.currentUser.get();
var isAuthorized = user.hasGrantedScopes(SCOPE);
if (isAuthorized) {
$('#sign-in-or-out-button').html('Sign out');
$('#revoke-access-button').css('display', 'inline-block');
$('#auth-status').html('You are currently signed in and have granted ' +
'access to this app.');
} else {
$('#sign-in-or-out-button').html('Sign In/Authorize');
$('#revoke-access-button').css('display', 'none');
$('#auth-status').html('You have not authorized this app or you are ' +
'signed out.');
}
}
function updateSigninStatus() {
setSigninStatus();
}
</script>
<button id="sign-in-or-out-button"
style="margin-left: 25px">Sign In/Authorize</button>
<button id="revoke-access-button"
style="display: none; margin-left: 25px">Revoke access</button>
<div id="auth-status" style="display: inline; padding-left: 25px"></div><hr>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script async defer src="https://apis.google.com/js/api.js"
onload="this.onload=function(){};handleClientLoad()"
onreadystatechange="if (this.readyState === 'complete') this.onload()">
</script>
</body></html>
Điểm cuối OAuth 2.0
OAuth 2.0 cho ứng dụng web phía máy khách chạy trong trình duyệt bằng cách sử dụng lệnh chuyển hướng đến Google để yêu cầu người dùng đồng ý.
Ví dụ này cho thấy các lệnh gọi trực tiếp đến các điểm cuối OAuth 2.0 của Google từ trình duyệt của người dùng và không sử dụng mô-đun gapi.auth2
hoặc thư viện JavaScript.
<!DOCTYPE html>
<html><head></head><body>
<script>
var YOUR_CLIENT_ID = 'REPLACE_THIS_VALUE';
var YOUR_REDIRECT_URI = 'REPLACE_THIS_VALUE';
var fragmentString = location.hash.substring(1);
// Parse query string to see if page request is coming from OAuth 2.0 server.
var params = {};
var regex = /([^&=]+)=([^&]*)/g, m;
while (m = regex.exec(fragmentString)) {
params[decodeURIComponent(m[1])] = decodeURIComponent(m[2]);
}
if (Object.keys(params).length > 0) {
localStorage.setItem('oauth2-test-params', JSON.stringify(params) );
if (params['state'] && params['state'] == 'try_sample_request') {
trySampleRequest();
}
}
// If there's an access token, try an API request.
// Otherwise, start OAuth 2.0 flow.
function trySampleRequest() {
var params = JSON.parse(localStorage.getItem('oauth2-test-params'));
if (params && params['access_token']) {
var xhr = new XMLHttpRequest();
xhr.open('GET',
'https://www.googleapis.com/drive/v3/about?fields=user&' +
'access_token=' + params['access_token']);
xhr.onreadystatechange = function (e) {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.response);
} else if (xhr.readyState === 4 && xhr.status === 401) {
// Token invalid, so prompt for user permission.
oauth2SignIn();
}
};
xhr.send(null);
} else {
oauth2SignIn();
}
}
/*
* Create form to request access token from Google's OAuth 2.0 server.
*/
function oauth2SignIn() {
// Google's OAuth 2.0 endpoint for requesting an access token
var oauth2Endpoint = 'https://accounts.google.com/o/oauth2/v2/auth';
// Create element to open OAuth 2.0 endpoint in new window.
var form = document.createElement('form');
form.setAttribute('method', 'GET'); // Send as a GET request.
form.setAttribute('action', oauth2Endpoint);
// Parameters to pass to OAuth 2.0 endpoint.
var params = {'client_id': YOUR_CLIENT_ID,
'redirect_uri': YOUR_REDIRECT_URI,
'scope': 'https://www.googleapis.com/auth/drive.metadata.readonly',
'state': 'try_sample_request',
'include_granted_scopes': 'true',
'response_type': 'token'};
// Add form parameters as hidden input values.
for (var p in params) {
var input = document.createElement('input');
input.setAttribute('type', 'hidden');
input.setAttribute('name', p);
input.setAttribute('value', params[p]);
form.appendChild(input);
}
// Add form to page and submit it to open the OAuth 2.0 endpoint.
document.body.appendChild(form);
form.submit();
}
</script>
<button onclick="trySampleRequest();">Try sample request</button>
</body></html>
Cách mới
Chỉ GIS
Ví dụ này chỉ cho thấy thư viện JavaScript Dịch vụ nhận dạng của Google sử dụng mô hình mã thông báo và hộp thoại bật lên để người dùng đồng ý. Mã này được cung cấp để minh hoạ số bước tối thiểu cần thiết để định cấu hình ứng dụng, yêu cầu và nhận mã thông báo truy cập, cũng như để gọi một API của Google.
<!DOCTYPE html>
<html>
<head>
<script src="https://accounts.google.com/gsi/client" onload="initClient()" async defer></script>
</head>
<body>
<script>
var client;
var access_token;
function initClient() {
client = google.accounts.oauth2.initTokenClient({
client_id: 'YOUR_CLIENT_ID',
scope: 'https://www.googleapis.com/auth/calendar.readonly \
https://www.googleapis.com/auth/contacts.readonly',
callback: (tokenResponse) => {
access_token = tokenResponse.access_token;
},
});
}
function getToken() {
client.requestAccessToken();
}
function revokeToken() {
google.accounts.oauth2.revoke(access_token, () => {console.log('access token revoked')});
}
function loadCalendar() {
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://www.googleapis.com/calendar/v3/calendars/primary/events');
xhr.setRequestHeader('Authorization', 'Bearer ' + access_token);
xhr.send();
}
</script>
<h1>Google Identity Services Authorization Token model</h1>
<button onclick="getToken();">Get access token</button><br><br>
<button onclick="loadCalendar();">Load Calendar</button><br><br>
<button onclick="revokeToken();">Revoke token</button>
</body>
</html>
GAPI không đồng bộ/chờ
Ví dụ này cho biết cách thêm thư viện Dịch vụ nhận dạng của Google bằng cách sử dụng mô hình mã thông báo, xoá mô-đun gapi.auth2
và gọi một API bằng Thư viện ứng dụng API của Google cho JavaScript.
Lời hứa, không đồng bộ và chờ được dùng để thực thi thứ tự tải thư viện cũng như để phát hiện và thử lại lỗi uỷ quyền. Lệnh gọi API chỉ được thực hiện sau khi có mã thông báo truy cập hợp lệ.
Người dùng sẽ nhấn nút "Hiển thị lịch" khi thiếu mã thông báo truy cập trong lần tải trang đầu tiên hoặc sau khi mã thông báo truy cập hết hạn.
<!DOCTYPE html>
<html>
<head></head>
<body>
<h1>GAPI with GIS async/await</h1>
<button id="showEventsBtn" onclick="showEvents();">Show Calendar</button><br><br>
<button id="revokeBtn" onclick="revokeToken();">Revoke access token</button>
<script>
const gapiLoadPromise = new Promise((resolve, reject) => {
gapiLoadOkay = resolve;
gapiLoadFail = reject;
});
const gisLoadPromise = new Promise((resolve, reject) => {
gisLoadOkay = resolve;
gisLoadFail = reject;
});
var tokenClient;
(async () => {
document.getElementById("showEventsBtn").style.visibility="hidden";
document.getElementById("revokeBtn").style.visibility="hidden";
// First, load and initialize the gapi.client
await gapiLoadPromise;
await new Promise((resolve, reject) => {
// NOTE: the 'auth2' module is no longer loaded.
gapi.load('client', {callback: resolve, onerror: reject});
});
await gapi.client.init({
// NOTE: OAuth2 'scope' and 'client_id' parameters have moved to initTokenClient().
})
.then(function() { // Load the Calendar API discovery document.
gapi.client.load('https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest');
});
// Now load the GIS client
await gisLoadPromise;
await new Promise((resolve, reject) => {
try {
tokenClient = google.accounts.oauth2.initTokenClient({
client_id: 'YOUR_CLIENT_ID',
scope: 'https://www.googleapis.com/auth/calendar.readonly',
prompt: 'consent',
callback: '', // defined at request time in await/promise scope.
});
resolve();
} catch (err) {
reject(err);
}
});
document.getElementById("showEventsBtn").style.visibility="visible";
document.getElementById("revokeBtn").style.visibility="visible";
})();
async function getToken(err) {
if (err.result.error.code == 401 || (err.result.error.code == 403) &&
(err.result.error.status == "PERMISSION_DENIED")) {
// The access token is missing, invalid, or expired, prompt for user consent to obtain one.
await new Promise((resolve, reject) => {
try {
// Settle this promise in the response callback for requestAccessToken()
tokenClient.callback = (resp) => {
if (resp.error !== undefined) {
reject(resp);
}
// GIS has automatically updated gapi.client with the newly issued access token.
console.log('gapi.client access token: ' + JSON.stringify(gapi.client.getToken()));
resolve(resp);
};
tokenClient.requestAccessToken();
} catch (err) {
console.log(err)
}
});
} else {
// Errors unrelated to authorization: server errors, exceeding quota, bad requests, and so on.
throw new Error(err);
}
}
function showEvents() {
// Try to fetch a list of Calendar events. If a valid access token is needed,
// prompt to obtain one and then retry the original request.
gapi.client.calendar.events.list({ 'calendarId': 'primary' })
.then(calendarAPIResponse => console.log(JSON.stringify(calendarAPIResponse)))
.catch(err => getToken(err)) // for authorization errors obtain an access token
.then(retry => gapi.client.calendar.events.list({ 'calendarId': 'primary' }))
.then(calendarAPIResponse => console.log(JSON.stringify(calendarAPIResponse)))
.catch(err => console.log(err)); // cancelled by user, timeout, etc.
}
function revokeToken() {
let cred = gapi.client.getToken();
if (cred !== null) {
google.accounts.oauth2.revoke(cred.access_token, () => {console.log('Revoked: ' + cred.access_token)});
gapi.client.setToken('');
}
}
</script>
<script async defer src="https://apis.google.com/js/api.js" onload="gapiLoadOkay()" onerror="gapiLoadFail(event)"></script>
<script async defer src="https://accounts.google.com/gsi/client" onload="gisLoadOkay()" onerror="gisLoadFail(event)"></script>
</body>
</html>
Lệnh gọi lại GAPI
Ví dụ này cho biết cách thêm thư viện Dịch vụ nhận dạng của Google bằng cách sử dụng mô hình mã thông báo, xoá mô-đun gapi.auth2
và gọi một API bằng Thư viện ứng dụng API của Google cho JavaScript.
Biến được dùng để thực thi thứ tự tải thư viện. Các lệnh gọi GAPI được thực hiện từ trong lệnh gọi lại sau khi mã thông báo truy cập hợp lệ được trả về.
Người dùng sẽ nhấn nút Hiển thị Lịch khi trang tải lần đầu và nhấn lại khi họ muốn làm mới thông tin Lịch.
<!DOCTYPE html>
<html>
<head>
<script async defer src="https://apis.google.com/js/api.js" onload="gapiLoad()"></script>
<script async defer src="https://accounts.google.com/gsi/client" onload="gisInit()"></script>
</head>
<body>
<h1>GAPI with GIS callbacks</h1>
<button id="showEventsBtn" onclick="showEvents();">Show Calendar</button><br><br>
<button id="revokeBtn" onclick="revokeToken();">Revoke access token</button>
<script>
let tokenClient;
let gapiInited;
let gisInited;
document.getElementById("showEventsBtn").style.visibility="hidden";
document.getElementById("revokeBtn").style.visibility="hidden";
function checkBeforeStart() {
if (gapiInited && gisInited){
// Start only when both gapi and gis are initialized.
document.getElementById("showEventsBtn").style.visibility="visible";
document.getElementById("revokeBtn").style.visibility="visible";
}
}
function gapiInit() {
gapi.client.init({
// NOTE: OAuth2 'scope' and 'client_id' parameters have moved to initTokenClient().
})
.then(function() { // Load the Calendar API discovery document.
gapi.client.load('https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest');
gapiInited = true;
checkBeforeStart();
});
}
function gapiLoad() {
gapi.load('client', gapiInit)
}
function gisInit() {
tokenClient = google.accounts.oauth2.initTokenClient({
client_id: 'YOUR_CLIENT_ID',
scope: 'https://www.googleapis.com/auth/calendar.readonly',
callback: '', // defined at request time
});
gisInited = true;
checkBeforeStart();
}
function showEvents() {
tokenClient.callback = (resp) => {
if (resp.error !== undefined) {
throw(resp);
}
// GIS has automatically updated gapi.client with the newly issued access token.
console.log('gapi.client access token: ' + JSON.stringify(gapi.client.getToken()));
gapi.client.calendar.events.list({ 'calendarId': 'primary' })
.then(calendarAPIResponse => console.log(JSON.stringify(calendarAPIResponse)))
.catch(err => console.log(err));
document.getElementById("showEventsBtn").innerText = "Refresh Calendar";
}
// Conditionally ask users to select the Google Account they'd like to use,
// and explicitly obtain their consent to fetch their Calendar.
// NOTE: To request an access token a user gesture is necessary.
if (gapi.client.getToken() === null) {
// Prompt the user to select a Google Account and asked for consent to share their data
// when establishing a new session.
tokenClient.requestAccessToken({prompt: 'consent'});
} else {
// Skip display of account chooser and consent dialog for an existing session.
tokenClient.requestAccessToken({prompt: ''});
}
}
function revokeToken() {
let cred = gapi.client.getToken();
if (cred !== null) {
google.accounts.oauth2.revoke(cred.access_token, () => {console.log('Revoked: ' + cred.access_token)});
gapi.client.setToken('');
document.getElementById("showEventsBtn").innerText = "Show Calendar";
}
}
</script>
</body>
</html>
Ví dụ về quy trình mã uỷ quyền
Trải nghiệm người dùng bật lên của thư viện Dịch vụ nhận dạng của Google có thể sử dụng lệnh chuyển hướng URL để trả về mã uỷ quyền trực tiếp đến điểm cuối mã thông báo phụ trợ hoặc trình xử lý gọi lại JavaScript chạy trong trình duyệt của người dùng để proxy phản hồi đến nền tảng của bạn. Trong cả hai trường hợp, nền tảng phụ trợ của bạn sẽ hoàn tất quy trình OAuth 2.0 để lấy mã truy cập và mã làm mới hợp lệ.
Cách cũ
Ứng dụng web phía máy chủ
Tính năng Đăng nhập bằng Google cho ứng dụng phía máy chủ chạy trên nền tảng phụ trợ bằng cách sử dụng lệnh chuyển hướng đến Google để yêu cầu người dùng đồng ý.
<!DOCTYPE html>
<html>
<head>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script src="https://apis.google.com/js/client:platform.js?onload=start" async defer></script>
<script>
function start() {
gapi.load('auth2', function() {
auth2 = gapi.auth2.init({
client_id: 'YOUR_CLIENT_ID',
api_key: 'YOUR_API_KEY',
discovery_docs: ['https://www.googleapis.com/discovery/v1/apis/translate/v2/rest'],
// Scopes to request in addition to 'profile' and 'email'
scope: 'https://www.googleapis.com/auth/cloud-translation',
});
});
}
function signInCallback(authResult) {
if (authResult['code']) {
console.log("sending AJAX request");
// Send authorization code obtained from Google to backend platform
$.ajax({
type: 'POST',
url: 'YOUR_AUTHORIZATION_CODE_ENDPOINT_URL',
// Always include an X-Requested-With header to protect against CSRF attacks.
headers: {
'X-Requested-With': 'XMLHttpRequest'
},
contentType: 'application/octet-stream; charset=utf-8',
success: function(result) {
console.log(result);
},
processData: false,
data: authResult['code']
});
} else {
console.log('error: failed to obtain authorization code')
}
}
</script>
</head>
<body>
<button id="signinButton">Sign In With Google</button>
<script>
$('#signinButton').click(function() {
// Obtain an authorization code from Google
auth2.grantOfflineAccess().then(signInCallback);
});
</script>
</body>
</html>
HTTP/REST sử dụng lệnh chuyển hướng
Sử dụng OAuth 2.0 cho ứng dụng máy chủ web để gửi mã uỷ quyền từ trình duyệt của người dùng đến nền tảng phụ trợ. Sự đồng ý của người dùng được xử lý bằng cách chuyển hướng trình duyệt của người dùng đến Google.
/\*
\* Create form to request access token from Google's OAuth 2.0 server.
\*/
function oauthSignIn() {
// Google's OAuth 2.0 endpoint for requesting an access token
var oauth2Endpoint = 'https://accounts.google.com/o/oauth2/v2/auth';
// Create <form> element to submit parameters to OAuth 2.0 endpoint.
var form = document.createElement('form');
form.setAttribute('method', 'GET'); // Send as a GET request.
form.setAttribute('action', oauth2Endpoint);
// Parameters to pass to OAuth 2.0 endpoint.
var params = {'client\_id': 'YOUR_CLIENT_ID',
'redirect\_uri': 'YOUR_AUTHORIZATION_CODE_ENDPOINT_URL',
'response\_type': 'token',
'scope': 'https://www.googleapis.com/auth/drive.metadata.readonly',
'include\_granted\_scopes': 'true',
'state': 'pass-through value'};
// Add form parameters as hidden input values.
for (var p in params) {
var input = document.createElement('input');
input.setAttribute('type', 'hidden');
input.setAttribute('name', p);
input.setAttribute('value', params[p]);
form.appendChild(input);
}
// Add form to page and submit it to open the OAuth 2.0 endpoint.
document.body.appendChild(form);
form.submit();
}
Cách mới
Trải nghiệm người dùng của cửa sổ bật lên GIS
Ví dụ này chỉ hiển thị thư viện JavaScript Dịch vụ nhận dạng của Google sử dụng mô hình mã uỷ quyền, một hộp thoại bật lên để người dùng đồng ý và trình xử lý gọi lại để nhận mã uỷ quyền từ Google. Bản tóm tắt này minh hoạ số bước tối thiểu cần thiết để định cấu hình ứng dụng, lấy sự đồng ý và gửi mã uỷ quyền đến nền tảng phụ trợ của bạn.
<!DOCTYPE html>
<html>
<head>
<script src="https://accounts.google.com/gsi/client" onload="initClient()" async defer></script>
</head>
<body>
<script>
var client;
function initClient() {
client = google.accounts.oauth2.initCodeClient({
client_id: 'YOUR_CLIENT_ID',
scope: 'https://www.googleapis.com/auth/calendar.readonly',
ux_mode: 'popup',
callback: (response) => {
var code_receiver_uri = 'YOUR_AUTHORIZATION_CODE_ENDPOINT_URI',
// Send auth code to your backend platform
const xhr = new XMLHttpRequest();
xhr.open('POST', code_receiver_uri, true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
xhr.onload = function() {
console.log('Signed in as: ' + xhr.responseText);
};
xhr.send('code=' + response.code);
// After receipt, the code is exchanged for an access token and
// refresh token, and the platform then updates this web app
// running in user's browser with the requested calendar info.
},
});
}
function getAuthCode() {
// Request authorization code and obtain user consent
client.requestCode();
}
</script>
<button onclick="getAuthCode();">Load Your Calendar</button>
</body>
</html>
Trải nghiệm người dùng của tính năng Chuyển hướng GIS
Mô hình mã uỷ quyền hỗ trợ các chế độ trải nghiệm người dùng bật lên và chuyển hướng để gửi mã uỷ quyền cho mỗi người dùng đến điểm cuối do nền tảng của bạn lưu trữ. Chế độ trải nghiệm người dùng chuyển hướng được hiển thị tại đây:
<!DOCTYPE html>
<html>
<head>
<script src="https://accounts.google.com/gsi/client" onload="initClient()" async defer></script>
</head>
<body>
<script>
var client;
function initClient() {
client = google.accounts.oauth2.initCodeClient({
client_id: 'YOUR_CLIENT_ID',
scope: 'https://www.googleapis.com/auth/calendar.readonly \
https://www.googleapis.com/auth/photoslibrary.readonly',
ux_mode: 'redirect',
redirect_uri: 'YOUR_AUTHORIZATION_CODE_ENDPOINT_URI'
});
}
// Request an access token
function getAuthCode() {
// Request authorization code and obtain user consent
client.requestCode();
}
</script>
<button onclick="getAuthCode();">Load Your Calendar</button>
</body>
</html>
Thư viện JavaScript
Dịch vụ nhận dạng của Google là một thư viện JavaScript duy nhất dùng để xác thực và uỷ quyền người dùng, giúp hợp nhất và thay thế các tính năng và chức năng có trong nhiều thư viện và mô-đun khác nhau:
Các hành động cần thực hiện khi di chuyển sang Dịch vụ nhận dạng:
Thư viện JS hiện có | Thư viện JS mới | Ghi chú |
---|---|---|
apis.google.com/js/api.js |
accounts.google.com/gsi/client |
Thêm thư viện mới và làm theo luồng ngầm ẩn. |
apis.google.com/js/client.js |
accounts.google.com/gsi/client |
Thêm thư viện mới và luồng mã uỷ quyền. |
Tài liệu tham khảo nhanh về thư viện
So sánh đối tượng và phương thức giữa thư viện cũ ứng dụng JavaScript đăng nhập bằng Google và thư viện mới Dịch vụ nhận dạng của Google, cũng như Ghi chú với thông tin bổ sung và hành động cần thực hiện trong quá trình di chuyển.
Cũ | Mới | Ghi chú |
---|---|---|
Đối tượng GoogleAuth và các phương thức liên quan: | ||
GoogleAuth.attachClickHandler() | Xóa | |
GoogleAuth.currentUser.get() | Xóa | |
GoogleAuth.currentUser.listen() | Xóa | |
GoogleAuth.disconnect() | google.accounts.oauth2.revoke | Thay thế cái cũ bằng cái mới. Việc thu hồi cũng có thể xảy ra trên trang https://myaccount.google.com/permissions |
GoogleAuth.grantOfflineAccess() | Xoá, làm theo quy trình sử dụng mã uỷ quyền. | |
GoogleAuth.isSignedIn.get() | Xóa | |
GoogleAuth.isSignedIn.listen() | Xóa | |
GoogleAuth.signIn() | Xóa | |
GoogleAuth.signOut() | Xóa | |
GoogleAuth.then() | Xóa | |
Đối tượng GoogleUser và các phương thức liên quan: | ||
GoogleUser.disconnect() | google.accounts.id.revoke | Thay thế cũ bằng mới. Việc thu hồi cũng có thể xảy ra trên trang https://myaccount.google.com/permissions |
GoogleUser.getAuthResponse() | requestCode() or requestAccessToken() | Thay thế cũ bằng mới |
GoogleUser.getBasicProfile() | Xóa. Thay vào đó, hãy sử dụng Mã thông báo nhận dạng, hãy xem bài viết Chuyển từ tính năng Đăng nhập bằng Google. | |
GoogleUser.getGrantedScopes() | hasGrantedAnyScope() | Thay thế cũ bằng mới |
GoogleUser.getHostedDomain() | Xóa | |
GoogleUser.getId() | Xóa | |
GoogleUser.grantOfflineAccess() | Xoá, làm theo quy trình sử dụng mã uỷ quyền. | |
GoogleUser.grant() | Xóa | |
GoogleUser.hasGrantedScopes() | hasGrantedAnyScope() | Thay thế cũ bằng mới |
GoogleUser.isSignedIn() | Xóa | |
GoogleUser.reloadAuthResponse() | requestAccessToken() | Xoá mã cũ, gọi mã mới để thay thế mã truy cập đã hết hạn hoặc bị thu hồi. |
Đối tượng gapi.auth2 và các phương thức liên quan: | ||
Đối tượng gapi.auth2.AuthorizeConfig | TokenClientConfig hoặc CodeClientConfig | Thay thế cũ bằng mới |
Đối tượng gapi.auth2.AuthorizeResponse | Xóa | |
Đối tượng gapi.auth2.AuthResponse | Xóa | |
gapi.auth2.authorize() | requestCode() or requestAccessToken() | Thay thế cũ bằng mới |
gapi.auth2.ClientConfig() | TokenClientConfig hoặc CodeClientConfig | Thay thế cũ bằng mới |
gapi.auth2.getAuthInstance() | Xóa | |
gapi.auth2.init() | initTokenClient() or initCodeClient() | Thay thế cũ bằng mới |
Đối tượng gapi.auth2.OfflineAccessOptions | Xóa | |
Đối tượng gapi.auth2.SignInOptions | Xóa | |
Đối tượng gapi.signin2 và các phương thức liên quan: | ||
gapi.signin2.render() | Xóa. Việc tải HTML DOM của phần tử g_id_signin hoặc lệnh gọi JS đến google.accounts.id.renderButton sẽ kích hoạt người dùng đăng nhập vào Tài khoản Google. |
Thông tin xác thực mẫu
Thông tin xác thực hiện có
Thư viện nền tảng Đăng nhập bằng Google, Thư viện ứng dụng API Google cho JavaScript hoặc lệnh gọi trực tiếp đến các điểm cuối của Google Auth 2.0 sẽ trả về cả mã thông báo truy cập OAuth 2.0 và mã thông báo nhận dạng OpenID Connect trong một phản hồi.
Ví dụ về phản hồi chứa cả access_token
và id_token
:
{
"token_type": "Bearer",
"access_token": "ya29.A0ARrdaM-SmArZaCIh68qXsZSzyeU-8mxhQERHrP2EXtxpUuZ-3oW8IW7a6D2J6lRnZrRj8S6-ZcIl5XVEqnqxq5fuMeDDH_6MZgQ5dgP7moY-yTiKR5kdPm-LkuPM-mOtUsylWPd1wpRmvw_AGOZ1UUCa6UD5Hg",
"scope": "https://www.googleapis.com/auth/calendar.readonly",
"login_hint": "AJDLj6I2d1RH77cgpe__DdEree1zxHjZJr4Q7yOisoumTZUmo5W2ZmVFHyAomUYzLkrluG-hqt4RnNxrPhArd5y6p8kzO0t8xIfMAe6yhztt6v2E-_Bb4Ec3GLFKikHSXNh5bI-gPrsI",
"expires_in": 3599,
"id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjkzNDFhYmM0MDkyYjZmYzAzOGU0MDNjOTEwMjJkZDNlNDQ1MzliNTYiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJhY2NvdW50cy5nb29nbGUuY29tIiwiYXpwIjoiNTM4MzQ0NjUzMjU1LTc1OGM1aDVpc2M0NXZnazI3ZDhoOGRlYWJvdnBnNnRvLmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tIiwiYXVkIjoiNTM4MzQ0NjUzMjU1LTc1OGM1aDVpc2M0NXZnazI3ZDhoOGRlYWJvdnBnNnRvLmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tIiwic3ViIjoiMTE3NzI2NDMxNjUxOTQzNjk4NjAwIiwiaGQiOiJnb29nbGUuY29tIiwiZW1haWwiOiJkYWJyaWFuQGdvb2dsZS5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiYXRfaGFzaCI6IkJBSW55TjN2MS1ZejNLQnJUMVo0ckEiLCJuYW1lIjoiQnJpYW4gRGF1Z2hlcnR5IiwicGljdHVyZSI6Imh0dHBzOi8vbGgzLmdvb2dsZXVzZXJjb250ZW50LmNvbS9hLS9BT2gxNEdnenAyTXNGRGZvbVdMX3VDemRYUWNzeVM3ZGtxTE5ybk90S0QzVXNRPXM5Ni1jIiwiZ2l2ZW5fbmFtZSI6IkJyaWFuIiwiZmFtaWx5X25hbWUiOiJEYXVnaGVydHkiLCJsb2NhbGUiOiJlbiIsImlhdCI6MTYzODk5MTYzOCwiZXhwIjoxNjM4OTk1MjM4LCJqdGkiOiI5YmRkZjE1YWFiNzE2ZDhjYmJmNDYwMmM1YWM3YzViN2VhMDQ5OTA5In0.K3EA-3Adw5HA7O8nJVCsX1HmGWxWzYk3P7ViVBb4H4BoT2-HIgxKlx1mi6jSxIUJGEekjw9MC-nL1B9Asgv1vXTMgoGaNna0UoEHYitySI23E5jaMkExkTSLtxI-ih2tJrA2ggfA9Ekj-JFiMc6MuJnwcfBTlsYWRcZOYVw3QpdTZ_VYfhUu-yERAElZCjaAyEXLtVQegRe-ymScra3r9S92TA33ylMb3WDTlfmDpWL0CDdDzby2asXYpl6GQ7SdSj64s49Yw6mdGELZn5WoJqG7Zr2KwIGXJuSxEo-wGbzxNK-mKAiABcFpYP4KHPEUgYyz3n9Vqn2Tfrgp-g65BQ",
"session_state": {
"extraQueryParams": {
"authuser": "0"
}
},
"first_issued_at": 1638991637982,
"expires_at": 1638995236982,
"idpId": "google"
}
Thông tin xác thực Dịch vụ nhận dạng của Google
Thư viện Dịch vụ nhận dạng của Google trả về:
mã thông báo truy cập khi được dùng để uỷ quyền:
{ "access_token": "ya29.A0ARrdaM_LWSO-uckLj7IJVNSfnUityT0Xj-UCCrGxFQdxmLiWuAosnAKMVQ2Z0LLqeZdeJii3TgULp6hR_PJxnInBOl8UoUwWoqsrGQ7-swxgy97E8_hnzfhrOWyQBmH6zs0_sUCzwzhEr_FAVqf92sZZHphr0g", "token_type": "Bearer", "expires_in": 3599, "scope": "https://www.googleapis.com/auth/calendar.readonly" }
hoặc mã thông báo ID khi được sử dụng để xác thực:
{ "clientId": "538344653255-758c5h5isc45vgk27d8h8deabovpg6to.apps.googleusercontent.com", "credential": "eyJhbGciOiJSUzI1NiIsImtpZCI6ImMxODkyZWI0OWQ3ZWY5YWRmOGIyZTE0YzA1Y2EwZDAzMjcxNGEyMzciLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJuYmYiOjE2MzkxNTcyNjQsImF1ZCI6IjUzODM0NDY1MzI1NS03NThjNWg1aXNjNDV2Z2syN2Q4aDhkZWFib3ZwZzZ0by5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbSIsInN1YiI6IjExNzcyNjQzMTY1MTk0MzY5ODYwMCIsIm5vbmNlIjoiZm9vYmFyIiwiaGQiOiJnb29nbGUuY29tIiwiZW1haWwiOiJkYWJyaWFuQGdvb2dsZS5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiYXpwIjoiNTM4MzQ0NjUzMjU1LTc1OGM1aDVpc2M0NXZnazI3ZDhoOGRlYWJvdnBnNnRvLmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tIiwibmFtZSI6IkJyaWFuIERhdWdoZXJ0eSIsInBpY3R1cmUiOiJodHRwczovL2xoMy5nb29nbGV1c2VyY29udGVudC5jb20vYS0vQU9oMTRHZ3pwMk1zRkRmb21XTF91Q3pkWFFjc3lTN2RrcUxOcm5PdEtEM1VzUT1zOTYtYyIsImdpdmVuX25hbWUiOiJCcmlhbiIsImZhbWlseV9uYW1lIjoiRGF1Z2hlcnR5IiwiaWF0IjoxNjM5MTU3NTY0LCJleHAiOjE2MzkxNjExNjQsImp0aSI6IjRiOTVkYjAyZjU4NDczMmUxZGJkOTY2NWJiMWYzY2VhYzgyMmI0NjUifQ.Cr-AgMsLFeLurnqyGpw0hSomjOCU4S3cU669Hyi4VsbqnAV11zc_z73o6ahe9Nqc26kPVCNRGSqYrDZPfRyTnV6g1PIgc4Zvl-JBuy6O9HhClAK1HhMwh1FpgeYwXqrng1tifmuotuLQnZAiQJM73Gl-J_6s86Buo_1AIx5YAKCucYDUYYdXBIHLxrbALsA5W6pZCqqkMbqpTWteix-G5Q5T8LNsfqIu_uMBUGceqZWFJALhS9ieaDqoxhIqpx_89QAr1YlGu_UO6R6FYl0wDT-nzjyeF5tonSs3FHN0iNIiR3AMOHZu7KUwZaUdHg4eYkU-sQ01QNY_11keHROCRQ", "select_by": "user" }
Phản hồi mã thông báo không hợp lệ
Ví dụ về phản hồi của Google khi cố gắng thực hiện một yêu cầu API bằng mã truy cập đã hết hạn, bị thu hồi hoặc không hợp lệ:
Tiêu đề phản hồi HTTP
www-authenticate: Bearer realm="https://accounts.google.com/", error="invalid_token"
Nội dung phản hồi
{
"error": {
"code": 401,
"message": "Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.",
"errors": [
{
"message": "Invalid Credentials",
"domain": "global",
"reason": "authError",
"location": "Authorization",
"locationType": "header"
}
],
"status": "UNAUTHENTICATED"
}
}