Sử dụng OAuth 2.0 cho ứng dụng máy chủ web

Tài liệu này giải thích cách các ứng dụng máy chủ web sử dụng Thư viện ứng dụng API của Google hoặc điểm cuối OAuth 2.0 của Google để triển khai việc uỷ quyền OAuth 2.0 để truy cập vào API YouTube Analytics hoặc API Báo cáo YouTube.

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 của họ. Ví dụ: một ứng dụng có thể sử dụng OAuth 2.0 để được cấp quyền truy xuất dữ liệu YouTube Analytics của kênh.

Quy trình OAuth 2.0 này dành riêng cho việc cho phép người dùng. API này được thiết kế cho các ứng dụng có thể lưu trữ thông tin bảo mật và duy trì trạng thái. Một ứng dụng máy chủ web được cấp phép đúng cách có thể truy cập API trong khi người dùng tương tác với ứng dụng hoặc sau khi người dùng rời khỏi ứng dụng.

Các ứng dụng máy chủ web cũng thường dùng tài khoản dịch vụ để cho phép các yêu cầu API, đặc biệt là khi gọi Cloud API để truy cập vào dữ liệu dựa trên dự án thay vì dữ liệu riêng của người dùng. Ứng dụng máy chủ web có thể sử dụng tài khoản dịch vụ cùng với sự cho phép của người dùng.

  • API YouTube Analytics không hỗ trợ quy trình tài khoản dịch vụ.
  • API Báo cáo của YouTube chỉ hỗ trợ quy trình tài khoản dịch vụ dành 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. Cụ thể, chủ sở hữu nội dung có thể sử dụng tài khoản dịch vụ trong các yêu cầu API có đặt giá trị cho tham số yêu cầu onBehalfOfContentOwner.

Thư viện ứng dụng

Các ví dụ theo ngôn ngữ cụ thể trên trang này sử dụng Thư viện ứng dụng API của Google để triển khai hoạt động uỷ quyền OAuth 2.0. Để chạy mã mẫu, trước tiên, bạn phải cài đặt thư viện ứng dụng cho ngôn ngữ của mình.

Khi bạn dùng Thư viện ứng dụng API của Google để xử lý quy trình OAuth 2.0 của ứng dụng, thư viện ứng dụng sẽ thực hiện nhiều thao tác mà ứng dụng sẽ phải tự xử lý. Ví dụ: mã này xác định thời điểm ứng dụng có thể dùng hoặc làm mới mã truy cập đã lưu trữ, cũng như thời điểm ứng dụng phải nhận được sự đồng ý. Thư viện ứng dụng cũng tạo URL chuyển hướng chính xác và giúp triển khai các trình xử lý chuyển hướng có trao đổi mã uỷ quyền lấy mã truy cập.

Thư viện ứng dụng API của Google dành cho các ứng dụng phía máy chủ hiện hỗ trợ các ngôn ngữ sau:

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

Bật API cho dự án

Bất kỳ ứng dụng nào 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 YouTube Analytics cũng như API Báo cáo của YouTube. Nhiều ứng dụng truy xuất dữ liệu YouTube Analytics cũng có giao diện với API dữ liệu YouTube. Tìm bất kỳ API nào 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 uỷ quyền

Mọi ứng dụng dùng OAuth 2.0 để truy cập vào API Google đều phải có thông tin xác thực uỷ quyền giúp nhận dạng ứng dụng đó với 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 đó, ứng dụng của bạn có thể sử dụng thông tin đăng nhập để 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. Điền vào biểu mẫu và nhấp vào Tạo. Những ứng dụng dùng ngôn ngữ và khung như PHP, Java, Python, Ruby và .NET phải chỉ định URI chuyển hướng được uỷ quyền. URI chuyển hướng là những điểm cuối mà máy chủ OAuth 2.0 có thể gửi phản hồi. Các điểm cuối này phải tuân thủ các quy tắc xác thực của Google.

    Để kiểm thử, bạn có thể chỉ định các URI tham chiếu đến máy cục bộ, chẳng hạn như http://localhost:8080. Vì vậy, xin lưu ý rằng tất cả các ví dụ trong tài liệu này đều sử dụng http://localhost:8080 làm URI chuyển hướng.

    Bạn nên thiết kế điểm cuối xác thực của ứng dụng để ứng dụng không tiết lộ mã uỷ quyền cho các tài nguyên khác trên trang.

Sau khi tạo thông tin đăng nhập, hãy tải tệp client_secret.json xuống từ API Console. Lưu trữ an toàn tệp ở một vị trí mà chỉ ứng dụng của bạn mới có thể truy cập.

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 lượng quyền truy cập mà họ cấp cho ứng dụng của bạn. Do đó, có thể có mối quan hệ nghịch đảo giữa số phạm vi được yêu cầu và khả năng có được sự đồng ý của người dùng.

Trước khi bắt đầu triển khai tính năng 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.

Ứng dụng của bạn cũng nên yêu cầu quyền truy cập vào các phạm vi uỷ quyền thông qua quy trình uỷ quyền gia tăng, trong đó ứng dụng yêu cầu quyền truy cập vào dữ liệu người dùng theo bối cảnh. Phương pháp hay nhất này giúp người dùng dễ dàng hơn trong việc hiểu 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.

API YouTube Analytics sử dụng các phạm vi sau:

Phạm vi
https://www.googleapis.com/auth/youtube Quản lý tài khoản YouTube của bạn
https://www.googleapis.com/auth/youtube.readonly Xem tài khoản YouTube của bạn
https://www.googleapis.com/auth/youtubepartner Xem và quản lý nội dung cũng như nội dung liên quan của bạn trên YouTube
https://www.googleapis.com/auth/yt-analytics-monetary.readonly Xem báo cáo YouTube Analytics bằng tiền và phi tiền tệ cho nội dung YouTube của bạn
https://www.googleapis.com/auth/yt-analytics.readonly Xem báo cáo YouTube Analytics cho nội dung YouTube của bạn

API Báo cáo của YouTube sử dụng các phạm vi sau:

Phạm vi
https://www.googleapis.com/auth/yt-analytics-monetary.readonly Xem báo cáo YouTube Analytics bằng tiền và phi tiền tệ cho nội dung YouTube của bạn
https://www.googleapis.com/auth/yt-analytics.readonly Xem báo cáo YouTube Analytics cho nội dung YouTube của bạn

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

Yêu cầu đối với từng ngôn ngữ

Để chạy bất kỳ mã mẫu nào trong tài liệu này, bạn cần có Tài khoản Google, quyền truy cập Internet và trình duyệt web. Nếu bạn đang sử dụng một trong các thư viện ứng dụng API, hãy xem cả các yêu cầu theo ngôn ngữ cụ thể ở bên dưới.

1.199

Để chạy mã mẫu PHP trong tài liệu này, bạn cần có:

  • PHP 5.6 trở lên nếu đã cài đặt giao diện dòng lệnh (CLI) và tiện ích JSON.
  • Công cụ quản lý phần phụ thuộc Composer.
  • Thư viện ứng dụng API của Google cho PHP:

    composer require google/apiclient:^2.10

Python

Để chạy mã mẫu Python trong tài liệu này, bạn sẽ cần:

  • Python 2.6 trở lên
  • Công cụ quản lý gói pip.
  • Thư viện ứng dụng API của Google cho Python:
    pip install --upgrade google-api-python-client
  • google-auth, google-auth-oauthlibgoogle-auth-httplib2 để uỷ quyền cho người dùng.
    pip install --upgrade google-auth google-auth-oauthlib google-auth-httplib2
  • Khung ứng dụng web Flask Python.
    pip install --upgrade flask
  • Thư viện HTTP requests.
    pip install --upgrade requests

Ruby

Để chạy mã mẫu của Ruby trong tài liệu này, bạn sẽ cần:

  • Ruby 2.6 trở lên
  • Thư viện xác thực của Google dành cho Ruby:

    gem install googleauth
  • Khung ứng dụng web Sinatra Ruby.

    gem install sinatra

Node.js

Để chạy mã mẫu Node.js trong tài liệu này, bạn sẽ cần:

  • LTS bảo trì, LTS đang hoạt động hoặc bản phát hành Node.js hiện tại.
  • Ứng dụng Node.js API của Google:

    npm install googleapis

HTTP/REST

Bạn không cần cài đặt bất kỳ thư viện nào để có thể gọi trực tiếp điểm cuối OAuth 2.0.

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 để có được sự đồng ý của người dùng nhằm thực hiện yêu cầu API thay mặt người dùng. Ứng dụng của bạn phải có được sự đồng ý đó thì mới có thể thực thi yêu cầu API của Google (yêu cầu phải được người dùng cho phép).

Danh sách dưới đây tóm tắt nhanh các bước sau:

  1. Ứng dụng của bạn xác định các quyền mà ứng dụng cần.
  2. Ứng dụng của bạn chuyển hướng người dùng đến Google cùng với danh sách các quyền được yêu cầu.
  3. Người dùng quyết định có cấp quyền cho ứng dụng của bạn hay không.
  4. Ứng dụng của bạn tìm hiểu những gì người dùng quyết định.
  5. Nếu người dùng đã cấp các quyền được yêu cầu, thì ứng dụng của bạn sẽ truy xuất mã thông báo cần thiết để thay mặt người dùng gửi yêu cầu API.

Bước 1: Đặt tham số uỷ quyền

