Sử dụng OAuth 2.0 cho ứng dụng web JavaScript

Tài liệu này giải thích cách triển khai quy trình uỷ quyền OAuth 2.0 để truy cập vào API Dữ liệu của YouTube từ một ứng dụng web JavaScript. OAuth 2.0 cho phép người dùng chia sẻ dữ liệu cụ thể với một ứng dụng trong khi vẫn bảo mật tên người dùng, mật khẩu và các thông tin khác. Ví dụ: một ứng dụng có thể sử dụng OAuth 2.0 để xin phép tải video lên kênh YouTube của người dùng.

Quy trình OAuth 2.0 này được gọi là quy trình cấp quyền ngầm ẩn. API này được thiết kế cho các ứng dụng chỉ truy cập vào API khi người dùng đang ở trong ứng dụng. Những ứng dụng này không thể lưu trữ thông tin mật.

Trong quy trình này, ứng dụng của bạn sẽ mở một URL của Google sử dụng các tham số truy vấn để xác định ứng dụng của bạn và loại quyền truy cập API mà ứng dụng yêu cầu. Bạn có thể mở URL trong cửa sổ trình duyệt hiện tại hoặc cửa sổ bật lên. Người dùng có thể xác thực bằng Google và cấp các quyền được yêu cầu. Sau đó, Google sẽ chuyển hướng người dùng trở lại ứng dụng của bạn. Lệnh chuyển hướng này bao gồm một mã thông báo truy cập mà ứng dụng của bạn xác minh rồi sử dụng để tạo các yêu cầu API.

Thư viện ứng dụng API của Google và Dịch vụ nhận dạng của Google

Nếu sử dụng thư viện ứng dụng API của Google cho JavaScript để thực hiện các lệnh gọi được uỷ quyền đến Google, bạn nên sử dụng thư viện JavaScript Dịch vụ nhận dạng của Google để xử lý quy trình OAuth 2.0. Vui lòng xem mô hình mã thông báo của Dịch vụ nhận dạng của Google. Mô hình này dựa trên quy trình cấp quyền ngầm ẩn của OAuth 2.0.

Điều kiện tiên quyết

Bật API cho dự án

Mọi ứng dụng gọi API của Google đều cần bật các API đó trong API Console.

Cách bật API cho dự án:

  1. Open the API Library trong Google API Console.
  2. If prompted, select a project, or create a new one.
  3. Sử dụng trang Thư viện để tìm và bật API Dữ liệu YouTube. Tìm mọi API khác mà ứng dụng của bạn sẽ sử dụng và bật các API đó.

Tạo thông tin xác thực cho phép

Mọi ứng dụng dùng OAuth 2.0 để truy cập API Google đều phải có thông tin xác thực uỷ quyền giúp xác định ứng dụng đó cho máy chủ OAuth 2.0 của Google. Các bước sau đây sẽ giải thích cách tạo thông tin xác thực cho dự án của bạn. Sau đó, các ứng dụng của bạn có thể sử dụng thông tin xác thực để truy cập vào các API mà bạn đã bật cho dự án đó.

  1. Go to the Credentials page.
  2. Nhấp vào Tạo thông tin xác thực > Mã ứng dụng khách OAuth.
  3. Chọn loại ứng dụng Ứng dụng web.
  4. Hoàn thành biểu mẫu. Các ứng dụng sử dụng JavaScript để tạo yêu cầu API Google được uỷ quyền phải chỉ định nguồn gốc JavaScript được uỷ quyền. Nguồn gốc xác định các miền mà ứng dụng của bạn có thể gửi yêu cầu đến máy chủ OAuth 2.0. Các nguồn gốc này phải tuân thủ các quy tắc xác thực của Google.

Xác định phạm vi truy cập

Phạm vi cho phép ứng dụng của bạn chỉ yêu cầu quyền truy cập vào các tài nguyên mà ứng dụng cần, đồng thời cho phép người dùng kiểm soát mức độ truy cập mà họ cấp cho ứng dụng. Do đó, có thể có mối quan hệ nghịch đảo giữa số lượng phạm vi được yêu cầu và khả năng nhận được sự đồng ý của người dùng.

Trước khi bắt đầu triển khai quy trình uỷ quyền OAuth 2.0, bạn nên xác định các phạm vi mà ứng dụng của bạn cần có quyền truy cập.

YouTube Data API phiên bản 3 sử dụng các phạm vi sau:

Kính ngắm
https://www.googleapis.com/auth/youtubeQuản lý tài khoản YouTube của bạn
https://www.googleapis.com/auth/youtube.channel-memberships.creatorXem danh sách các hội viên đang hoạt động trên kênh của bạn, cấp độ hiện tại của họ và thời điểm họ trở thành hội viên
https://www.googleapis.com/auth/youtube.force-sslXem, chỉnh sửa và xóa vĩnh viễn các video, mức xếp hạng, ý kiến nhận xét và phụ đề của bạn trên YouTube
https://www.googleapis.com/auth/youtube.readonlyXem tài khoản YouTube của bạn
https://www.googleapis.com/auth/youtube.uploadQuản lý video trên YouTube của bạn
https://www.googleapis.com/auth/youtubepartnerXem và quản lý tài sản cũng như nội dung được kết hợp của bạn trên YouTube
https://www.googleapis.com/auth/youtubepartner-channel-auditXem thông tin riêng tư trên kênh YouTube của bạn có liên quan trong quá trình kiểm tra với đối tác YouTube

Tài liệu Phạm vi API OAuth 2.0 chứa danh sách đầy đủ các phạm vi mà bạn có thể sử dụng để truy cập vào các API của Google.

Lấy mã truy cập OAuth 2.0