Bước đầu tiên là tạo yêu cầu uỷ quyền. Yêu cầu đó sẽ đặt các tham số nhận dạng ứng dụng của bạn và xác định các quyền mà người dùng sẽ được yêu cầu cấp cho ứng dụng của bạn.

  • Nếu sử dụng thư viện ứng dụng của Google để xác thực và uỷ quyền OAuth 2.0, thì bạn sẽ tạo và định cấu hình một đối tượng giúp xác định các tham số này.
  • Nếu gọi trực tiếp điểm cuối của Google OAuth 2.0, bạn sẽ tạo một URL và đặt các tham số cho URL đó.

Thẻ bên dưới xác định các tham số uỷ quyền được hỗ trợ cho các ứng dụng máy chủ web. Các ví dụ theo ngôn ngữ cụ thể cũng cho thấy cách sử dụng thư viện ứng dụng hoặc thư viện uỷ quyền để định cấu hình một đối tượng sẽ đặt các tham số đó.

1.199

Đoạn mã dưới đây sẽ tạo một đối tượng Google\Client(). Đối tượng này xác định các thông số trong yêu cầu uỷ quyền.

Đối tượng đó sử dụng thông tin từ tệp client_secret.json để xác định ứng dụng của bạn. (Xem bài viết tạo thông tin xác thực uỷ quyền để biết thêm thông tin về tệp đó.) Đối tượng này cũng xác định các phạm vi mà ứng dụng của bạn đang yêu cầu quyền truy cập và URL đến điểm cuối xác thực của ứng dụng. Điểm cuối này sẽ xử lý phản hồi từ máy chủ OAuth 2.0 của Google. Cuối cùng, đoạn mã này sẽ đặt các tham số access_typeinclude_granted_scopes không bắt buộc.

Ví dụ: để yêu cầu quyền truy cập ngoại tuyến nhằm truy xuất các báo cáo YouTube Analytics của người dùng, hãy làm như sau:

$client = new Google\Client();

// Required, call the setAuthConfig function to load authorization credentials from
// client_secret.json file.
$client->setAuthConfig('client_secret.json');

// Required, to set the scope value, call the addScope function
$client->addScope(Google_Service_YouTubeAnalytics::YT_ANALYTICS_READONLY);

// Required, call the setRedirectUri function to specify a valid redirect URI for the
// provided client_id
$client->setRedirectUri('http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php');

// Recommended, offline access will give you both an access and refresh token so that
// your app can refresh the access token without user interaction.
$client->setAccessType('offline');

// Recommended, call the setState function. Using a state value can increase your assurance that
// an incoming connection is the result of an authentication request.
$client->setState($sample_passthrough_value);

// Optional, if your application knows which user is trying to authenticate, it can use this
// parameter to provide a hint to the Google Authentication Server.
$client->setLoginHint('hint@example.com');

// Optional, call the setPrompt function to set "consent" will prompt the user for consent
$client->setPrompt('consent');

// Optional, call the setIncludeGrantedScopes function with true to enable incremental
// authorization
$client->setIncludeGrantedScopes(true);

Python

Đoạn mã sau đây sử dụng mô-đun google-auth-oauthlib.flow để tạo yêu cầu uỷ quyền.

Mã này sẽ tạo một đối tượng Flow giúp nhận dạng ứng dụng của bạn bằng cách sử dụng thông tin từ tệp client_secret.json mà bạn đã tải xuống sau khi tạo thông tin xác thực uỷ quyền. Đối tượng đó cũng xác định các phạm vi mà ứng dụng của bạn đang yêu cầu quyền truy cập và URL đến điểm cuối xác thực của ứng dụng. Điểm cuối này sẽ xử lý phản hồi từ máy chủ OAuth 2.0 của Google. Cuối cùng, đoạn mã này sẽ đặt các tham số access_typeinclude_granted_scopes (không bắt buộc).

Ví dụ: để yêu cầu quyền truy cập ngoại tuyến nhằm truy xuất các báo cáo YouTube Analytics của người dùng, hãy làm như sau:

import google.oauth2.credentials
import google_auth_oauthlib.flow

# Required, call the from_client_secrets_file method to retrieve the client ID from a
# client_secret.json file. The client ID (from that file) and access scopes are required. (You can
# also use the from_client_config method, which passes the client configuration as it originally
# appeared in a client secrets file but doesn't access the file itself.)
flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
    'client_secret.json',
    scopes=['https://www.googleapis.com/auth/yt-analytics.readonly'])

# Required, indicate where the API server will redirect the user after the user completes
# the authorization flow. The redirect URI is required. The value must exactly
# match one of the authorized redirect URIs for the OAuth 2.0 client, which you
# configured in the API Console. If this value doesn't match an authorized URI,
# you will get a 'redirect_uri_mismatch' error.
flow.redirect_uri = 'https://www.example.com/oauth2callback'

# Generate URL for request to Google's OAuth 2.0 server.
# Use kwargs to set optional request parameters.
authorization_url, state = flow.authorization_url(
    # Recommended, enable offline access so that you can refresh an access token without
    # re-prompting the user for permission. Recommended for web server apps.
    access_type='offline',
    # Optional, enable incremental authorization. Recommended as a best practice.
    include_granted_scopes='true',
    # Recommended, state value can increase your assurance that an incoming connection is the result
    # of an authentication request.
    state=sample_passthrough_value,
    # Optional, if your application knows which user is trying to authenticate, it can use this
    # parameter to provide a hint to the Google Authentication Server.
    login_hint='hint@example.com',
    # Optional, set prompt to 'consent' will prompt the user for consent
    prompt='consent')

Ruby

Sử dụng tệp client_secrets.json mà bạn đã tạo để định cấu hình một đối tượng ứng dụng trong ứng dụng của mình. Khi định cấu hình một đối tượng ứng dụng, bạn sẽ chỉ định các phạm vi mà ứng dụng cần truy cập, cùng với URL đến điểm cuối xác thực của ứng dụng. Điểm cuối này sẽ xử lý phản hồi từ máy chủ OAuth 2.0.

Ví dụ: để yêu cầu quyền truy cập ngoại tuyến nhằm truy xuất các báo cáo YouTube Analytics của người dùng, hãy làm như sau:

require 'google/apis/youtube_analytics_v1'
require "googleauth"
require 'googleauth/stores/redis_token_store'

client_id = Google::Auth::ClientId.from_file('/path/to/client_secret.json')
scope = 'https://www.googleapis.com/auth/yt-analytics.readonly'
token_store = Google::Auth::Stores::RedisTokenStore.new(redis: Redis.new)
authorizer = Google::Auth::WebUserAuthorizer.new(client_id, scope, token_store, '/oauth2callback')

Ứng dụng của bạn dùng đối tượng ứng dụng khách để thực hiện các thao tác OAuth 2.0, chẳng hạn như tạo URL yêu cầu uỷ quyền và áp dụng mã truy cập cho các yêu cầu HTTP.

Node.js

Đoạn mã dưới đây sẽ tạo một đối tượng google.auth.OAuth2. Đối tượng này xác định các thông số trong yêu cầu uỷ quyền.

Đối tượng đó sử dụng thông tin từ tệp client_secret.json để xác định ứng dụng của bạn. Để yêu cầu người dùng cấp quyền truy xuất mã truy cập, bạn phải chuyển hướng họ đến trang đồng ý. Cách tạo URL trang đồng ý:

const {google} = require('googleapis');

/**
 * To use OAuth2 authentication, we need access to a CLIENT_ID, CLIENT_SECRET, AND REDIRECT_URI
 * from the client_secret.json file. To get these credentials for your application, visit
 * https://console.cloud.google.com/apis/credentials.
 */
const oauth2Client = new google.auth.OAuth2(
  YOUR_CLIENT_ID,
  YOUR_CLIENT_SECRET,
  YOUR_REDIRECT_URL
);

// Access scopes for read-only Drive activity.
const scopes = [
  'https://www.googleapis.com/auth/drive.metadata.readonly'
];

// Generate a url that asks permissions for the Drive activity scope
const authorizationUrl = oauth2Client.generateAuthUrl({
  // 'online' (default) or 'offline' (gets refresh_token)
  access_type: 'offline',
  /** Pass in the scopes array defined above.
    * Alternatively, if only one scope is needed, you can pass a scope URL as a string */
  scope: scopes,
  // Enable incremental authorization. Recommended as a best practice.
  include_granted_scopes: true
});

Lưu ý quan trọngrefresh_token chỉ được trả về trong lần uỷ quyền đầu tiên. Bạn có thể xem thêm thông tin tại đây.

HTTP/REST

Điểm cuối OAuth 2.0 của Google nằm tại https://accounts.google.com/o/oauth2/v2/auth. Bạn chỉ có thể truy cập vào điểm cuối này qua HTTPS. Các kết nối HTTP thuần tuý 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 của ứng dụng. 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 vị trí mà 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 một URI chuyển hướng được uỷ quyền cho client_id được cung cấp, bạn sẽ gặp lỗi redirect_uri_mismatch.

Xin lưu ý rằng giao thức, cách viết hoa và dấu gạch chéo http hoặc https ('/') phải khớp tất cả.

response_type Bắt buộc

Xác định xem điểm cuối của Google OAuth 2.0 có trả về mã uỷ quyền hay không.

Đặt giá trị tham số thành code cho các ứng dụng máy chủ web.

scope Bắt buộc

Một danh sách phạm vi được phân tách bằng dấu cách giúp xác định những tài nguyên mà ứng dụng của bạn có thể thay mặt người dùng truy cập. Những giá trị này thông báo cho màn hình xin phép 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 lượng quyền truy cập mà họ cấp cho ứng dụng của bạn. Do đó, có mối quan hệ nghịch đảo giữa số phạm vi được yêu cầu và khả năng có được sự đồng ý của người dùng.

API YouTube Analytics sử dụng các phạm vi sau:

Phạm vi
https://www.googleapis.com/auth/youtube Quản lý tài khoản YouTube của bạn
https://www.googleapis.com/auth/youtube.readonly Xem tài khoản YouTube của bạn
https://www.googleapis.com/auth/youtubepartner Xem và quản lý nội dung cũng như nội dung liên quan của bạn trên YouTube
https://www.googleapis.com/auth/yt-analytics-monetary.readonly Xem báo cáo YouTube Analytics bằng tiền và phi tiền tệ cho nội dung YouTube của bạn
https://www.googleapis.com/auth/yt-analytics.readonly Xem báo cáo YouTube Analytics cho nội dung YouTube của bạn

API Báo cáo của YouTube sử dụng các phạm vi sau:

Phạm vi
https://www.googleapis.com/auth/yt-analytics-monetary.readonly Xem báo cáo YouTube Analytics bằng tiền và phi tiền tệ cho nội dung YouTube của bạn
https://www.googleapis.com/auth/yt-analytics.readonly Xem báo cáo YouTube Analytics cho nội dung YouTube của bạn

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

Ứng dụng của bạn nên yêu cầu quyền truy cập vào phạm vi uỷ quyền trong bối cảnh bất cứ khi nào có thể. Bằng việc 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 sẽ giúp người dùng dễ dàng hiểu 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.

access_type Recommended (Nên dùng)

Cho biết liệu ứng dụng của bạn có thể làm mới mã truy cập khi người dùng không có mặt trong trình duyệt hay không. Các giá trị thông số hợp lệ là online (là giá trị mặc định) và offline.

Thiết lập giá trị thành offline nếu ứng dụng của bạn cần làm mới mã truy cập khi người dùng không có mặt trên trình duyệt. Đây là phương thức làm mới mã truy cập được mô tả ở phần sau của tài liệu này. Giá trị này hướng dẫn máy chủ uỷ quyền của Google trả về mã làm mới mã truy cập vào lần đầu tiên ứng dụng của bạn trao đổi mã uỷ quyền cho mã thông báo.

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 thành phần truy vấ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 nhiều mục đích, chẳng hạn như hướng người dùng đến đúng tài nguyên trong ứng dụng, gửi số chỉ dùng một lần và giảm thiểu hành vi giả mạo yêu cầu trên nhiều trang web. Vì có thể đoán được redirect_uri, nên việc sử dụng giá trị state có thể giúp bạn tăng mức độ đảm bảo rằng 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 cookie hoặc một giá trị khác ghi lại trạng thái của ứng dụng, thì bạn có thể xác thực phản hồi để đảm bảo thêm 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 chống lại các cuộc tấn công như giả mạ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 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 khác trong bối 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ẽ áp dụng cho mọi phạm vi mà trước đây người dùng đã cấp quyền truy cập vào ứng dụng. Hãy xem phần uỷ quyền gia tăng để tham khảo ví dụ.

login_hint Không bắt buộc

Nếu ứng dụng của bạn biết người dùng nào đang cố xác thực, thì ứng dụng có thể sử dụng tham 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 chọn phiên đăng nhập nhiều tài khoản thích hợp.

Đặt giá trị tham số thành một đị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 trình bày cho người dùng, được phân tách bằng dấu cách và phân biệt chữ hoa chữ thường. Nếu bạn không chỉ định tham số này, người dùng sẽ chỉ được nhắc vào 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 nhở người dùng đồng ý lại để biết thêm thông tin.

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

none Đừ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.

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

Chuyển hướng người dùng đến máy chủ OAuth 2.0 của Google để bắt đầu quy trình xác thực và uỷ quyền. Thông thường, trường hợp này xảy ra khi ứng dụng của bạn cần truy cập vào dữ liệu của người dùng lần đầu tiên. Trong trường hợp uỷ quyền gia tăng, bước này cũng xảy ra khi ứng dụng của bạn lần đầu cần truy cập vào các tài nguyên bổ sung mà ứng dụng chưa có quyền truy cập.

1.199

  1. Tạo một URL để yêu cầu quyền truy cập từ máy chủ OAuth 2.0 của Google:
    $auth_url = $client->createAuthUrl();
  2. Chuyển hướng người dùng đến $auth_url:
    header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));

Python

Ví dụ này cho thấy cách chuyển hướng người dùng đến URL uỷ quyền bằng khung ứng dụng web Flask:

return flask.redirect(authorization_url)

Ruby

  1. Tạo một URL để yêu cầu quyền truy cập từ máy chủ OAuth 2.0 của Google:
    auth_uri = authorizer.get_authorization_url(login_hint: user_id, request: request)
  2. Chuyển hướng người dùng đến auth_uri.

Node.js

  1. Sử dụng URL đã tạo authorizationUrl trong phương thức Bước 1 generateAuthUrl để yêu cầu quyền truy cập từ máy chủ OAuth 2.0 của Google.
  2. Chuyển hướng người dùng đến authorizationUrl.
    res.writeHead(301, { "Location": authorizationUrl });

HTTP/REST

Sample redirect to Google's authorization server

The sample URL below requests offline access (access_type=offline) to a scope that permits access to retrieve the user's YouTube Analytics reports. It uses incremental authorization to ensure that the new access token covers any scopes to which the user previously granted the application access. The URL also sets values for the required redirect_uri, response_type, and client_id parameters as well as for the state parameter. The URL contains line breaks and spaces for readability.

https://accounts.google.com/o/oauth2/v2/auth?
 scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fyt-analytics.readonly&
 access_type=offline&
 include_granted_scopes=true&
 state=state_parameter_passthrough_value&
 redirect_uri=http%3A%2F%2Flocalhost%2Foauth2callback&
 response_type=code&
 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áy chủ OAuth 2.0 của Google sẽ xác thực người dùng và xin sự đồng ý của người dùng để ứng dụng của bạn truy cập vào các phạm vi được yêu cầu. Phản hồi được gửi về ứng dụng của bạn bằng URL chuyển hướng mà bạn đã chỉ định.

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

Ở bước này, người dùng quyết định có cấp cho ứng dụng của bạn quyền truy cập mà họ yêu cầu hay không. Ở giai đoạn này, Google sẽ hiện một cửa sổ đồng ý cho thấy tên ứng dụng của bạn và các dịch vụ API của Google mà Google đang yêu cầu cấp quyền truy cập bằng thông tin xác thực cấp quyền của người dùng và bản tóm tắt về phạm vi quyền 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 đang chờ phản hồi từ máy chủ OAuth 2.0 của Google cho biết liệu có quyền truy cập nào đã được cấp hay không. Câu trả lời đó được giải thích trong bước sau.

Lỗi

Các yêu cầu gửi đế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 dành cho người dùng thay vì các quy trình xác thực và uỷ quyền như dự kiến. Dưới đây là các mã lỗi phổ biến và giải pháp được đề xuất.

admin_policy_enforced

Tài khoản Google không thể cấp quyền cho một hoặc nhiều phạm vi theo yêu cầu theo chính sách của quản trị viên Google Workspace của họ. 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 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ả các phạm vi hoặc các phạm vi nhạy cảm và bị hạn chế cho đến khi mã ứng dụng khách OAuth của bạn được cấp quyền truy cập rõ ràng.

disallowed_useragent

Điểm cuối uỷ quyền hiển thị bên trong một tác nhân người dùng nhúng không được Chính sách OAuth 2.0 của Google 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ở yêu cầu uỷ quyền trong android.webkit.WebView. Thay vào đó, nhà phát triển nên chuyển sang sử dụng các thư viện Android như Đăng nhập bằng Google cho Android hoặc AppAuth cho Android của OpenSL Foundation.

Các nhà phát triển web có thể gặp phải lỗi này khi ứ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à một 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 mở các đường liên kết chung 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 của Android cũng là một tuỳ chọn được hỗ trợ.

iOS

Nhà phát triển iOS và macOS có thể gặp phải lỗi này khi mở 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 dành cho iOS, chẳng hạn như tính năng Đăng nhập bằng Google dành cho iOS hoặc AppAuth cho iOS của ID mở Foundation.

Các nhà phát triển web có thể gặp phải 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à một 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 mở các đường liên kết chung 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 phổ quát 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 khách OAuth trong yêu cầu là một phần của dự án giới hạn quyền truy cập vào các Tài khoản Google trong một tổ chức cụ thể trên Google Cloud. Để biết thêm thông tin về lựa 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 Thiết lập màn hình xin phép bằng OAuth.

invalid_client

Mật khẩu ứng dụng khách OAuth không chính xác. Xem lại cấu hình ứng dụng OAuth, bao gồm cả mã ứng dụng khách và khoá bí mật dùng cho yêu cầu này.

invalid_grant

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

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 khách OAuth. Xem lại các URI chuyển hướng được uỷ quyền trong Google API Console Credentials page.

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

invalid_request

Đã xảy ra lỗi với yêu cầu của bạn. Điều này có thể là do một số lý do:

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

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

Máy chủ OAuth 2.0 phản hồi yêu cầu truy cập của ứng dụng bằng cách sử dụng URL được chỉ định trong yêu cầu.

Nếu người dùng phê duyệt yêu cầu truy cập, thì phản hồi sẽ chứa mã uỷ quyền. 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ã uỷ quyền hoặc thông báo lỗi được trả về cho máy chủ web sẽ xuất hiện trên chuỗi truy vấn, như minh hoạ dưới đây:

Phản hồi lỗi:

https://oauth2.example.com/auth?error=access_denied

Phản hồi về mã uỷ quyền:

https://oauth2.example.com/auth?code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7

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. URL này yêu cầu quyền 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%2Fyt-analytics.readonly&
 access_type=offline&
 include_granted_scopes=true&
 state=state_parameter_passthrough_value&
 redirect_uri=http%3A%2F%2Flocalhost%2Foauth2callback&
 response_type=code&
 client_id=client_id

Sau khi hoàn tất quy trình OAuth 2.0, bạn nên chuyển hướng đến http://localhost/oauth2callback. Thao tác này có thể gây ra lỗi 404 NOT FOUND trừ phi máy cục bộ của bạn phân phát tệp tại địa chỉ đó. Bước tiếp theo sẽ 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.

Bước 5: Trao đổi mã uỷ quyền để làm mới và mã thông báo truy cập

Sau khi nhận được mã uỷ quyền, máy chủ web có thể đổi mã uỷ quyền lấy mã truy cập.

1.199

Để đổi mã uỷ quyền lấy mã truy cập, hãy sử dụng phương thức authenticate:

$client->authenticate($_GET['code']);

Bạn có thể truy xuất mã truy cập bằng phương thức getAccessToken:

$access_token = $client->getAccessToken();

Python

Trên trang gọi lại, hãy dùng thư viện google-auth để xác minh phản hồi của máy chủ uỷ quyền. Sau đó, sử dụng phương thức flow.fetch_token để đổi mã uỷ quyền trong phản hồi đó lấy mã truy cập:

state = flask.session['state']
flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
    'client_secret.json',
    scopes=['https://www.googleapis.com/auth/yt-analytics.readonly'],
    state=state)
flow.redirect_uri = flask.url_for('oauth2callback', _external=True)

authorization_response = flask.request.url
flow.fetch_token(authorization_response=authorization_response)

# Store the credentials in the session.
# ACTION ITEM for developers:
#     Store user's access and refresh tokens in your data store if
#     incorporating this code into your real app.
credentials = flow.credentials
flask.session['credentials'] = {
    'token': credentials.token,
    'refresh_token': credentials.refresh_token,
    'token_uri': credentials.token_uri,
    'client_id': credentials.client_id,
    'client_secret': credentials.client_secret,
    'scopes': credentials.scopes}

Ruby

Trên trang gọi lại, hãy dùng thư viện googleauth để xác minh phản hồi của máy chủ uỷ quyền. Hãy sử dụng phương thức authorizer.handle_auth_callback_deferred để lưu mã uỷ quyền và chuyển hướng về URL đã yêu cầu uỷ quyền ban đầu. Điều này có thể trì hoãn quá trình trao đổi mã bằng cách tạm thời lưu trữ các kết quả trong phiên hoạt động của người dùng.

  target_url = Google::Auth::WebUserAuthorizer.handle_auth_callback_deferred(request)
  redirect target_url

Node.js

Để đổi mã uỷ quyền lấy mã truy cập, hãy sử dụng phương thức getToken:

const url = require('url');

// Receive the callback from Google's OAuth 2.0 server.
if (req.url.startsWith('/oauth2callback')) {
  // Handle the OAuth 2.0 server response
  let q = url.parse(req.url, true).query;

  // Get access and refresh tokens (if access_type is offline)
  let { tokens } = await oauth2Client.getToken(q.code);
  oauth2Client.setCredentials(tokens);
}

HTTP/REST

Để đổi mã uỷ quyền lấy mã truy cập, hãy gọi điểm cuối https://oauth2.googleapis.com/token và đặt các tham số sau:

Trường
client_id Mã ứng dụng khách lấy từ API Console Credentials page.
client_secret Mật khẩu ứng dụng khách lấy từ API Console Credentials page.
code Mã uỷ quyền được trả về từ yêu cầu ban đầu.
grant_type Như xác định trong thông số kỹ thuật của OAuth 2.0, giá trị của trường này phải được đặt thành authorization_code.
redirect_uri Một trong những URI chuyển hướng được liệt kê cho dự án của bạn trong API Console Credentials page của client_id đã cho.

Đoạn mã sau đây cho thấy một yêu cầu mẫu:

POST /token HTTP/1.1
Host: oauth2.googleapis.com
Content-Type: application/x-www-form-urlencoded

code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7&
client_id=your_client_id&
client_secret=your_client_secret&
redirect_uri=https%3A//oauth2.example.com/code&
grant_type=authorization_code

Google phản hồi yêu cầu này bằng cách trả về một đối tượng JSON chứa mã truy cập ngắn hạn và mã làm mới. Xin lưu ý rằng mã làm mới chỉ được trả về nếu ứng dụng của bạn đã đặt tham số access_type thành offline trong yêu cầu ban đầu đến máy chủ uỷ quyền của Google.

Phản hồi chứa các trường sau:

Trường
access_token Mã thông báo mà ứng dụng của bạn gửi để uỷ quyền cho một yêu cầu API của Google.
expires_in Thời gian hoạt động còn lại của mã truy cập tính bằng giây.
refresh_token Mã thông báo mà bạn có thể dùng để lấy mã truy cập mới. Mã làm mới có hiệu lực cho đến khi người dùng thu hồi quyền truy cập. Xin nhắc lại rằng trường này chỉ xuất hiện trong phản hồi này nếu bạn đặt tham số access_type thành offline trong yêu cầu ban đầu đến máy chủ uỷ quyền của Google.
scope Phạm vi truy cập mà access_token cấp được biểu thị dưới dạng danh sách các chuỗi được phân tách bằng dấu cách và phân biệt chữ hoa chữ thường.
token_type Loại mã thông báo được trả về. Hiện tại, giá trị của trường này luôn được đặt thành Bearer.

Đoạn mã sau đây cho thấy một câu trả lời mẫu:

{
  "access_token": "1/fFAGRNJru1FTz70BzhT3Zg",
  "expires_in": 3920,
  "token_type": "Bearer",
  "scope": "https://www.googleapis.com/auth/yt-analytics.readonly",
  "refresh_token": "1//xEoDL4iW3cxlI7yDbSRFYNG01kVKM2C-259HOF2aQbI"
}

Lỗi

Khi trao đổi mã uỷ quyền lấy mã truy cập, bạn có thể gặp phải lỗi sau thay vì phản hồi dự kiến. Bạn có thể xem danh sách các mã lỗi phổ biến và giải pháp dưới đây.

invalid_grant

Mã uỷ quyền đã cung cấp không hợp lệ hoặc có định dạng sai. Yêu cầu mã mới bằng cách khởi động lại quy trình OAuth để nhắc người dùng đồng ý lại.

Gọi API của Google

1.199

Sử dụng mã truy cập để gọi API Google bằng cách hoàn tất các bước sau:

  1. Nếu bạn cần áp dụng mã truy cập cho một đối tượng Google\Client mới (ví dụ: nếu bạn lưu trữ mã truy cập trong một phiên hoạt động của người dùng), hãy sử dụng phương thức setAccessToken:
    $client->setAccessToken($access_token);
  2. Tạo một đối tượng dịch vụ cho API mà bạn muốn gọi. Bạn tạo một đối tượng dịch vụ bằng cách cung cấp một đối tượng Google\Client được uỷ quyền cho hàm khởi tạo cho API mà bạn muốn gọi. Ví dụ: để gọi API YouTube Analytics:
    $youtube = new Google_Service_YouTubeAnalytics($client);
  3. Gửi yêu cầu đến dịch vụ API bằng cách sử dụng giao diện do đối tượng dịch vụ cung cấp. Ví dụ: để truy xuất báo cáo YouTube Analytics cho kênh của người dùng đã xác thực, hãy làm như sau:
    $report = $youtube->reports->query('channel==MINE', '2016-05-01', '2016-06-30', 'views');

Python

Sau khi nhận được mã truy cập, ứng dụng của bạn có thể sử dụng mã đó để uỷ quyền cho các yêu cầu API thay mặt cho một tài khoản người dùng hoặc tài khoản dịch vụ cụ thể. Sử dụng thông tin xác thực uỷ quyền dành riêng cho người dùng để tạo một đối tượng dịch vụ cho API mà bạn muốn gọi, sau đó sử dụng đối tượng đó để tạo các yêu cầu API được uỷ quyền.

  1. Tạo một đối tượng dịch vụ cho API mà bạn muốn gọi. Bạn tạo đối tượng dịch vụ bằng cách gọi phương thức build của thư viện googleapiclient.discovery với tên và phiên bản API cũng như thông tin đăng nhập của người dùng: Ví dụ: để gọi phiên bản 1 của API YouTube Analytics:
    from googleapiclient.discovery import build
    
    youtube = build('youtubeAnalytics', 'v1', credentials=credentials)
  2. Gửi yêu cầu đến dịch vụ API bằng cách sử dụng giao diện do đối tượng dịch vụ cung cấp. Ví dụ: để truy xuất báo cáo YouTube Analytics cho kênh của người dùng đã xác thực, hãy làm như sau:
    report = youtube.reports().query(ids='channel==MINE', start_date='2016-05-01', end_date='2016-06-30', metrics='views').execute()

Ruby