Các bước sau đây cho thấy cách ứng dụng của bạn tương tác với máy chủ OAuth 2.0 của Google để lấy sự đồng ý của người dùng nhằm thay mặt người dùng thực hiện yêu cầu API. Ứng dụng của bạn phải nhận được sự đồng ý đó thì mới có thể thực thi yêu cầu API của Google mà cần có sự cho phép của người dùng.

Bước 1: Chuyển hướng đến máy chủ OAuth 2.0 của Google

Để yêu cầu quyền truy cập vào dữ liệu của người dùng, hãy chuyển hướng người dùng đến máy chủ OAuth 2.0 của Google.

Điểm cuối OAuth 2.0

Tạo URL để yêu cầu quyền truy cập từ điểm cuối OAuth 2.0 của Google tại https://accounts.google.com/o/oauth2/v2/auth. Bạn có thể truy cập điểm cuối này qua HTTPS; các kết nối HTTP thuần tuý sẽ bị từ chối.

Máy chủ uỷ quyền của Google hỗ trợ các tham số chuỗi truy vấn sau đây cho các ứng dụng máy chủ web:

Thông số
client_id Bắt buộc

Mã ứng dụng khách cho ứng dụng của bạn. Bạn có thể tìm thấy giá trị này trong API Console Credentials page.

redirect_uri Bắt buộc

Xác định nơi máy chủ API chuyển hướng người dùng sau khi người dùng hoàn tất quy trình uỷ quyền. Giá trị này phải khớp chính xác với một trong các URI chuyển hướng được uỷ quyền cho ứng dụng OAuth 2.0 mà bạn đã định cấu hình trong API Console Credentials pagecủa ứng dụng. Nếu giá trị này không khớp với URI chuyển hướng được uỷ quyền cho client_id đã cung cấp, bạn sẽ gặp lỗi redirect_uri_mismatch.

Xin lưu ý rằng giao thức, trường hợp và dấu gạch chéo cuối cùng của http hoặc https ('/') phải khớp nhau.

response_type Bắt buộc