Sau khi nhận được mã truy cập, ứng dụng của bạn có thể dùng mã đó để gửi yêu cầu API thay mặt cho một tài khoản người dùng hoặc tài khoản dịch vụ cụ thể. Sử dụng thông tin xác thực uỷ quyền dành riêng cho người dùng để tạo một đối tượng dịch vụ cho API mà bạn muốn gọi, sau đó sử dụng đối tượng đó để tạo các yêu cầu API được uỷ quyền.

  1. Tạo một đối tượng dịch vụ cho API mà bạn muốn gọi. Ví dụ: để gọi phiên bản 1 của API YouTube Analytics:
    youtube = Google::Apis::YoutubeAnalyticsV1::YouTubeAnalyticsService.new
  2. Đặt thông tin xác thực trên dịch vụ:
    youtube.authorization = credentials
  3. Gửi yêu cầu đến dịch vụ API bằng cách sử dụng giao diện do đối tượng dịch vụ cung cấp. Ví dụ: để truy xuất báo cáo YouTube Analytics cho kênh của người dùng đã xác thực, hãy làm như sau:
    report = youtube.query_report('channel==MINE', '2016-05-01', '2016-06-30', 'views')

Ngoài ra, bạn có thể uỷ quyền theo từng phương thức bằng cách cung cấp tham số options cho một phương thức:

report = youtube.query_report('channel==MINE', '2016-05-01', '2016-06-30', 'views', options: { authorization: auth_client })

Node.js

Sau khi lấy mã truy cập và đặt mã đó thành đối tượng OAuth2, hãy sử dụng đối tượng này để gọi các API của Google. Ứng dụng của bạn có thể sử dụng mã thông báo đó để uỷ quyền cho các yêu cầu API thay mặt cho một tài khoản người dùng hoặc tài khoản dịch vụ cụ thể. Tạo một đối tượng dịch vụ cho API mà bạn muốn gọi.

const { google } = require('googleapis');

// Example of using Google Drive API to list filenames in user's Drive.
const drive = google.drive('v3');
drive.files.list({
  auth: oauth2Client,
  pageSize: 10,
  fields: 'nextPageToken, files(id, name)',
}, (err1, res1) => {
  if (err1) return console.log('The API returned an error: ' + err1);
  const files = res1.data.files;
  if (files.length) {
    console.log('Files:');
    files.map((file) => {
      console.log(`${file.name} (${file.id})`);
    });
  } else {
    console.log('No files found.');
  }
});

HTTP/REST

Sau khi ứng dụng của bạn nhận được mã truy cập, bạn có thể sử dụng mã thông báo này để thực hiện lệnh gọi đến một API Google thay mặt cho một tài khoản người dùng cụ thể 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 một yêu cầu gửi tới API bằng cách cung cấp tham số truy vấn access_token hoặc giá trị tiêu đề HTTP Authorization Bearer. Khi có thể, bạn nên sử dụng tiêu đề HTTP vì các chuỗi truy vấn thường hiển thị 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 lệnh gọi đến các API của Google (ví dụ: khi gọi API YouTube Analytics).

Xin lưu ý rằng API YouTube Analytics không hỗ trợ quy trình tài khoản dịch vụ. API Báo cáo YouTube 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ả các API của Google và xem phạm vi của các API đó tại Playground 2.0 của OAuth.

Ví dụ về HTTP GET

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

GET /youtube/analytics/v1/reports?ids=channel%3D%3DMINE&start-date=2016-05-01&end-date=2016-06-30&metrics=views HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer access_token

Dưới đây là lệnh gọi tới 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/analytics/v1/reports?access_token=access_token&ids=channel%3D%3DMINE&start-date=2016-05-01&end-date=2016-06-30&metrics=views

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/analytics/v1/reports?ids=channel%3D%3DMINE&start-date=2016-05-01&end-date=2016-06-30&metrics=views

Hoặc cách khác là lựa chọn tham số chuỗi truy vấn:

curl https://www.googleapis.com/youtube/analytics/v1/reports?access_token=access_token&ids=channel%3D%3DMINE&start-date=2016-05-01&end-date=2016-06-30&metrics=views

Ví dụ đầy đủ

Ví dụ sau in một đối tượng có định dạng JSON hiển thị dữ liệu lượt xem cho kênh YouTube của người dùng đã xác thực sau khi người dùng cho phép ứng dụng truy xuất báo cáo YouTube Analytics.

1.199

Cách chạy ví dụ này:

  1. Trong API Console, hãy thêm URL của máy cục bộ vào danh sách URL chuyển hướng. Ví dụ: thêm http://localhost:8080.
  2. Tạo một thư mục mới và đổi sang thư mục đó. Ví dụ:
    mkdir ~/php-oauth2-example
    cd ~/php-oauth2-example
  3. Cài đặt Thư viện ứng dụng API Google cho PHP bằng Composer:
    composer require google/apiclient:^2.10
  4. Tạo các tệp index.phpoauth2callback.php có nội dung bên dưới.
  5. Chạy ví dụ này với máy chủ web được định cấu hình để phân phát PHP. Nếu sử dụng phiên bản PHP 5.6 trở lên, bạn có thể dùng máy chủ web thử nghiệm tích hợp sẵn của PHP:
    php -S localhost:8080 ~/php-oauth2-example

index.php

<?php
require_once __DIR__.'/vendor/autoload.php';

session_start();

$client = new Google\Client();
$client->setAuthConfig('client_secrets.json');
$client->addScope(Google_Service_YouTubeAnalytics::YT_ANALYTICS_READONLY);

if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {
  $client->setAccessToken($_SESSION['access_token']);
  $youtube = new Google_Service_YouTubeAnalytics($client);
  $report = $youtube->reports->query('channel==MINE', '2016-05-01', '2016-06-30', 'views');
  echo json_encode($report);
} else {
  $redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php';
  header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}

oauth2callback.php

<?php
require_once __DIR__.'/vendor/autoload.php';

session_start();

$client = new Google\Client();
$client->setAuthConfigFile('client_secrets.json');
$client->setRedirectUri('http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php');
$client->addScope(Google_Service_YouTubeAnalytics::YT_ANALYTICS_READONLY);

if (! isset($_GET['code'])) {
  $auth_url = $client->createAuthUrl();
  header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
} else {
  $client->authenticate($_GET['code']);
  $_SESSION['access_token'] = $client->getAccessToken();
  $redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . '/';
  header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}

Python

Ví dụ này sử dụng khung Flask. API này chạy một ứng dụng web tại http://localhost:8080 cho phép bạn kiểm thử quy trình OAuth 2.0. Nếu truy cập vào URL đó, bạn sẽ thấy 4 đường liên kết:

  • Kiểm tra yêu cầu API: Đường liên kết này trỏ đến một trang cố gắng thực thi yêu cầu API mẫu. Nếu cần, thao tác này sẽ bắt đầu quy trình uỷ quyền. Nếu thành công, trang sẽ cho thấy phản hồi của API.
  • Kiểm tra trực tiếp quy trình xác thực: Đường liên kết này trỏ đến một trang cố gắng chuyển người dùng thông qua quy trình uỷ quyền. Ứng dụng yêu cầu quyền gửi các yêu cầu API được cho phép thay mặt người dùng.
  • Thu hồi thông tin xác thực hiện tại: Đường liên kết này trỏ đến một trang sẽ thu hồi các quyền mà người dùng đã cấp cho ứng dụng.
  • Xoá thông tin xác thực phiên hoạt động Flask: Đường liên kết này sẽ xoá thông tin xác thực uỷ quyền được lưu trữ trong phiên Flask. Điều này cho bạn biết điều gì sẽ xảy ra nếu người dùng đã cấp quyền cho ứng dụng của bạn cố thực thi yêu cầu API trong một phiên mới. Thao tác này cũng cho phép bạn xem phản hồi của API mà ứng dụng sẽ nhận được nếu người dùng thu hồi các quyền đã cấp cho ứng dụng và ứng dụng vẫn cố gắng uỷ quyền cho một yêu cầu bằng mã truy cập đã thu hồi.
# -*- coding: utf-8 -*-

import os
import flask
import requests

import google.oauth2.credentials
import google_auth_oauthlib.flow
import googleapiclient.discovery

# This variable specifies the name of a file that contains the OAuth 2.0
# information for this application, including its client_id and client_secret.
CLIENT_SECRETS_FILE = "client_secret.json"

# This OAuth 2.0 access scope allows for full read/write access to the
# authenticated user's account and requires requests to use an SSL connection.
SCOPES = ['https://www.googleapis.com/auth/yt-analytics.readonly']
API_SERVICE_NAME = 'youtubeAnalytics'
API_VERSION = 'v1'

app = flask.Flask(__name__)
# Note: A secret key is included in the sample so that it works.
# If you use this code in your application, replace this with a truly secret
# key. See https://flask.palletsprojects.com/quickstart/#sessions.
app.secret_key = 'REPLACE ME - this value is here as a placeholder.'


@app.route('/')
def index():
  return print_index_table()


@app.route('/test')
def test_api_request():
  if 'credentials' not in flask.session:
    return flask.redirect('authorize')

  # Load credentials from the session.
  credentials = google.oauth2.credentials.Credentials(
      **flask.session['credentials'])

  youtube = googleapiclient.discovery.build(
      API_SERVICE_NAME, API_VERSION, credentials=credentials)

  report = youtube.reports().query(ids='channel==MINE', start_date='2016-05-01', end_date='2016-06-30', metrics='views').execute()

  # Save credentials back to session in case access token was refreshed.
  # ACTION ITEM: In a production app, you likely want to save these
  #              credentials in a persistent database instead.
  flask.session['credentials'] = credentials_to_dict(credentials)

  return flask.jsonify(**report)


@app.route('/authorize')
def authorize():
  # Create flow instance to manage the OAuth 2.0 Authorization Grant Flow steps.
  flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
      CLIENT_SECRETS_FILE, scopes=SCOPES)

  # The URI created here must exactly match one of the authorized redirect URIs
  # for the OAuth 2.0 client, which you configured in the API Console. If this
  # value doesn't match an authorized URI, you will get a 'redirect_uri_mismatch'
  # error.
  flow.redirect_uri = flask.url_for('oauth2callback', _external=True)

  authorization_url, state = flow.authorization_url(
      # Enable offline access so that you can refresh an access token without
      # re-prompting the user for permission. Recommended for web server apps.
      access_type='offline',
      # Enable incremental authorization. Recommended as a best practice.
      include_granted_scopes='true')

  # Store the state so the callback can verify the auth server response.
  flask.session['state'] = state

  return flask.redirect(authorization_url)


@app.route('/oauth2callback')
def oauth2callback():
  # Specify the state when creating the flow in the callback so that it can
  # verified in the authorization server response.
  state = flask.session['state']

  flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
      CLIENT_SECRETS_FILE, scopes=SCOPES, state=state)
  flow.redirect_uri = flask.url_for('oauth2callback', _external=True)

  # Use the authorization server's response to fetch the OAuth 2.0 tokens.
  authorization_response = flask.request.url
  flow.fetch_token(authorization_response=authorization_response)

  # Store credentials in the session.
  # ACTION ITEM: In a production app, you likely want to save these
  #              credentials in a persistent database instead.
  credentials = flow.credentials
  flask.session['credentials'] = credentials_to_dict(credentials)

  return flask.redirect(flask.url_for('test_api_request'))


@app.route('/revoke')
def revoke():
  if 'credentials' not in flask.session:
    return ('You need to <a href="/authorize">authorize</a> before ' +
            'testing the code to revoke credentials.')

  credentials = google.oauth2.credentials.Credentials(
    **flask.session['credentials'])

  revoke = requests.post('https://oauth2.googleapis.com/revoke',
      params={'token': credentials.token},
      headers = {'content-type': 'application/x-www-form-urlencoded'})

  status_code = getattr(revoke, 'status_code')
  if status_code == 200:
    return('Credentials successfully revoked.' + print_index_table())
  else:
    return('An error occurred.' + print_index_table())


@app.route('/clear')
def clear_credentials():
  if 'credentials' in flask.session:
    del flask.session['credentials']
  return ('Credentials have been cleared.<br><br>' +
          print_index_table())


def credentials_to_dict(credentials):
  return {'token': credentials.token,
          'refresh_token': credentials.refresh_token,
          'token_uri': credentials.token_uri,
          'client_id': credentials.client_id,
          'client_secret': credentials.client_secret,
          'scopes': credentials.scopes}

def print_index_table():
  return ('<table>' +
          '<tr><td><a href="/test">Test an API request</a></td>' +
          '<td>Submit an API request and see a formatted JSON response. ' +
          '    Go through the authorization flow if there are no stored ' +
          '    credentials for the user.</td></tr>' +
          '<tr><td><a href="/authorize">Test the auth flow directly</a></td>' +
          '<td>Go directly to the authorization flow. If there are stored ' +
          '    credentials, you still might not be prompted to reauthorize ' +
          '    the application.</td></tr>' +
          '<tr><td><a href="/revoke">Revoke current credentials</a></td>' +
          '<td>Revoke the access token associated with the current user ' +
          '    session. After revoking credentials, if you go to the test ' +
          '    page, you should see an <code>invalid_grant</code> error.' +
          '</td></tr>' +
          '<tr><td><a href="/clear">Clear Flask session credentials</a></td>' +
          '<td>Clear the access token currently stored in the user session. ' +
          '    After clearing the token, if you <a href="/test">test the ' +
          '    API request</a> again, you should go back to the auth flow.' +
          '</td></tr></table>')


if __name__ == '__main__':
  # When running locally, disable OAuthlib's HTTPs verification.
  # ACTION ITEM for developers:
  #     When running in production *do not* leave this option enabled.
  os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1'

  # Specify a hostname and port that are set as a valid redirect URI
  # for your API project in the Google API Console.
  app.run('localhost', 8080, debug=True)

Ruby

Ví dụ này sử dụng khung Sinatra.

require 'google/apis/youtube_analytics_v1'
require 'sinatra'
require 'googleauth'
require 'googleauth/stores/redis_token_store'

configure do
  enable :sessions

  set :client_id, Google::Auth::ClientId.from_file('/path/to/client_secret.json')
  set :scope, Google::Apis::DriveV3::AUTH_DRIVE_METADATA_READONLY
  set :token_store, Google::Auth::Stores::RedisTokenStore.new(redis: Redis.new)
  set :authorizer, Google::Auth::WebUserAuthorizer.new(settings.client_id, settings.scope, settings.token_store, '/oauth2callback')
end

get '/' do
  user_id = settings.client_id.id
  credentials = settings.authorizer.get_credentials(user_id, request)
  if credentials.nil?
    redirect settings.authorizer.get_authorization_url(login_hint: user_id, request: request)
  end
  youtube = Google::Apis::YoutubeAnalyticsV1::YouTubeAnalyticsService.new
  report = youtube.query_report('channel==MINE', '2016-05-01', '2016-06-30', 'views', options: { authorization: auth_client })
  
  "<pre>#{JSON.pretty_generate(report.to_h)}</pre>"
end

get '/oauth2callback' do
  target_url = Google::Auth::WebUserAuthorizer.handle_auth_callback_deferred(request)
  redirect target_url
end

Node.js

Cách chạy ví dụ này:

  1. Trong API Console, hãy thêm URL của máy cục bộ vào danh sách URL chuyển hướng. Ví dụ: thêm http://localhost.
  2. Đảm bảo bạn đã cài đặt LTS bảo trì, LTS đang hoạt động hoặc bản phát hành Node.js hiện tại.
  3. Tạo một thư mục mới và đổi sang thư mục đó. Ví dụ:
    mkdir ~/nodejs-oauth2-example
    cd ~/nodejs-oauth2-example
  4. Install the Google API Client Library for Node.js using npm:
    npm install googleapis
  5. Tạo các tệp main.js có nội dung dưới đây.
  6. Chạy ví dụ:
    node .\main.js

main.js

const http = require('http');
const https = require('https');
const url = require('url');
const { google } = require('googleapis');

/**
 * To use OAuth2 authentication, we need access to a CLIENT_ID, CLIENT_SECRET, AND REDIRECT_URI.
 * To get these credentials for your application, visit
 * https://console.cloud.google.com/apis/credentials.
 */
const oauth2Client = new google.auth.OAuth2(
  YOUR_CLIENT_ID,
  YOUR_CLIENT_SECRET,
  YOUR_REDIRECT_URL
);

// Access scopes for read-only Drive activity.
const scopes = [
  'https://www.googleapis.com/auth/drive.metadata.readonly'
];

// Generate a url that asks permissions for the Drive activity scope
const authorizationUrl = oauth2Client.generateAuthUrl({
  // 'online' (default) or 'offline' (gets refresh_token)
  access_type: 'offline',
  /** Pass in the scopes array defined above.
    * Alternatively, if only one scope is needed, you can pass a scope URL as a string */
  scope: scopes,
  // Enable incremental authorization. Recommended as a best practice.
  include_granted_scopes: true
});

/* Global variable that stores user credential in this code example.
 * ACTION ITEM for developers:
 *   Store user's refresh token in your data store if
 *   incorporating this code into your real app.
 *   For more information on handling refresh tokens,
 *   see https://github.com/googleapis/google-api-nodejs-client#handling-refresh-tokens
 */
let userCredential = null;

async function main() {
  const server = http.createServer(async function (req, res) {
    // Example on redirecting user to Google's OAuth 2.0 server.
    if (req.url == '/') {
      res.writeHead(301, { "Location": authorizationUrl });
    }

    // Receive the callback from Google's OAuth 2.0 server.
    if (req.url.startsWith('/oauth2callback')) {
      // Handle the OAuth 2.0 server response
      let q = url.parse(req.url, true).query;

      if (q.error) { // An error response e.g. error=access_denied
        console.log('Error:' + q.error);
      } else { // Get access and refresh tokens (if access_type is offline)
        let { tokens } = await oauth2Client.getToken(q.code);
        oauth2Client.setCredentials(tokens);

        /** Save credential to the global variable in case access token was refreshed.
          * ACTION ITEM: In a production app, you likely want to save the refresh token
          *              in a secure persistent database instead. */
        userCredential = tokens;

        // Example of using Google Drive API to list filenames in user's Drive.
        const drive = google.drive('v3');
        drive.files.list({
          auth: oauth2Client,
          pageSize: 10,
          fields: 'nextPageToken, files(id, name)',
        }, (err1, res1) => {
          if (err1) return console.log('The API returned an error: ' + err1);
          const files = res1.data.files;
          if (files.length) {
            console.log('Files:');
            files.map((file) => {
              console.log(`${file.name} (${file.id})`);
            });
          } else {
            console.log('No files found.');
          }
        });
      }
    }

    // Example on revoking a token
    if (req.url == '/revoke') {
      // Build the string for the POST request
      let postData = "token=" + userCredential.access_token;

      // Options for POST request to Google's OAuth 2.0 server to revoke a token
      let postOptions = {
        host: 'oauth2.googleapis.com',
        port: '443',
        path: '/revoke',
        method: 'POST',
        headers: {
          'Content-Type': 'application/x-www-form-urlencoded',
          'Content-Length': Buffer.byteLength(postData)
        }
      };

      // Set up the request
      const postReq = https.request(postOptions, function (res) {
        res.setEncoding('utf8');
        res.on('data', d => {
          console.log('Response: ' + d);
        });
      });

      postReq.on('error', error => {
        console.log(error)
      });

      // Post the request with data
      postReq.write(postData);
      postReq.end();
    }
    res.end();
  }).listen(80);
}
main().catch(console.error);