Các ứng dụng JavaScript cần đặt giá trị của tham số thành token. Giá trị này hướng dẫn Máy chủ uỷ quyền của Google trả về mã thông báo truy cập dưới dạng một cặp name=value trong giá trị nhận dạng mảnh của URI (#) mà người dùng được chuyển hướng đến sau khi hoàn tất quy trình uỷ quyền.

scope Bắt buộc

Một danh sách các phạm vi được phân tách bằng dấu cách xác định những tài nguyên mà ứng dụng của bạn có thể truy cập thay mặt cho người dùng. Các giá trị này sẽ cung cấp thông tin cho màn hình yêu cầu đồng ý mà Google hiển thị cho người dùng.

Phạm vi cho phép ứng dụng của bạn chỉ yêu cầu quyền truy cập vào các tài nguyên mà ứng dụng cần, đồng thời cho phép người dùng kiểm soát mức độ truy cập mà họ cấp cho ứng dụng. Do đó, có mối quan hệ nghịch đảo giữa số lượng phạm vi được yêu cầu và khả năng nhận được sự đồng ý của người dùng.

YouTube Data API phiên bản 3 sử dụng các phạm vi sau:

Kính ngắm
https://www.googleapis.com/auth/youtubeQuản lý tài khoản YouTube của bạn
https://www.googleapis.com/auth/youtube.channel-memberships.creatorXem danh sách các hội viên đang hoạt động trên kênh của bạn, cấp độ hiện tại của họ và thời điểm họ trở thành hội viên
https://www.googleapis.com/auth/youtube.force-sslXem, chỉnh sửa và xóa vĩnh viễn các video, mức xếp hạng, ý kiến nhận xét và phụ đề của bạn trên YouTube
https://www.googleapis.com/auth/youtube.readonlyXem tài khoản YouTube của bạn
https://www.googleapis.com/auth/youtube.uploadQuản lý video trên YouTube của bạn
https://www.googleapis.com/auth/youtubepartnerXem và quản lý tài sản cũng như nội dung được kết hợp của bạn trên YouTube
https://www.googleapis.com/auth/youtubepartner-channel-auditXem thông tin riêng tư trên kênh YouTube của bạn có liên quan trong quá trình kiểm tra với đối tác YouTube

Tài liệu Phạm vi API OAuth 2.0 cung cấp danh sách đầy đủ các phạm vi mà bạn có thể sử dụng để truy cập vào các API của Google.

Bạn nên yêu cầu ứng dụng của mình truy cập vào các phạm vi uỷ quyền theo ngữ cảnh bất cứ khi nào có thể. Bằng cách yêu cầu quyền truy cập vào dữ liệu người dùng theo bối cảnh, thông qua tính năng uỷ quyền gia tăng, bạn giúp người dùng dễ dàng hiểu được lý do ứng dụng của bạn cần quyền truy cập mà ứng dụng đang yêu cầu.

state Recommended (Nên dùng)

Chỉ định mọi giá trị chuỗi mà ứng dụng của bạn sử dụng để duy trì trạng thái giữa yêu cầu uỷ quyền và phản hồi của máy chủ uỷ quyền. Máy chủ sẽ trả về giá trị chính xác mà bạn gửi dưới dạng cặp name=value trong giá trị nhận dạng phân đoạn URL (#) của redirect_uri sau khi người dùng đồng ý hoặc từ chối yêu cầu truy cập của ứng dụng.

Bạn có thể sử dụng tham số này cho một số mục đích, chẳng hạn như hướng người dùng đến đúng tài nguyên trong ứng dụng của bạn, gửi số chỉ dùng một lần và giảm thiểu việc giả mạo yêu cầu trên nhiều trang web. Vì redirect_uri của bạn có thể bị đoán, nên việc sử dụng giá trị state có thể giúp bạn tăng độ tin cậy rằng một kết nối đến là kết quả của một yêu cầu xác thực. Nếu tạo một chuỗi ngẫu nhiên hoặc mã hoá hàm băm của một cookie hoặc một giá trị khác ghi lại trạng thái của ứng dụng, bạn có thể xác thực phản hồi để đảm bảo rằng yêu cầu và phản hồi bắt nguồn từ cùng một trình duyệt, giúp bảo vệ khỏi các cuộc tấn công như lừa đảo yêu cầu trên nhiều trang web. Hãy xem tài liệu về OpenID Connect để biết ví dụ về cách tạo và xác nhận mã thông báo state.

include_granted_scopes Không bắt buộc

Cho phép ứng dụng sử dụng tính năng uỷ quyền gia tăng để yêu cầu quyền truy cập vào các phạm vi bổ sung trong ngữ cảnh. Nếu bạn đặt giá trị của thông số này thành true và yêu cầu uỷ quyền được cấp, thì mã truy cập mới cũng sẽ bao gồm mọi phạm vi mà trước đây người dùng đã cấp quyền truy cập cho ứng dụng. Hãy xem phần uỷ quyền gia tăng để biết ví dụ.

login_hint Không bắt buộc

Nếu biết người dùng nào đang cố gắng xác thực, thì ứng dụng của bạn có thể sử dụng thông số này để cung cấp gợi ý cho Máy chủ xác thực của Google. Máy chủ sử dụng gợi ý để đơn giản hoá quy trình đăng nhập bằng cách điền sẵn trường email trong biểu mẫu đăng nhập hoặc bằng cách chọn phiên đăng nhập nhiều người dùng thích hợp.

Đặt giá trị tham số thành địa chỉ email hoặc giá trị nhận dạng sub, tương đương với mã nhận dạng Google của người dùng.

prompt Không bắt buộc

Danh sách lời nhắc phân tách bằng dấu cách, phân biệt chữ hoa chữ thường để hiển thị cho người dùng. Nếu bạn không chỉ định tham số này, người dùng sẽ chỉ được nhắc trong lần đầu tiên dự án của bạn yêu cầu quyền truy cập. Hãy xem phần Nhắc người dùng đồng ý lại để biết thêm thông tin.

Các giá trị có thể là:

none Không hiển thị bất kỳ màn hình xác thực hoặc màn hình đồng ý nào. Không được chỉ định bằng các giá trị khác.
consent Nhắc người dùng đồng ý.
select_account Nhắc người dùng chọn một tài khoản.

Mẫu chuyển hướng đến máy chủ uỷ quyền của Google

URL mẫu bên dưới yêu cầu quyền truy cập ngoại tuyến (access_type=offline) vào một phạm vi cho phép truy cập để xem tài khoản YouTube của người dùng. Phương thức này sử dụng lệnh uỷ quyền gia tăng để đảm bảo rằng mã truy cập mới bao gồm mọi phạm vi mà trước đây người dùng đã cấp quyền truy cập cho ứng dụng. URL cũng đặt giá trị cho các tham số redirect_uri, response_typeclient_id bắt buộc cũng như cho tham số state. URL chứa dấu ngắt dòng và dấu cách để dễ đọc.

https://accounts.google.com/o/oauth2/v2/auth?
 scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fyoutube.readonly&
 include_granted_scopes=true&
 state=state_parameter_passthrough_value&
 redirect_uri=http%3A%2F%2Flocalhost%2Foauth2callback&
 response_type=token&
 client_id=client_id

Sau khi bạn tạo URL yêu cầu, hãy chuyển hướng người dùng đến URL đó.

Mã mẫu JavaScript

Đoạn mã JavaScript sau đây cho biết cách bắt đầu quy trình uỷ quyền trong JavaScript mà không cần sử dụng Thư viện ứng dụng API của Google cho JavaScript. Vì điểm cuối OAuth 2.0 này không hỗ trợ tính năng Chia sẻ tài nguyên trên nhiều nguồn gốc (CORS), nên đoạn mã này sẽ tạo một biểu mẫu mở yêu cầu đến điểm cuối đó.

/*
 * 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_REDIRECT_URI',
                'response_type': 'token',
                'scope': 'https://www.googleapis.com/auth/youtube.force-ssl',
                '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();
}

Bước 2: Google nhắc người dùng đồng ý

Trong bước này, người dùng sẽ quyết định có cấp cho ứng dụng của bạn quyền truy cập đã yêu cầu hay không. Ở giai đoạn này, Google sẽ hiển thị một cửa sổ yêu cầu đồng ý cho biết tên ứng dụng và các dịch vụ API của Google mà ứng dụng đang yêu cầu quyền truy cập bằng thông tin xác thực uỷ quyền của người dùng, cũng như thông tin tóm tắt về phạm vi truy cập sẽ được cấp. Sau đó, người dùng có thể đồng ý cấp quyền truy cập vào một hoặc nhiều phạm vi mà ứng dụng của bạn yêu cầu hoặc từ chối yêu cầu đó.

Ứng dụng của bạn không cần làm gì ở giai đoạn này vì ứng dụng sẽ chờ phản hồi từ máy chủ OAuth 2.0 của Google cho biết liệu có cấp quyền truy cập nào hay không. Phản hồi đó được giải thích trong bước sau.

Lỗi

Các yêu cầu đến điểm cuối uỷ quyền OAuth 2.0 của Google có thể hiển thị thông báo lỗi mà người dùng nhìn thấy thay vì luồng xác thực và uỷ quyền dự kiến. Dưới đây là danh sách các mã lỗi thường gặp và giải pháp đề xuất.

admin_policy_enforced

Tài khoản Google không thể uỷ quyền cho một hoặc nhiều phạm vi được yêu cầu do chính sách của quản trị viên Google Workspace. Hãy xem bài viết trợ giúp dành cho Quản trị viên Google Workspace Kiểm soát những ứng dụng nội bộ và ứng dụng bên thứ ba nào truy cập vào dữ liệu trong Google Workspace để biết thêm thông tin về cách quản trị viên có thể hạn chế quyền truy cập vào tất cả phạm vi hoặc các phạm vi nhạy cảm và bị hạn chế cho đến khi bạn cấp quyền truy cập rõ ràng cho mã ứng dụng khách OAuth.

disallowed_useragent

Điểm cuối uỷ quyền hiển thị trong một tác nhân người dùng được nhúng theo Chính sách của OAuth 2.0 mà Google không cho phép.

Android

Nhà phát triển Android có thể gặp phải thông báo lỗi này khi mở các yêu cầu uỷ quyền trong android.webkit.WebView. Thay vào đó, nhà phát triển nên sử dụng các thư viện Android, chẳng hạn như Đăng nhập bằng Google cho Android hoặc AppAuth cho Android của OpenID Foundation.

Nhà phát triển web có thể gặp lỗi này khi một ứng dụng Android mở một đường liên kết web chung trong một tác nhân người dùng được nhúng và người dùng chuyển đến điểm cuối uỷ quyền OAuth 2.0 của Google từ trang web của bạn. Nhà phát triển nên cho phép các đường liên kết chung mở trong trình xử lý đường liên kết mặc định của hệ điều hành, bao gồm cả trình xử lý Đường liên kết trong ứng dụng Android hoặc ứng dụng trình duyệt mặc định. Thư viện Thẻ tuỳ chỉnh Android cũng là một lựa chọn được hỗ trợ.

iOS

Nhà phát triển iOS và macOS có thể gặp lỗi này khi mở các yêu cầu uỷ quyền trong WKWebView. Thay vào đó, nhà phát triển nên sử dụng các thư viện iOS như Google Sign-In cho iOS hoặc AppAuth cho iOS của OpenID Foundation.

Nhà phát triển web có thể gặp lỗi này khi một ứng dụng iOS hoặc macOS mở một đường liên kết web chung trong một tác nhân người dùng được nhúng và người dùng chuyển đến điểm cuối uỷ quyền OAuth 2.0 của Google từ trang web của bạn. Nhà phát triển nên cho phép các đường liên kết chung mở trong trình xử lý đường liên kết mặc định của hệ điều hành, bao gồm cả trình xử lý Đường liên kết chung hoặc ứng dụng trình duyệt mặc định. Thư viện SFSafariViewController cũng là một tuỳ chọn được hỗ trợ.

org_internal

Mã ứng dụng OAuth trong yêu cầu này thuộc một dự án giới hạn quyền truy cập vào Tài khoản Google trong một Tổ chức Google Cloud cụ thể. Để biết thêm thông tin về tuỳ chọn cấu hình này, hãy xem phần Loại người dùng trong bài viết trợ giúp về cách thiết lập màn hình xin phép bằng OAuth.

invalid_client

Nguồn gốc của yêu cầu không được uỷ quyền cho ứng dụng này. Xem origin_mismatch.

invalid_grant

Khi sử dụng tính năng uỷ quyền gia tăng, mã thông báo có thể đã hết hạn hoặc không hợp lệ. Xác thực lại người dùng và yêu cầu người dùng đồng ý để lấy mã thông báo mới. Nếu bạn vẫn gặp lỗi này, hãy đảm bảo rằng ứng dụng của bạn đã được định cấu hình chính xác và bạn đang sử dụng đúng mã thông báo và tham số trong yêu cầu. Nếu không, tài khoản người dùng có thể đã bị xoá hoặc bị vô hiệu hoá.

origin_mismatch

Lược đồ, miền và/hoặc cổng của JavaScript khởi tạo yêu cầu uỷ quyền có thể không khớp với URI gốc JavaScript được uỷ quyền đã đăng ký cho mã ứng dụng khách OAuth. Xem lại các nguồn gốc JavaScript được cho phép trong Google API Console Credentials page.

redirect_uri_mismatch

redirect_uri được truyền trong yêu cầu uỷ quyền không khớp với URI chuyển hướng được uỷ quyền cho mã ứng dụng OAuth. Xem xét các URI chuyển hướng được uỷ quyền trong Google API Console Credentials page.

Giao thức, miền và/hoặc cổng của JavaScript tạo ra yêu cầu uỷ quyền có thể không khớp với URI nguồn gốc JavaScript được uỷ quyền đã đăng ký cho mã ứng dụng khách OAuth. Xem lại nguồn gốc JavaScript được uỷ quyền trong Google API Console Credentials page.

Tham số redirect_uri có thể tham chiếu đến luồng OAuth ngoài băng thông (OOB) đã ngừng hoạt động và không còn được hỗ trợ nữa. Hãy tham khảo hướng dẫn di chuyển để cập nhật tính năng tích hợp.

invalid_request

Yêu cầu mà bạn đưa ra có vấn đề. Điều này có thể là do một số lý do sau:

  • Yêu cầu không được định dạng đúng cách
  • Yêu cầu bị thiếu các tham số bắt buộc
  • Yêu cầu sử dụng một phương thức uỷ quyền mà Google không hỗ trợ. Xác minh việc tích hợp OAuth của bạn sử dụng phương thức tích hợp được đề xuất

Bước 3: Xử lý phản hồi của máy chủ OAuth 2.0

Điểm cuối OAuth 2.0

Máy chủ OAuth 2.0 sẽ gửi phản hồi đến redirect_uri được chỉ định trong yêu cầu mã truy cập của bạn.

Nếu người dùng phê duyệt yêu cầu, thì phản hồi sẽ chứa mã truy cập. Nếu người dùng không phê duyệt yêu cầu, thì phản hồi sẽ chứa thông báo lỗi. Mã thông báo truy cập hoặc thông báo lỗi sẽ được trả về trên mảnh băm của URI chuyển hướng, như minh hoạ dưới đây:

  • Phản hồi mã truy cập:

    https://oauth2.example.com/callback#access_token=4/P7q7W91&token_type=Bearer&expires_in=3600

    Ngoài tham số access_token, chuỗi phân mảnh cũng chứa tham số token_type (luôn được đặt thành Bearer) và tham số expires_in chỉ định thời gian tồn tại của mã thông báo tính bằng giây. Nếu tham số state được chỉ định trong yêu cầu mã truy cập, thì giá trị của tham số đó cũng được đưa vào phản hồi.

  • Phản hồi lỗi:
    https://oauth2.example.com/callback#error=access_denied

Phản hồi mẫu của máy chủ OAuth 2.0

Bạn có thể kiểm thử quy trình này bằng cách nhấp vào URL mẫu sau đây. URL này yêu cầu quyền truy cập chỉ có thể đọc để xem siêu dữ liệu cho các tệp trong Google Drive của bạn:

https://accounts.google.com/o/oauth2/v2/auth?
 scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fyoutube.readonly&
 include_granted_scopes=true&
 state=state_parameter_passthrough_value&
 redirect_uri=http%3A%2F%2Flocalhost%2Foauth2callback&
 response_type=token&
 client_id=client_id

Sau khi hoàn tất quy trình OAuth 2.0, bạn sẽ được chuyển hướng đến http://localhost/oauth2callback. URL đó sẽ trả về lỗi 404 NOT FOUND trừ phi máy cục bộ của bạn tình cờ phân phát một tệp tại địa chỉ đó. Bước tiếp theo cung cấp thêm thông tin chi tiết về thông tin được trả về trong URI khi người dùng được chuyển hướng trở lại ứng dụng của bạn.

Gọi API của Google

Điểm cuối OAuth 2.0

Sau khi ứng dụng của bạn nhận được mã thông báo truy cập, bạn có thể sử dụng mã thông báo đó để thay mặt một tài khoản người dùng nhất định thực hiện lệnh gọi đến API của Google nếu(các) phạm vi truy cập mà API yêu cầu đã được cấp. Để thực hiện việc này, hãy đưa mã truy cập vào yêu cầu gửi đến API bằng cách thêm tham số truy vấn access_token hoặc giá trị Bearer của tiêu đề HTTP Authorization. Khi có thể, bạn nên sử dụng tiêu đề HTTP vì chuỗi truy vấn thường xuất hiện trong nhật ký máy chủ. Trong hầu hết các trường hợp, bạn có thể sử dụng thư viện ứng dụng để thiết lập các lệnh gọi đến API của Google (ví dụ: khi gọi API Dữ liệu YouTube).

Xin lưu ý rằng YouTube Data API chỉ hỗ trợ tài khoản dịch vụ cho những chủ sở hữu nội dung trên YouTube sở hữu và quản lý nhiều kênh YouTube, chẳng hạn như hãng thu âm và hãng phim.

Bạn có thể dùng thử tất cả API của Google và xem phạm vi của các API đó tại OAuth 2.0 Playground.

Ví dụ về HTTP GET

Lệnh gọi đến điểm cuối youtube.channels (API Dữ liệu YouTube) sử dụng tiêu đề HTTP Authorization: Bearer có thể có dạng như sau. Xin lưu ý rằng bạn cần chỉ định mã truy cập của riêng mình:

GET /youtube/v3/channels?part=snippet&mine=true HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer access_token

Dưới đây là lệnh gọi đến cùng một API cho người dùng đã xác thực bằng cách sử dụng tham số chuỗi truy vấn access_token:

GET https://www.googleapis.com/youtube/v3/channels?access_token=access_token&part=snippet&mine=true

Ví dụ về curl

Bạn có thể kiểm thử các lệnh này bằng ứng dụng dòng lệnh curl. Dưới đây là ví dụ sử dụng tuỳ chọn tiêu đề HTTP (ưu tiên):

curl -H "Authorization: Bearer access_token" https://www.googleapis.com/youtube/v3/channels?part=snippet&mine=true

Hoặc tuỳ chọn tham số chuỗi truy vấn:

curl https://www.googleapis.com/youtube/v3/channels?access_token=access_token&part=snippet&mine=true

Mã mẫu JavaScript

Đoạn mã dưới đây minh hoạ cách sử dụng CORS (Chia sẻ tài nguyên trên nhiều nguồn gốc) để gửi yêu cầu đến một API của Google. Ví dụ này không sử dụng Thư viện ứng dụng API của Google cho JavaScript. Tuy nhiên, ngay cả khi bạn không sử dụng thư viện ứng dụng, hướng dẫn hỗ trợ CORS trong tài liệu của thư viện đó có thể giúp bạn hiểu rõ hơn về các yêu cầu này.

Trong đoạn mã này, biến access_token đại diện cho mã thông báo mà bạn đã nhận được để thay mặt người dùng được uỷ quyền gửi yêu cầu API. Ví dụ đầy đủ minh hoạ cách lưu trữ mã thông báo đó trong bộ nhớ cục bộ của trình duyệt và truy xuất mã thông báo đó khi đưa ra yêu cầu API.

var xhr = new XMLHttpRequest();
xhr.open('GET',
    'https://www.googleapis.com/youtube/v3/channels?part=snippet&mine=true&' +
    'access_token=' + params['access_token']);
xhr.onreadystatechange = function (e) {
  console.log(xhr.response);
};
xhr.send(null);

Ví dụ đầy đủ

Điểm cuối OAuth 2.0

Mã mẫu này minh hoạ cách hoàn tất quy trình OAuth 2.0 trong JavaScript mà không cần sử dụng Thư viện ứng dụng API của Google cho JavaScript. Mã này dành cho một trang HTML hiển thị nút để thử yêu cầu API. Nếu bạn nhấp vào nút này, mã sẽ kiểm tra xem trang có lưu mã thông báo truy cập API trong bộ nhớ cục bộ của trình duyệt hay không. Nếu có, thì ứng dụng sẽ thực thi yêu cầu API. Nếu không, ứng dụng sẽ bắt đầu quy trình OAuth 2.0.

Đối với luồng OAuth 2.0, trang sẽ tuân theo các bước sau:

  1. Thao tác này chuyển người dùng đến máy chủ OAuth 2.0 của Google. Máy chủ này yêu cầu quyền truy cập vào phạm vi https://www.googleapis.com/auth/youtube.force-ssl.
  2. Sau khi cấp (hoặc từ chối) quyền truy cập vào một hoặc nhiều phạm vi được yêu cầu, người dùng sẽ được chuyển hướng đến trang ban đầu. Trang này sẽ phân tích cú pháp mã thông báo truy cập từ chuỗi giá trị nhận dạng mảnh.
  3. Trang này sử dụng mã thông báo truy cập để tạo yêu cầu API mẫu.

    Yêu cầu API này gọi phương thức channels.list của YouTube Data API để truy xuất dữ liệu về kênh YouTube của người dùng được uỷ quyền.

  4. Nếu yêu cầu thực thi thành công, phản hồi API sẽ được ghi lại trong bảng điều khiển gỡ lỗi của trình duyệt.

Bạn có thể thu hồi quyền truy cập vào ứng dụng thông qua trang Quyền cho Tài khoản Google của mình. Ứng dụng sẽ được liệt kê là OAuth 2.0 Demo for Google API Docs (Bản minh hoạ OAuth 2.0 cho Tài liệu API của Google).

Để chạy mã này trên máy, bạn cần đặt giá trị cho các biến YOUR_CLIENT_IDYOUR_REDIRECT_URI tương ứng với thông tin xác thực uỷ quyền của bạn. Bạn nên đặt biến YOUR_REDIRECT_URI thành cùng một URL nơi trang đang được phân phát. Giá trị này phải khớp chính xác với một trong các URI chuyển hướng được uỷ quyền cho ứng dụng OAuth 2.0 mà bạn đã định cấu hình trong API Console Credentials page. Nếu giá trị này không khớp với một URI được uỷ quyền, bạn sẽ gặp lỗi redirect_uri_mismatch. Dự án của bạn cũng phải bật API thích hợp cho yêu cầu này.

<html><head></head><body>
<script>
  var YOUR_CLIENT_ID = 'REPLACE_THIS_VALUE';
  var YOUR_REDIRECT_URI = 'REPLACE_THIS_VALUE';

  // Parse query string to see if page request is coming from OAuth 2.0 server.
  var fragmentString = location.hash.substring(1);
  var params = {};
  var regex = /([^&=]+)=([^&]*)/g, m;
  while (m = regex.exec(fragmentString)) {
    params[decodeURIComponent(m[1])] = decodeURIComponent(m[2]);
  }
  if (Object.keys(params).length > 0 && params['state']) {
    if (params['state'] == localStorage.getItem('state')) {
      localStorage.setItem('oauth2-test-params', JSON.stringify(params) );

      trySampleRequest();
    } else {
      console.log('State mismatch. Possible CSRF attack');
    }
  }

  // Function to generate a random state value
  function generateCryptoRandomState() {
    const randomValues = new Uint32Array(2);
    window.crypto.getRandomValues(randomValues);

    // Encode as UTF-8
    const utf8Encoder = new TextEncoder();
    const utf8Array = utf8Encoder.encode(
      String.fromCharCode.apply(null, randomValues)
    );

    // Base64 encode the UTF-8 data
    return btoa(String.fromCharCode.apply(null, utf8Array))
      .replace(/\+/g, '-')
      .replace(/\//g, '_')
      .replace(/=+$/, '');
  }

  // 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/youtube/v3/channels?part=snippet&mine=true&' +
          '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() {
    // create random state value and store in local storage
    var state = generateCryptoRandomState();
    localStorage.setItem('state', state);

    // 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/youtube.force-ssl',
                  'state': state,
                  '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>

Quy tắc xác thực nguồn gốc JavaScript

Google áp dụng các quy tắc xác thực sau đây cho nguồn gốc JavaScript để giúp nhà phát triển bảo mật ứng dụng của họ. Nguồn gốc JavaScript của bạn phải tuân thủ các quy tắc này. Xem phần 3 của RFC 3986 để biết định nghĩa về miền, máy chủ lưu trữ và giao thức, được đề cập bên dưới.

Các quy tắc xác thực
Lược đồ

Nguồn gốc JavaScript phải sử dụng giao thức HTTPS, chứ không phải HTTP thuần tuý. URI máy chủ cục bộ (bao gồm cả URI địa chỉ IP máy chủ cục bộ) được miễn trừ khỏi quy tắc này.

Máy chủ lưu trữ

Máy chủ không được là địa chỉ IP thô. Địa chỉ IP của máy chủ cục bộ được miễn trừ khỏi quy tắc này.

Miền
  • TLD của máy chủ lưu trữ (Miền cấp cao nhất) phải thuộc danh sách hậu tố công khai.
  • Miền lưu trữ không được là “googleusercontent.com”.
  • Nguồn gốc JavaScript không được chứa miền rút gọn URL (ví dụ: goo.gl) trừ phi ứng dụng sở hữu miền đó.
  • Userinfo

    Nguồn gốc JavaScript không được chứa thành phần phụ userinfo.

    Đường dẫn

    Nguồn gốc JavaScript không được chứa thành phần đường dẫn.

    Cụm từ tìm kiếm

    Nguồn gốc JavaScript không được chứa thành phần truy vấn.

    Mảnh

    Nguồn gốc JavaScript không được chứa thành phần mảnh.

    Ký tự Nguồn gốc JavaScript không được chứa một số ký tự nhất định, bao gồm:
    • Ký tự đại diện ('*')
    • Ký tự ASCII không in được
    • Mã hoá phần trăm không hợp lệ (mọi mã hoá phần trăm không tuân theo định dạng mã hoá URL là dấu phần trăm theo sau là hai chữ số thập lục phân)
    • Ký tự rỗng (ký tự NULL đã mã hoá, ví dụ: %00, %C0%80)

    Uỷ quyền gia tăng

    Trong giao thức OAuth 2.0, ứng dụng của bạn yêu cầu uỷ quyền để truy cập vào các tài nguyên được xác định theo phạm vi. Đây được coi là phương pháp hay nhất về trải nghiệm người dùng để yêu cầu uỷ quyền cho tài nguyên tại thời điểm bạn cần. Để cho phép hoạt động đó, máy chủ uỷ quyền của Google sẽ hỗ trợ uỷ quyền gia tăng. Tính năng này cho phép bạn yêu cầu các phạm vi khi cần và nếu người dùng cấp quyền cho phạm vi mới, thì sẽ trả về một mã uỷ quyền có thể được hoán đổi cho một mã thông báo chứa tất cả các phạm vi mà người dùng đã cấp cho dự án.

    Ví dụ: giả sử một ứng dụng giúp người dùng xác định các sự kiện thú vị tại địa phương. Ứng dụng này cho phép người dùng xem video về các sự kiện, đánh giá video và thêm video vào danh sách phát. Người dùng cũng có thể sử dụng ứng dụng này để thêm sự kiện vào Lịch Google.

    Trong trường hợp này, tại thời điểm đăng nhập, ứng dụng có thể không cần hoặc không yêu cầu quyền truy cập vào bất kỳ phạm vi nào. Tuy nhiên, nếu người dùng cố gắng xếp hạng một video, thêm một video vào danh sách phát hoặc thực hiện một hành động khác trên YouTube, thì ứng dụng có thể yêu cầu quyền truy cập vào phạm vi https://www.googleapis.com/auth/youtube.force-ssl. Tương tự, ứng dụng có thể yêu cầu quyền truy cập vào phạm vi https://www.googleapis.com/auth/calendar nếu người dùng cố gắng thêm một sự kiện trên lịch.

    Các quy tắc sau đây áp dụng cho mã truy cập nhận được từ một quá trình uỷ quyền gia tăng:

    • Bạn có thể dùng mã thông báo này để truy cập vào các tài nguyên tương ứng với bất kỳ phạm vi nào được đưa vào quyền uỷ quyền mới, kết hợp.
    • Khi bạn sử dụng mã thông báo làm mới cho quyền uỷ quyền kết hợp để lấy mã thông báo truy cập, mã thông báo truy cập sẽ đại diện cho quyền uỷ quyền kết hợp và có thể được dùng cho bất kỳ giá trị scope nào có trong phản hồi.
    • Quyền uỷ quyền kết hợp bao gồm tất cả các phạm vi mà người dùng đã cấp cho dự án API, ngay cả khi các quyền cấp này được yêu cầu từ nhiều ứng dụng. Ví dụ: nếu người dùng cấp quyền truy cập vào một phạm vi bằng ứng dụng máy tính của ứng dụng, sau đó cấp một phạm vi khác cho cùng một ứng dụng thông qua ứng dụng di động, thì quyền uỷ quyền kết hợp sẽ bao gồm cả hai phạm vi.
    • Nếu bạn thu hồi một mã thông báo đại diện cho một quyền uỷ quyền kết hợp, thì quyền truy cập vào tất cả các phạm vi của quyền uỷ quyền đó thay mặt cho người dùng được liên kết sẽ bị thu hồi đồng thời.

    Các mã mẫu bên dưới cho biết cách thêm phạm vi vào mã truy cập hiện có. Phương pháp này cho phép ứng dụng của bạn tránh phải quản lý nhiều mã thông báo truy cập.

    Điểm cuối OAuth 2.0

    Trong ví dụ này, ứng dụng gọi yêu cầu quyền truy cập để truy xuất dữ liệu YouTube Analytics của người dùng, ngoài mọi quyền truy cập khác mà người dùng đã cấp cho ứng dụng.

    Để thêm phạm vi vào một mã truy cập hiện có, hãy thêm tham số include_granted_scopes vào yêu cầu gửi tới máy chủ OAuth 2.0 của Google.

    Đoạn mã sau đây minh hoạ cách thực hiện việc đó. Đoạn mã giả định rằng bạn đã lưu trữ các phạm vi mà mã truy cập của bạn hợp lệ trong bộ nhớ cục bộ của trình duyệt. (Mã ví dụ đầy đủ lưu trữ danh sách các phạm vi mà mã thông báo truy cập hợp lệ bằng cách đặt thuộc tính oauth2-test-params.scope trong bộ nhớ cục bộ của trình duyệt.)

    Đoạn mã này so sánh các phạm vi mà mã truy cập hợp lệ với phạm vi bạn muốn sử dụng cho một truy vấn cụ thể. Nếu mã truy cập không bao gồm phạm vi đó, quy trình OAuth 2.0 sẽ bắt đầu. Ở đây, hàm oauth2SignIn giống với hàm được cung cấp trong bước 2 (và hàm này được cung cấp sau trong ví dụ đầy đủ).

    var SCOPE = 'https://www.googleapis.com/auth/youtube.force-ssl';
    var params = JSON.parse(localStorage.getItem('oauth2-test-params'));
    
    var current_scope_granted = false;
    if (params.hasOwnProperty('scope')) {
      var scopes = params['scope'].split(' ');
      for (var s = 0; s < scopes.length; s++) {
        if (SCOPE == scopes[s]) {
          current_scope_granted = true;
        }
      }
    }
    
    if (!current_scope_granted) {
      oauth2SignIn(); // This function is defined elsewhere in this document.
    } else {
      // Since you already have access, you can proceed with the API request.
    }

    Thu hồi mã thông báo

    Trong một số trường hợp, người dùng có thể muốn thu hồi quyền truy cập đã cấp cho một ứng dụng. Người dùng có thể thu hồi quyền truy cập bằng cách truy cập vào phần Cài đặt tài khoản. Hãy xem phần Xoá quyền truy cập vào trang web hoặc ứng dụng trong tài liệu hỗ trợ về Các trang web và ứng dụng của bên thứ ba có quyền truy cập vào tài khoản của bạn để biết thêm thông tin.

    Ứng dụng cũng có thể thu hồi quyền truy cập đã cấp cho ứng dụng đó theo phương thức lập trình. Việc thu hồi có lập trình là rất quan trọng trong trường hợp người dùng huỷ đăng ký, xoá ứng dụng hoặc tài nguyên API mà ứng dụng yêu cầu đã thay đổi đáng kể. Nói cách khác, một phần của quy trình xoá có thể bao gồm yêu cầu API để đảm bảo các quyền đã cấp cho ứng dụng trước đó sẽ bị xoá.

    Điểm cuối OAuth 2.0

    Để thu hồi mã thông báo theo phương thức lập trình, ứng dụng của bạn sẽ gửi yêu cầu đến https://oauth2.googleapis.com/revoke và đưa mã thông báo vào làm tham số:

    curl -d -X -POST --header "Content-type:application/x-www-form-urlencoded" \
            https://oauth2.googleapis.com/revoke?token={token}

    Mã thông báo có thể là mã thông báo truy cập hoặc mã thông báo làm mới. Nếu mã thông báo là mã truy cập và có mã làm mới tương ứng, thì mã làm mới cũng sẽ bị thu hồi.

    Nếu quá trình thu hồi được xử lý thành công, thì mã trạng thái HTTP của phản hồi sẽ là 200. Đối với các điều kiện lỗi, hệ thống sẽ trả về mã trạng thái HTTP 400 cùng với mã lỗi.

    Đoạn mã JavaScript sau đây cho biết cách thu hồi mã thông báo trong JavaScript mà không cần sử dụng Thư viện ứng dụng API của Google cho JavaScript. Vì điểm cuối OAuth 2.0 của Google để thu hồi mã thông báo không hỗ trợ tính năng Chia sẻ tài nguyên trên nhiều nguồn gốc (CORS), nên mã này sẽ tạo một biểu mẫu và gửi biểu mẫu đến điểm cuối thay vì sử dụng phương thức XMLHttpRequest() để đăng yêu cầu.

    function revokeAccess(accessToken) {
      // Google's OAuth 2.0 endpoint for revoking access tokens.
      var revokeTokenEndpoint = 'https://oauth2.googleapis.com/revoke';
    
      // Create <form> element to use to POST data to the OAuth 2.0 endpoint.
      var form = document.createElement('form');
      form.setAttribute('method', 'post');
      form.setAttribute('action', revokeTokenEndpoint);
    
      // Add access token to the form so it is set as value of 'token' parameter.
      // This corresponds to the sample curl request, where the URL is:
      //      https://oauth2.googleapis.com/revoke?token={token}
      var tokenField = document.createElement('input');
      tokenField.setAttribute('type', 'hidden');
      tokenField.setAttribute('name', 'token');
      tokenField.setAttribute('value', accessToken);
      form.appendChild(tokenField);
    
      // Add form to page and submit it to actually revoke the token.
      document.body.appendChild(form);
      form.submit();
    }

    Triển khai tính năng Bảo vệ nhiều tài khoản

    Bạn nên thực hiện thêm một bước để bảo vệ tài khoản của người dùng, đó là triển khai tính năng Bảo vệ nhiều tài khoản bằng cách sử dụng Dịch vụ bảo vệ nhiều tài khoản của Google. Dịch vụ này cho phép bạn đăng ký nhận thông báo về sự kiện bảo mật. Thông báo này cung cấp thông tin cho ứng dụng của bạn về những thay đổi lớn đối với tài khoản người dùng. Sau đó, bạn có thể sử dụng thông tin này để hành động tuỳ thuộc vào cách bạn quyết định phản hồi các sự kiện.

    Dưới đây là một số ví dụ về các loại sự kiện mà Dịch vụ bảo vệ nhiều tài khoản của Google gửi tới ứng dụng của bạn:

    • https://schemas.openid.net/secevent/risc/event-type/sessions-revoked
    • https://schemas.openid.net/secevent/oauth/event-type/token-revoked
    • https://schemas.openid.net/secevent/risc/event-type/account-disabled

    Hãy xem trang Bảo vệ tài khoản người dùng bằng tính năng Bảo vệ nhiều tài khoản để biết thêm thông tin về cách triển khai tính năng Bảo vệ nhiều tài khoản và danh sách đầy đủ các sự kiện hiện có.