HTTP/REST

Ví dụ dùng đoạn mã Python này sử dụng khung Flask và thư viện Requests (Yêu cầu) để minh hoạ luồng web OAuth 2.0. Bạn nên sử dụng Thư viện ứng dụng API của Google cho Python cho quy trình này. (Ví dụ trong thẻ Python có sử dụng thư viện ứng dụng.)

import json

import flask
import requests


app = flask.Flask(__name__)

CLIENT_ID = '123456789.apps.googleusercontent.com'
CLIENT_SECRET = 'abc123'  # Read from a file or environmental variable in a real app
SCOPE = 'https://www.googleapis.com/auth/yt-analytics.readonly'
REDIRECT_URI = 'http://example.com/oauth2callback'


@app.route('/')
def index():
  if 'credentials' not in flask.session:
    return flask.redirect(flask.url_for('oauth2callback'))
  credentials = json.loads(flask.session['credentials'])
  if credentials['expires_in'] <= 0:
    return flask.redirect(flask.url_for('oauth2callback'))
  else:
    headers = {'Authorization': 'Bearer {}'.format(credentials['access_token'])}
    req_uri = 'https://www.googleapis.com/youtube/analytics/v1/reports'
    r = requests.get(req_uri, headers=headers)
    return r.text


@app.route('/oauth2callback')
def oauth2callback():
  if 'code' not in flask.request.args:
    auth_uri = ('https://accounts.google.com/o/oauth2/v2/auth?response_type=code'
                '&client_id={}&redirect_uri={}&scope={}').format(CLIENT_ID, REDIRECT_URI, SCOPE)
    return flask.redirect(auth_uri)
  else:
    auth_code = flask.request.args.get('code')
    data = {'code': auth_code,
            'client_id': CLIENT_ID,
            'client_secret': CLIENT_SECRET,
            'redirect_uri': REDIRECT_URI,
            'grant_type': 'authorization_code'}
    r = requests.post('https://oauth2.googleapis.com/token', data=data)
    flask.session['credentials'] = r.text
    return flask.redirect(flask.url_for('index'))


if __name__ == '__main__':
  import uuid
  app.secret_key = str(uuid.uuid4())
  app.debug = False
  app.run()

Quy tắc xác thực URI chuyển hướng

Google áp dụng các quy tắc xác thực sau đây cho việc chuyển hướng URI nhằm giúp các nhà phát triển giữ an toàn cho ứng dụng của họ. URI chuyển hướng của bạn phải tuân thủ các quy tắc này. Vui lòng xem phần 3 của RFC 3986 để biết định nghĩa về miền, máy chủ lưu trữ, đường dẫn, truy vấn, giao thức và thông tin người dùng nêu dưới đây.

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

URI chuyển hướng phải dùng giao thức HTTPS, không phải HTTP thuần tuý. URI Localhost (bao gồm cả URI địa chỉ IP localhost) được miễn tuân theo quy tắc này.

Máy chủ lưu trữ

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

Miền
  • Miền cấp cao nhất của máy chủ (Miền cấp cao nhất) phải thuộc danh sách hậu tố công khai.
  • Miền máy chủ không được là “googleusercontent.com”.
  • URI chuyển hướng không được chứa miền URLtóm tắt (ví dụ: goo.gl) trừ phi ứng dụng sở hữu miền. Hơn nữa, nếu một ứng dụng sở hữu miền rút ngắn chọn chuyển hướng đến miền đó, thì URI chuyển hướng đó phải chứa “/google-callback/” trong đường dẫn hoặc kết thúc bằng “/google-callback”.
  • Thông tin người dùng

    URI chuyển hướng không được chứa thành phần phụ thông tin người dùng.

    Đường dẫn

    URI chuyển hướng không được chứa đường dẫn truyền tải (còn gọi là theo dõi ngược thư mục), được biểu thị bằng “/..” hoặc “\..” hoặc mã hoá URL của chúng.

    Cụm từ tìm kiếm

    URI chuyển hướng không được chứa lệnh chuyển hướng mở.

    Mảnh

    URI chuyển hướng không thể chứa thành phần mảnh.

    Ký tự URI chuyển hướng 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 phương thức mã hoá phần trăm không tuân theo dạng mã hoá URL là ký hiệu phần trăm theo sau là hai chữ số thập lục phân)
    • Ký tự rỗng (ký tự NULL được 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 quyền truy cập vào các tài nguyên được xác định theo phạm vi. Đây được xem 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 các tài nguyên vào thời điểm bạn cần. Để thực hiện điều đó, máy chủ uỷ quyền của Google có hỗ trợ tính năng uỷ quyền gia tăng. Tính năng này cho phép bạn yêu cầu phạm vi khi cần thiết và nếu người dùng cấp quyền cho phạm vi mới, hãy trả về một mã uỷ quyền có thể đổi lấy 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 truy xuất các báo cáo YouTube Analytics, một số báo cáo trong số đó là các báo cáo tiền tệ yêu cầu quyền truy cập vào một phạm vi bổ sung không cần thiết cho các báo cáo khác. Trong trường hợp này, tại thời điểm đăng nhập, ứng dụng có thể chỉ yêu cầu quyền truy cập vào phạm vi https://www.googleapis.com/auth/yt-analytics.readonly. Tuy nhiên, nếu người dùng cố gắng truy xuất một báo cáo tiền tệ, thì ứng dụng cũng có thể yêu cầu quyền truy cập vào phạm vi https://www.googleapis.com/auth/yt-analytics-monetary.readonly.

    Để triển khai việc uỷ quyền gia tăng, bạn cần hoàn tất quy trình yêu cầu mã truy cập thông thường, nhưng hãy đảm bảo rằng yêu cầu uỷ quyền bao gồm các phạm vi đã cấp trướ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ã truy cập.

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

    • Bạn có thể dùng mã thông báo để 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 cuộn vào hoạt động uỷ quyền kết hợp mới.
    • Khi bạn dùng mã làm mới cho uỷ quyền kết hợp để lấy mã truy cập, mã truy cập này đại diện cho 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.
    • Hoạt động uỷ quyền kết hợp bao gồm tất cả phạm vi mà người dùng đã cấp cho dự án API ngay cả khi các ứng dụng khác yêu cầu cấp quyền. 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 dành cho máy tính, sau đó cấp một phạm vi khác cho chính ứng dụng đó thông qua ứng dụng dành cho thiết bị di động, thì việc 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 lệnh uỷ quyền kết hợp, thì quyền truy cập vào tất cả phạm vi của quyền đó thay mặt cho người dùng được liên kết sẽ bị thu hồi đồng thời.

    Mã mẫu dành riêng cho ngôn ngữ trong Bước 1: Đặt tham số uỷ quyền và URL chuyển hướng HTTP/REST mẫu trong Bước 2: Chuyển hướng đến máy chủ OAuth 2.0 của Google đều sử dụng tính năng uỷ quyền gia tăng. Các mã mẫu bên dưới cũng cho thấy mã mà bạn cần thêm để sử dụng tính năng uỷ quyền gia tăng.

    1.199

    $client->setIncludeGrantedScopes(true);

    Python

    Trong Python, hãy đặt đối số từ khoá include_granted_scopes thành true để đảm bảo rằng yêu cầu uỷ quyền bao gồm các phạm vi đã cấp trước đó. Rất có thể include_granted_scopes sẽ không phải là đối số từ khoá duy nhất mà bạn đặt, như trong ví dụ dưới đây.

    authorization_url, state = flow.authorization_url(
        # Enable offline access so that you can refresh an access token without
        # re-prompting the user for permission. Recommended for web server apps.
        access_type='offline',
        # Enable incremental authorization. Recommended as a best practice.
        include_granted_scopes='true')

    Ruby

    auth_client.update!(
      :additional_parameters => {"include_granted_scopes" => "true"}
    )

    Node.js

    const authorizationUrl = oauth2Client.generateAuthUrl({
      // 'online' (default) or 'offline' (gets refresh_token)
      access_type: 'offline',
      /** Pass in the scopes array defined above.
        * Alternatively, if only one scope is needed, you can pass a scope URL as a string */
      scope: scopes,
      // Enable incremental authorization. Recommended as a best practice.
      include_granted_scopes: true
    });
    

    HTTP/REST

    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 cùng với mọi quyền truy cập khác mà người dùng đã cấp cho ứng dụng.

    GET https://accounts.google.com/o/oauth2/v2/auth?
      scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fyt-analytics.readonly&
      access_type=offline&
      state=security_token%3D138rk%3Btarget_url%3Dhttp...index&
      redirect_uri=http%3A%2F%2Flocalhost%2Foauth2callback&
      response_type=code&
      client_id=client_id&
      include_granted_scopes=true
    
          

    Refreshing an access token (offline access)

    Access tokens periodically expire and become invalid credentials for a related API request. You can refresh an access token without prompting the user for permission (including when the user is not present) if you requested offline access to the scopes associated with the token.

    • If you use a Google API Client Library, the client object refreshes the access token as needed as long as you configure that object for offline access.
    • If you are not using a client library, you need to set the access_type HTTP query parameter to offline when redirecting the user to Google's OAuth 2.0 server. In that case, Google's authorization server returns a refresh token when you exchange an authorization code for an access token. Then, if the access token expires (or at any other time), you can use a refresh token to obtain a new access token.

    Requesting offline access is a requirement for any application that needs to access a Google API when the user is not present. For example, an app that performs backup services or executes actions at predetermined times needs to be able to refresh its access token when the user is not present. The default style of access is called online.

    Server-side web applications, installed applications, and devices all obtain refresh tokens during the authorization process. Refresh tokens are not typically used in client-side (JavaScript) web applications.

    PHP

    If your application needs offline access to a Google API, set the API client's access type to offline:

    $client->setAccessType("offline");

    Sau khi người dùng cấp quyền truy cập ngoại tuyến vào các phạm vi được yêu cầu, bạn có thể tiếp tục sử dụng ứng dụng API để thay người dùng truy cập vào các API của Google khi người dùng không kết nối mạng. Đối tượng ứng dụng khách sẽ làm mới mã truy cập nếu cần.

    Python

    Trong Python, hãy đặt đối số từ khoá access_type thành offline để đảm bảo rằng bạn có thể làm mới mã truy cập mà không cần phải nhắc lại người dùng để yêu cầu cấp quyền. Rất có thể access_type sẽ không phải là đối số từ khoá duy nhất mà bạn đặt, như trong ví dụ bên dưới.

    authorization_url, state = flow.authorization_url(
        # Enable offline access so that you can refresh an access token without
        # re-prompting the user for permission. Recommended for web server apps.
        access_type='offline',
        # Enable incremental authorization. Recommended as a best practice.
        include_granted_scopes='true')

    Sau khi người dùng cấp quyền truy cập ngoại tuyến vào các phạm vi được yêu cầu, bạn có thể tiếp tục sử dụng ứng dụng API để thay người dùng truy cập vào các API của Google khi người dùng không kết nối mạng. Đối tượng ứng dụng khách sẽ làm mới mã truy cập nếu cần.

    Ruby

    Nếu ứng dụng của bạn cần quyền truy cập ngoại tuyến vào một API của Google, hãy đặt loại quyền truy cập của ứng dụng API thành offline:

    auth_client.update!(
      :additional_parameters => {"access_type" => "offline"}
    )

    Sau khi người dùng cấp quyền truy cập ngoại tuyến vào các phạm vi được yêu cầu, bạn có thể tiếp tục sử dụng ứng dụng API để thay người dùng truy cập vào các API của Google khi người dùng không kết nối mạng. Đối tượng ứng dụng khách sẽ làm mới mã truy cập nếu cần.

    Node.js

    Nếu ứng dụng của bạn cần quyền truy cập ngoại tuyến vào một API của Google, hãy đặt loại quyền truy cập của ứng dụng API thành offline:

    const authorizationUrl = oauth2Client.generateAuthUrl({
      // 'online' (default) or 'offline' (gets refresh_token)
      access_type: 'offline',
      /** Pass in the scopes array defined above.
        * Alternatively, if only one scope is needed, you can pass a scope URL as a string */
      scope: scopes,
      // Enable incremental authorization. Recommended as a best practice.
      include_granted_scopes: true
    });
    

    Sau khi người dùng cấp quyền truy cập ngoại tuyến vào các phạm vi được yêu cầu, bạn có thể tiếp tục sử dụng ứng dụng API để thay người dùng truy cập vào các API của Google khi người dùng không kết nối mạng. Đối tượng ứng dụng khách sẽ làm mới mã truy cập nếu cần.

    Mã truy cập sẽ hết hạn. Thư viện này sẽ tự động dùng mã làm mới để lấy mã truy cập mới nếu mã này sắp hết hạn. Một cách dễ dàng để đảm bảo bạn luôn lưu trữ các mã thông báo gần đây nhất là sử dụng sự kiện mã thông báo:

    oauth2Client.on('tokens', (tokens) => {
      if (tokens.refresh_token) {
        // store the refresh_token in your secure persistent database
        console.log(tokens.refresh_token);
      }
      console.log(tokens.access_token);
    });

    Sự kiện mã thông báo này chỉ xảy ra trong lần uỷ quyền đầu tiên và bạn cần thiết lập access_type thành offline khi gọi phương thức generateAuthUrl để nhận mã làm mới. Nếu đã cấp cho ứng dụng các quyền cần thiết mà không đặt ra các điều kiện ràng buộc thích hợp để nhận mã làm mới, thì bạn sẽ phải uỷ quyền lại cho ứng dụng nhận mã làm mới.

    Để đặt refresh_token vào lúc khác, bạn có thể sử dụng phương thức setCredentials:

    oauth2Client.setCredentials({
      refresh_token: `STORED_REFRESH_TOKEN`
    });
    

    Sau khi ứng dụng có mã làm mới, mã truy cập sẽ được thu thập và tự động làm mới trong lệnh gọi tiếp theo đến API.

    HTTP/REST

    Để làm mới mã truy cập, ứng dụng của bạn sẽ gửi yêu cầu POST HTTPS đến máy chủ uỷ quyền của Google (https://oauth2.googleapis.com/token) bao gồm các thông số sau:

    Trường
    client_id Mã ứng dụng khách lấy từ API Console.
    client_secret Mật khẩu ứng dụng khách lấy từ API Console.
    grant_type Như xác định trong thông số kỹ thuật của OAuth 2.0, giá trị của trường này phải được đặt thành refresh_token.
    refresh_token Mã làm mới được trả về từ quá trình trao đổi mã uỷ quyền.

    Đoạn mã sau đây cho thấy một yêu cầu mẫu:

    POST /token HTTP/1.1
    Host: oauth2.googleapis.com
    Content-Type: application/x-www-form-urlencoded
    
    client_id=your_client_id&
    client_secret=your_client_secret&
    refresh_token=refresh_token&
    grant_type=refresh_token

    Miễn là người dùng chưa thu hồi quyền truy cập đã cấp cho ứng dụng, máy chủ mã thông báo sẽ trả về một đối tượng JSON chứa mã truy cập mới. Đoạn mã sau đây cho thấy một phản hồi mẫu:

    {
      "access_token": "1/fFAGRNJru1FTz70BzhT3Zg",
      "expires_in": 3920,
      "scope": "https://www.googleapis.com/auth/drive.metadata.readonly",
      "token_type": "Bearer"
    }

    Xin lưu ý rằng có một giới hạn về số lượng mã thông báo làm mới sẽ được phát hành; một giới hạn cho mỗi tổ hợp ứng dụng/người dùng và một giới hạn khác cho mỗi người dùng trên tất cả các ứng dụng. Bạn nên lưu mã thông báo làm mới vào bộ nhớ dài hạn và tiếp tục sử dụng các mã này cho đến khi các mã này vẫn hợp lệ. Nếu yêu cầu quá nhiều mã làm mới, thì ứng dụng có thể gặp phải các giới hạn này. Trong trường hợp đó, những mã làm mới cũ hơn sẽ ngừng hoạt động.

    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 ứ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 tài liệu hỗ trợ về Xoá quyền truy cập vào trang web hoặc ứng dụng trong phần 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 đóng vai trò quan trọng trong những 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 cả yêu cầu API để đảm bảo các quyền đã cấp trước đó cho ứng dụng sẽ bị xoá.

    1.199

    Để thu hồi mã thông báo theo phương thức lập trình, hãy gọi revokeToken():

    $client->revokeToken();

    Python

    Để thu hồi một mã thông báo bằng phương thức lập trình, hãy gửi yêu cầu tới https://oauth2.googleapis.com/revoke. Yêu cầu này bao gồm mã thông báo dưới dạng tham số và thiết lập tiêu đề Content-Type:

    requests.post('https://oauth2.googleapis.com/revoke',
        params={'token': credentials.token},
        headers = {'content-type': 'application/x-www-form-urlencoded'})

    Ruby

    Để thu hồi mã thông báo theo phương thức lập trình, hãy gửi một yêu cầu HTTP đến điểm cuối oauth2.revoke:

    uri = URI('https://oauth2.googleapis.com/revoke')
    response = Net::HTTP.post_form(uri, 'token' => auth_client.access_token)
    

    Mã thông báo này có thể là mã truy cập hoặc mã làm mới. Nếu mã thông báo này 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 quy trình thu hồi được xử lý thành công, thì mã trạng thái của phản hồi sẽ là 200. Đối với các điều kiện lỗi, mã trạng thái 400 sẽ được trả về cùng với mã lỗi.

    Node.js

    Để thu hồi mã thông báo theo phương thức lập trình, hãy gửi một yêu cầu POST qua HTTPS đến điểm cuối của /revoke:

    const https = require('https');
    
    // Build the string for the POST request
    let postData = "token=" + userCredential.access_token;
    
    // Options for POST request to Google's OAuth 2.0 server to revoke a token
    let postOptions = {
      host: 'oauth2.googleapis.com',
      port: '443',
      path: '/revoke',
      method: 'POST',
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
        'Content-Length': Buffer.byteLength(postData)
      }
    };
    
    // Set up the request
    const postReq = https.request(postOptions, function (res) {
      res.setEncoding('utf8');
      res.on('data', d => {
        console.log('Response: ' + d);
      });
    });
    
    postReq.on('error', error => {
      console.log(error)
    });
    
    // Post the request with data
    postReq.write(postData);
    postReq.end();
    

    Tham số mã thông báo có thể là mã truy cập hoặc mã làm mới. Nếu mã thông báo này 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 quy trình thu hồi được xử lý thành công, thì mã trạng thái của phản hồi sẽ là 200. Đối với các điều kiện lỗi, mã trạng thái 400 sẽ được trả về cùng với mã lỗi.

    HTTP/REST

    Để thu hồi một mã thông báo theo phương thức lập trình, ứng dụng sẽ gửi yêu cầu đến https://oauth2.googleapis.com/revoke và đưa mã thông báo đó vào dưới dạng một 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 này có thể là mã truy cập hoặc mã làm mới. Nếu mã thông báo này 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 yêu cầu 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.