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

Sử dụng bộ sưu tập để sắp xếp ngăn nắp các trang Lưu và phân loại nội dung dựa trên lựa chọn ưu tiên của bạn.

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 OAuth 2.0 nhằm truy cập vào các API của Google.

OAuth 2.0 cho phép người dùng chia sẻ dữ liệu cụ thể với một ứng dụng, đồng thời giữ tên người dùng, mật khẩu và thông tin khác của họ ở chế độ riêng tư. Ví dụ: một ứng dụng có thể sử dụng OAuth 2.0 để có quyền yêu cầu người dùng lưu trữ tệp trong Google Drive.

Quy trình OAuth 2.0 này dành riêng cho việc ủy quyền cho người dùng. API này được thiết kế dành cho các ứng dụng có thể lưu trữ thông tin mật và duy trì trạng thái. Ứng dụng máy chủ web được ủy quyền thích hợp có thể truy cập vào 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 xuyên sử dụng tài khoản dịch vụ để cấp phép cho các yêu cầu API, đặc biệt là khi gọi API Cloud để truy cập vào dữ liệu dựa trên dự án thay vì dữ liệu dành riêng cho người dùng. Các ứ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.

Thư viện ứng dụng

Các ví dụ về 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 cấp phép OAuth 2.0. Để chạy các mã mẫu, trước tiên bạn phải cài đặt thư viện ứng dụng ngôn ngữ cho bạn.

Khi bạn sử dụng Thư viện ứng dụng API của Google để xử lý luồng OAuth 2.0 của ứng dụng, thư viện ứng dụng khách sẽ thực hiện nhiều thao tác mà ứng dụng cần phải tự xử lý. Ví dụ: ứng dụng này xác định thời điểm ứng dụng có thể sử dụng hoặc làm mới mã thông báo truy cập đã lưu trữ, cũng như thời điểm ứng dụng phải lấy lại 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 trình xử lý chuyển hướng để trao đổi mã ủy quyền cho mã thông báo 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ủ có sẵn cho các ngôn ngữ sau:

Đ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. API Library Danh sách này liệt kê tất cả các API hiện có, được nhóm theo nhóm sản phẩm và mức độ phổ biến. Nếu API bạn muốn bật không hiển thị trong danh sách, hãy sử dụng tính năng tìm kiếm để tìm API đó hoặc nhấp vào Xem tất cả trong nhóm sản phẩm chứa API đó.
  4. Chọn API bạn muốn bật, sau đó nhấp vào nút Bật.
  5. If prompted, enable billing.
  6. If prompted, read and accept the API's Terms of Service.

Tạo thông tin uỷ quyền

Bất kỳ ứng dụng nào sử dụng OAuth 2.0 để truy cập API của Google đều phải có thông tin xác thực ủy quyền để xác định ứng dụng đó với máy chủ OAuth 2.0 của Google. Các bước sau đây 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ó thể 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. Điền vào biểu mẫu rồi nhấp vào Tạo. Các ứng dụng dùng khung và ngôn ngữ như PHP, Java, Python, Ruby và .NET phải chỉ định URI chuyển hướng được ủy quyền. URI chuyển hướng là các đ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ủ 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, hãy lưu ý rằng tất 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 hiển thị mã uỷ quyền cho các tài nguyên khác trên trang.

Sau khi tạo thông tin xác thực, hãy tải tệp client_ney.json xuống từ API Console. Lưu trữ an toàn tệp này ở 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 cần thiết, đồng thời cho phép người dùng kiểm soát số 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ố lượng phạm vi được yêu cầu và khả năng thu thập sự đồng ý của người dùng.

Trước khi bắt đầu triển khai 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 phạm vi uỷ quyền thông qua một quy trình ủy quyền gia tăng, trong đó ứng dụng của bạn yêu cầu quyền truy cập vào dữ liệu người dùng trong ngữ cảnh. Phương pháp hay nhất này giúp người dùng hiểu rõ hơn lý do ứng dụng của bạn cần quyền truy cập mà ứng dụng đó yêu cầu.

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 theo 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 những thư viện ứng dụng API, hãy xem thêm các yêu cầu dành riêng cho từng ngôn ngữ bên dưới.

PHP

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

  • PHP 5.6 trở lên có 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 PHP cho API:

    composer require google/apiclient:^2.10

Python

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

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

Ruby

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

  • Ruby 2.2.2 trở lên
  • Thư viện ứng dụng API của Google cho Ruby:

    gem install google-api-client
  • 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 cần:

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

    npm install googleapis

HTTP/REST

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

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 sẽ 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 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 yêu cầu API.

Bước 1: Đặt thông số cấp phép

Bước đầu tiên là tạo yêu cầu uỷ quyền. Yêu cầu đó đặt các tham số xác định ứng dụng 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 khách của Google để xác thực và uỷ quyền OAuth 2.0, bạn sẽ tạo và định cấu hình một đối tượng xác định các tham số này.
  • Nếu gọi trực tiếp điểm cuối Google OAuth 2.0, bạn sẽ tạo một URL và đặt các tham số trên URL đó.

Các thẻ dưới đây xác định các thông số uỷ quyền được hỗ trợ cho các ứng dụng máy chủ web. Các ví dụ về 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 ủy quyền để định cấu hình một đối tượng đặt các tham số đó.

PHP

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

Đối tượng đó sử dụng thông tin trong tệp client_bí.json của bạn để xác định ứng dụng. (Xem tạo thông tin xác thực ủy quyền để biết thêm về tệp đó.) Đối tượng này cũng xác định phạm vi mà ứng dụng của bạn đang yêu cầu quyền truy cập và URL tới đ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, mã này đặt các tham số access_typeinclude_granted_scopes (không bắt buộc).

Ví dụ: mã này yêu cầu quyền truy cập chỉ đọc, ngoại tuyến vào Google Drive của người dùng:

$client = new Google\Client();
$client->setAuthConfig('client_secret.json');
$client->addScope(Google\Service\Drive::DRIVE_METADATA_READONLY);
$client->setRedirectUri('http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php');
// 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');
// Using "consent" ensures that your application always receives a refresh token.
// If you are not using offline access, you can omit this.
$client->setApprovalPrompt('consent');
$client->setIncludeGrantedScopes(true);   // incremental auth

Yêu cầu chỉ định thông tin sau:

Các tham 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 Credentials page API Console.

Trong PHP, hãy gọi hàm setAuthConfig để tải thông tin xác thực ủy quyền từ tệp client_bí.json.

$client = new Google\Client();
$client->setAuthConfig('client_secret.json');
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 cấp phép. Giá trị phải khớp hoàn toàn với một trong các URI chuyển hướng đã được ủy quyền cho ứng dụng OAuth 2.0 mà bạn đã thiết lập trong ứng dụng khách API Console Credentials page. Nếu giá trị này không khớp với URI chuyển hướng được ủy quyền cho client_id được cung cấp, bạn sẽ gặp lỗi redirect_uri_mismatch.

Lưu ý rằng giao thức http, https và dấu gạch chéo ( # 39; / ') đều phải khớp.

Để đặt giá trị này trong PHP, hãy gọi hàm setRedirectUri. Xin lưu ý rằng bạn phải chỉ định một URI chuyển hướng hợp lệ cho client_id được cung cấp.

$client->setRedirectUri('https://oauth2.example.com/code');
scope Bắt buộc

Danh sách phạm vi được phân tách bằng dấu cách để xác định 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. Những giá trị này thông báo cho màn hình về sự đồ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 cần thiết, đồng thời cho phép người dùng kiểm soát số lượng quyền truy cập mà họ cấp vào ứ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 thu thập sự đồng ý của người dùng.

Để đặt giá trị này trong PHP, hãy gọi hàm addScope:

$client->addScope(Google\Service\Drive::DRIVE_METADATA_READONLY);

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

access_type Nên

Cho biết ứng dụng của bạn có thể làm mới mã thông báo truy cập khi người dùng không có mặt tại 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.

Đặt giá trị thành offline nếu ứng dụng của bạn cần làm mới mã thông báo 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ã thông báo 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ột mã làm mới mã truy cập trong lần đầu tiên ứng dụng của bạn trao đổi mã uỷ quyền cho mã thông báo.

Để đặt giá trị này trong PHP, hãy gọi hàm setAccessType:

$client->setAccessType('offline');
state Nên

Chỉ định bất kỳ giá trị chuỗi nào mà ứng dụng sử dụng để duy trì trạng thái giữa yêu cầu ủy quyền và phản hồi của máy chủ ủy quyền. Máy chủ 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 quyền truy cập của ứng dụng.

Bạn có thể sử dụng thông 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 giả mạo yêu cầu trên nhiều trang web. Vì redirect_uri của bạn có thể đoán được, nên việc sử dụng giá trị state có thể giúp đảm bảo rằng kết nối đến là kết quả của 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 nắm bắt trạng thái của ứng dụng, 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, qua đó bảo vệ khỏ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.

Để đặt giá trị này trong PHP, hãy gọi hàm setState:

$client->setState($sample_passthrough_value);
include_granted_scopes Tùy chọn

Cho phép các ứng dụng sử dụng tính năng ủy 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ị thông số này thành true và yêu cầu cấp quyền được cấp, thì mã thông báo truy cập mới cũng sẽ bao gồm mọi phạm vi mà người dùng đã cấp quyền truy cập vào ứng dụng trước đó. Hãy xem phần ủy quyền gia tăng để biết ví dụ.

Để đặt giá trị này trong PHP, hãy gọi hàm setIncludeGrantedScopes:

$client->setIncludeGrantedScopes(true);
login_hint Tùy chọn

Nếu biết người dùng nào đang cố xác thực, ứ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 hóa luồng đă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 lần thích hợp.

Đặt giá trị thông 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.

Để đặt giá trị này trong PHP, hãy gọi hàm setLoginHint:

$client->setLoginHint('None');
prompt Tùy chọn

Danh sách lời nhắc đượ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 thông số này, thì người dùng sẽ chỉ được nhắc ở lần đầu tiên dự án của bạn yêu cầu quyền truy cập. Hãy xem bài viết Nhắc người dùng đồng ý lại để biết thêm thông tin.

Để đặt giá trị này trong PHP, hãy gọi hàm setApprovalPrompt:

$client->setApprovalPrompt('consent');

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

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

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

Ví dụ: mã này yêu cầu quyền truy cập chỉ đọc, ngoại tuyến vào Google Drive của người dùng:

import google.oauth2.credentials
import google_auth_oauthlib.flow

# Use the client_secret.json file to identify the application requesting
# authorization. The client ID (from that file) and access scopes are required.
flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
    'client_secret.json',
    scopes=['https://www.googleapis.com/auth/drive.metadata.readonly'])

# 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(
    # 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')

Yêu cầu chỉ định thông tin sau:

Các tham 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 Credentials page API Console.

Trong Python, hãy gọi phương thức from_client_secrets_file để truy xuất mã ứng dụng từ tệp client_bí.json. (Bạn cũng có thể sử dụng phương thức from_client_config để truyền cấu hình máy khách như khi xuất hiện ban đầu trong tệp bí mật của ứng dụng nhưng không truy cập vào tệp đó.)

flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
    'client_secret.json',
    scopes=['https://www.googleapis.com/auth/drive.metadata.readonly'])
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 cấp phép. Giá trị phải khớp hoàn toàn với một trong các URI chuyển hướng đã được ủy quyền cho ứng dụng OAuth 2.0 mà bạn đã thiết lập trong ứng dụng khách API Console Credentials page. Nếu giá trị này không khớp với URI chuyển hướng được ủy quyền cho client_id được cung cấp, bạn sẽ gặp lỗi redirect_uri_mismatch.

Lưu ý rằng giao thức http, https và dấu gạch chéo ( # 39; / ') đều phải khớp.

Để đặt giá trị này trong Python, hãy đặt thuộc tính redirect_uri của đối tượng flow:

flow.redirect_uri = 'https://oauth2.example.com/code'
scope Bắt buộc

Danh sách phạm vi xác định tài nguyên mà ứng dụng của bạn có thể thay mặt bạn truy cập. Những giá trị này thông báo cho màn hình về sự đồ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 cần thiết, đồng thời cho phép người dùng kiểm soát số lượng quyền truy cập mà họ cấp vào ứ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 thu thập sự đồng ý của người dùng.

Trong Python, hãy sử dụng cùng một phương thức mà bạn dùng để đặt client_id để chỉ định danh sách phạm vi.

flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
    'client_secret.json',
    scopes=['https://www.googleapis.com/auth/drive.metadata.readonly'])

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

access_type Nên

Cho biết ứng dụng của bạn có thể làm mới mã thông báo truy cập khi người dùng không có mặt tại 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.

Đặt giá trị thành offline nếu ứng dụng của bạn cần làm mới mã thông báo 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ã thông báo 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ột mã làm mới mã truy cập trong lần đầu tiên ứng dụng của bạn trao đổi mã uỷ quyền cho mã thông báo.

Trong Python, hãy đặt tham số access_type bằng cách chỉ định access_type làm đối số từ khoá khi gọi phương thức flow.authorization_url:

authorization_url, state = flow.authorization_url(
    access_type='offline',
    include_granted_scopes='true')
state Nên

Chỉ định bất kỳ giá trị chuỗi nào mà ứng dụng sử dụng để duy trì trạng thái giữa yêu cầu ủy quyền và phản hồi của máy chủ ủy quyền. Máy chủ 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 quyền truy cập của ứng dụng.

Bạn có thể sử dụng thông 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 giả mạo yêu cầu trên nhiều trang web. Vì redirect_uri của bạn có thể đoán được, nên việc sử dụng giá trị state có thể giúp đảm bảo rằng kết nối đến là kết quả của 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 nắm bắt trạng thái của ứng dụng, 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, qua đó bảo vệ khỏ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.

Trong Python, hãy đặt tham số state bằng cách chỉ định state làm đối số từ khoá khi gọi phương thức flow.authorization_url:

authorization_url, state = flow.authorization_url(
    access_type='offline',
    state=sample_passthrough_value,
    include_granted_scopes='true')
include_granted_scopes Tùy chọn

Cho phép các ứng dụng sử dụng tính năng ủy 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ị thông số này thành true và yêu cầu cấp quyền được cấp, thì mã thông báo truy cập mới cũng sẽ bao gồm mọi phạm vi mà người dùng đã cấp quyền truy cập vào ứng dụng trước đó. Hãy xem phần ủy quyền gia tăng để biết ví dụ.

Trong Python, hãy đặt tham số include_granted_scopes bằng cách chỉ định include_granted_scopes làm đối số từ khoá khi gọi phương thức flow.authorization_url:

authorization_url, state = flow.authorization_url(
    access_type='offline',
    include_granted_scopes='true')
login_hint Tùy chọn

Nếu biết người dùng nào đang cố xác thực, ứ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 hóa luồng đă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 lần thích hợp.

Đặt giá trị thông 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.

Trong Python, hãy đặt tham số login_hint bằng cách chỉ định login_hint làm đối số từ khoá khi gọi phương thức flow.authorization_url:

authorization_url, state = flow.authorization_url(
    access_type='offline',
    login_hint='None',
    include_granted_scopes='true')
prompt Tùy chọn

Danh sách lời nhắc đượ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 thông số này, thì người dùng sẽ chỉ được nhắc ở lần đầu tiên dự án của bạn yêu cầu quyền truy cập. Hãy xem bài viết Nhắc người dùng đồng ý lại để biết thêm thông tin.

Trong Python, hãy đặt tham số prompt bằng cách chỉ định prompt làm đối số từ khoá khi gọi phương thức flow.authorization_url:

authorization_url, state = flow.authorization_url(
      access_type='offline',
      prompt='consent',
      include_granted_scopes='true')

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

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

Ruby

Sử dụng tệp client_bís.json mà bạn đã tạo để định cấu hình đối tượng ứng dụng trong ứng dụng. Khi định cấu hình đố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 dẫn đế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ụ: mã này yêu cầu quyền truy cập chỉ đọc, ngoại tuyến vào Google Drive của người dùng:

require 'google/apis/drive_v2'
require 'google/api_client/client_secrets'

client_secrets = Google::APIClient::ClientSecrets.load
auth_client = client_secrets.to_authorization
auth_client.update!(
  :scope => 'https://www.googleapis.com/auth/drive.metadata.readonly',
  :redirect_uri => 'http://www.example.com/oauth2callback',
  :additional_parameters => {
    "access_type" => "offline",         # offline access
    "include_granted_scopes" => "true"  # incremental auth
  }
)

Ứng dụng của bạn sử 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 ủy quyền và áp dụng mã thông báo truy cập vào các yêu cầu HTTP.

Node.js

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

Đối tượng đó sử dụng thông tin từ tệp client_bí.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ã thông báo truy cập, bạn hãy chuyển hướng họ đến một trang đồng ý. Cách tạo URL của 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ề vào lần uỷ quyền đầu tiên. Tìm hiểu thêm tại đây.

HTTP/REST

Điểm cuối OAuth 2.0 của Google đang ở 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. Kết nối HTTP thuần túy 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:

Các tham 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 Credentials page API Console.

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 cấp phép. Giá trị phải khớp hoàn toàn với một trong các URI chuyển hướng đã được ủy quyền cho ứng dụng OAuth 2.0 mà bạn đã thiết lập trong ứng dụng khách API Console Credentials page. Nếu giá trị này không khớp với URI chuyển hướng được ủy quyền cho client_id được cung cấp, bạn sẽ gặp lỗi redirect_uri_mismatch.

Lưu ý rằng giao thức http, https và dấu gạch chéo ( # 39; / ') đều phải khớp.

response_type Bắt buộc

Xác định xem điểm cuối Google OAuth 2.0 có trả về mã ủy 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

Danh sách phạm vi được phân tách bằng dấu cách để xác định 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. Những giá trị này thông báo cho màn hình về sự đồ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 cần thiết, đồng thời cho phép người dùng kiểm soát số lượng quyền truy cập mà họ cấp vào ứ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 thu thập sự đồng ý của người dùng.

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

access_type Nên

Cho biết ứng dụng của bạn có thể làm mới mã thông báo truy cập khi người dùng không có mặt tại 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.

Đặt giá trị thành offline nếu ứng dụng của bạn cần làm mới mã thông báo 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ã thông báo 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ột mã làm mới mã truy cập trong 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 Nên

Chỉ định bất kỳ giá trị chuỗi nào mà ứng dụng sử dụng để duy trì trạng thái giữa yêu cầu ủy quyền và phản hồi của máy chủ ủy quyền. Máy chủ 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 quyền truy cập của ứng dụng.

Bạn có thể sử dụng thông 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 giả mạo yêu cầu trên nhiều trang web. Vì redirect_uri của bạn có thể đoán được, nên việc sử dụng giá trị state có thể giúp đảm bảo rằng kết nối đến là kết quả của 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 nắm bắt trạng thái của ứng dụng, 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, qua đó bảo vệ khỏ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 Tùy chọn

Cho phép các ứng dụng sử dụng tính năng ủy 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ị thông số này thành true và yêu cầu cấp quyền được cấp, thì mã thông báo truy cập mới cũng sẽ bao gồm mọi phạm vi mà người dùng đã cấp quyền truy cập vào ứng dụng trước đó. Hãy xem phần ủy quyền gia tăng để biết ví dụ.

login_hint Tùy chọn

Nếu biết người dùng nào đang cố xác thực, ứ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 hóa luồng đă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 lần thích hợp.

Đặt giá trị thông 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 Tùy chọn

Danh sách lời nhắc đượ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 thông số này, thì người dùng sẽ chỉ được nhắc ở lần đầu tiên dự án của bạn yêu cầu quyền truy cập. Hãy xem bài viết 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ị màn hình xác thực hoặc đồng ý. Không được chỉ định giá trị khác.
consent Nhắc người dùng đồng ý.
select_account Nhắc người dùng chọn 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, điều 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 ủy quyền gia tăng, bước này cũng xảy ra khi ứng dụng của bạn cần truy cập vào các tài nguyên bổ sung đầu tiên mà ứng dụng chưa có quyền truy cập.

PHP

  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 = auth_client.authorization_uri.to_s
  2. Chuyển hướng người dùng đến auth_uri.

Node.js

  1. Hãy sử dụng URL được tạo authorizationUrl từ 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

An example URL is shown below, with line breaks and spaces for readability.

https://accounts.google.com/o/oauth2/v2/auth?
 scope=https%3A//www.googleapis.com/auth/drive.metadata.readonly&
 access_type=offline&
 include_granted_scopes=true&
 response_type=code&
 state=state_parameter_passthrough_value&
 redirect_uri=https%3A//oauth2.example.com/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à có được 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 yêu cầu. Phản hồi sẽ được gửi lại ứ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 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ị cửa sổ lấy sự đồng ý cho thấy tên của ứng dụng và 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 cấp phép của người dùng và bảng tóm tắt phạm vi truy cập đượ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ó quyền truy cập nào không. Phản hồi đó được giải thích ở bước sau.

Lỗi

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

admin_policy_enforced

Tài khoản Google không thể ủy quyền 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 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à amp; ứng dụng nội bộ nào có thể 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 mọi phạm vi hoặc phạm vi nhạy cảm và bị hạn chế cho đến khi quyền truy cập được cấp cho mã ứng dụng khách OAuth của bạn.

disallowed_useragent

Điểm cuối ủy quyền sẽ hiển thị bên trong một tác nhân người dùng được nhúng theo Chính sách OAuth 2.0 của Google.

Android

Nhà phát triển Android có thể gặp thông báo lỗi này khi mở yêu cầu ủy 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 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 ứ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 di chuyển đến điểm cuối ủy quyền OAuth 2.0 của Google từ trang web của bạn. Nhà phát triển phải 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 Android Custom Tab cũng là một tuỳ chọn được hỗ trợ.

iOS

Nhà phát triển iOS và macOS có thể gặp lỗi này khi mở yêu cầu ủy quyền trong WKWebView. Thay vào đó, nhà phát triển nên sử dụng các thư viện iOS như Đăng nhập bằng Google 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 ứ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 di chuyển đến điểm cuối ủy quyền OAuth 2.0 của Google từ trang web của bạn. Nhà phát triển phải 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 lựa chọn được hỗ trợ.

org_internal

Mã ứng dụng khách OAuth trong yêu cầu này là một phần của một dự án hạn chế 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 mục Loại người dùng trong bài viết trợ giúp về Thiết lập màn hình đồng ý OAuth của bạn.

redirect_uri_mismatch

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

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 chấp thuận 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ề 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ã ủy 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 tra 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 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//www.googleapis.com/auth/drive.metadata.readonly&
 access_type=offline&
 include_granted_scopes=true&
 response_type=code&
 state=state_parameter_passthrough_value&
 redirect_uri=https%3A//oauth2.example.com/code&
 client_id=client_id

Sau khi hoàn tất quy trình OAuth 2.0, bạn nên được chuyển hướng đến http://localhost/oauth2callback, điều này có thể gây ra lỗi 404 NOT FOUND trừ khi máy cục bộ của bạn phân phối 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ã ủy quyền để làm mới và truy cập vào mã thông báo

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

PHP

Để trao đổi mã uỷ quyền cho 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 sử dụng thư viện google-auth để xác minh phản hồi của máy chủ uỷ quyền. Sau đó, hãy sử dụng phương thức flow.fetch_token để trao đổi mã uỷ quyền trong phản hồi đó cho mã thông báo 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/drive.metadata.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

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

auth_client.code = auth_code
auth_client.fetch_access_token!

Node.js

Để trao đổi mã uỷ quyền cho 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

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

Các trường
client_id Mã khách hàng nhận được 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 OAuth 2.0, bạn phải đặt giá trị cho trường này là authorization_code.
redirect_uri Một trong các URI chuyển hướng được liệt kê cho dự án của bạn trong API Consolecủa Credentials page cho một client_id nhất định.

Đ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 thông số access_type thành offline trong yêu cầu ban đầu tới máy chủ uỷ quyền của Google.

Câu trả lời chứa các trường sau:

Các trường
access_token Mã thông báo mà ứng dụng của bạn gửi để cấp phép cho yêu cầu API của Google.
expires_in Thời gian còn lại của mã thông báo 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ã thông báo làm mới là hợp lệ 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 thể hiện là danh sách các chuỗi phân tách bằng dấu cách, phân biệt chữ hoa chữ thường.
token_type Loại mã thông báo được trả về. Tại thời điểm này, 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 phản hồi mẫu:

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

Gọi API Google

PHP

Hãy sử dụng mã truy cập để gọi các API của Google bằng cách hoàn thành 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 truy cập 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 ủy quyền cho hàm khởi tạo dành cho API mà bạn muốn gọi. Ví dụ: để gọi API Drive:
    $drive = new Google\Service\Drive($client);
  3. Gửi yêu cầu đến dịch vụ API bằng giao diện do đối tượng dịch vụ cung cấp. Ví dụ: để liệt kê các tệp trong Google Drive của người dùng đã xác thực:
    $files = $drive->files->listFiles(array())->getItems();

Python

Sau khi có được mã truy cập, ứng dụng của bạn có thể dùng mã đó để ủy quyền yêu cầu API thay cho một tài khoản người dùng hoặc tài khoản dịch vụ nhất định. Sử dụng thông tin cấp phép của người dùng cụ thể để xây dựng đối tượng dịch vụ cho API mà bạn muốn gọi, sau đó sử dụng đối tượng đó để tạo 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 một đối tượng dịch vụ bằng cách gọi phương thức build của thư viện googleapiclient.discovery bằng tên và phiên bản của API cùng thông tin xác thực người dùng: Ví dụ: để gọi phiên bản 2 của API Drive:
    from googleapiclient.discovery import build
    
    drive = build('drive', 'v2', credentials=credentials)
  2. Gửi yêu cầu đến dịch vụ API bằng giao diện do đối tượng dịch vụ cung cấp. Ví dụ: để liệt kê các tệp trong Google Drive của người dùng đã xác thực:
    files = drive.files().list().execute()

Ruby

Sử dụng đối tượng auth_client để gọi API Google bằng cách hoàn thành các bước sau:

  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 2 của API Drive:
    drive = Google::Apis::DriveV2::DriveService.new
  2. Đặt thông tin xác thực trên dịch vụ:
    drive.authorization = auth_client
  3. Gửi yêu cầu đến dịch vụ API bằng giao diện do đối tượng dịch vụ cung cấp. Ví dụ: để liệt kê các tệp trong Google Drive của người dùng đã xác thực:
    files = drive.list_files

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:

files = drive.list_files(options: { authorization: auth_client })

Node.js

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

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ề GET GET HTTP

Lệnh gọi đến điểm cuối drive.files (API Drive Drive) bằ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ã thông báo truy cập của riêng mình:

GET /drive/v2/files HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer access_token

Sau đây là một 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/drive/v2/files?access_token=access_token

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. Sau đây là một ví dụ về tuỳ chọn tiêu đề HTTP (ưu tiên):

curl -H "Authorization: Bearer access_token" https://www.googleapis.com/drive/v2/files

Hoặc tùy chọn tham số chuỗi truy vấn:

curl https://www.googleapis.com/drive/v2/files?access_token=access_token

Ví dụ đầy đủ

Ví dụ sau đây sẽ in danh sách các tệp theo định dạng JSON trong Google Drive của người dùng sau khi người dùng xác thực và đồng ý cho phép ứng dụng truy cập vào siêu dữ liệu trên Drive của người dùng đó.

PHP

Để chạy ví dụ này, hãy làm như sau:

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

if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {
  $client->setAccessToken($_SESSION['access_token']);
  $drive = new Google\Service\Drive($client);
  $files = $drive->files->listFiles(array())->getItems();
  echo json_encode($files);
} 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\Drive::DRIVE_METADATA_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. Công cụ này chạy một ứng dụng web tại http://localhost:8080 cho phép bạn kiểm thử luồng 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 một 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, quá trình này sẽ bắt đầu quy trình uỷ quyền. Nếu thành công, trang sẽ hiển thị 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 gửi 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 uỷ quyền thay mặt cho người dùng.
  • Thu hồi thông tin đăng nhập hiện tại: Đường liên kết này trỏ đến một trang 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 bình luận: Đường liên kết này sẽ xóa thông tin đăng nhập ủy quyền được lưu trữ trong phiên Bình luận. Đ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ố gắng thực thi yêu cầu API trong một phiên mới. Nó cũng cho phép bạn xem phản hồi API mà ứng dụng của bạn sẽ nhận được nếu người dùng đã thu hồi các quyền đã cấp cho ứng dụng của bạn, và ứng dụng vẫn cố gắng cho phép yêu cầu bằng mã thông báo truy cập bị 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/drive.metadata.readonly']
API_SERVICE_NAME = 'drive'
API_VERSION = 'v2'

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'])

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

  files = drive.files().list().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(**files)


@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/drive_v2'
require 'google/api_client/client_secrets'
require 'json'
require 'sinatra'

enable :sessions
set :session_secret, 'setme'

get '/' do
  unless session.has_key?(:credentials)
    redirect to('/oauth2callback')
  end
  client_opts = JSON.parse(session[:credentials])
  auth_client = Signet::OAuth2::Client.new(client_opts)
  drive = Google::Apis::DriveV2::DriveService.new
  files = drive.list_files(options: { authorization: auth_client })
  "<pre>#{JSON.pretty_generate(files.to_h)}</pre>"
end

get '/oauth2callback' do
  client_secrets = Google::APIClient::ClientSecrets.load
  auth_client = client_secrets.to_authorization
  auth_client.update!(
    :scope => 'https://www.googleapis.com/auth/drive.metadata.readonly',
    :redirect_uri => url('/oauth2callback'))
  if request['code'] == nil
    auth_uri = auth_client.authorization_uri.to_s
    redirect to(auth_uri)
  else
    auth_client.code = request['code']
    auth_client.fetch_access_token!
    auth_client.client_secret = nil
    session[:credentials] = auth_client.to_json
    redirect to('/')
  end
end

Node.js

Để chạy ví dụ này, hãy làm như sau:

  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. Hãy đảm bảo rằng bạn đã cài đặt LTS (hỗ trợ dài hạn), LTS (hỗ trợ dài hạn) đang hoạt động hoặc đã cài đặt Node.js hiện tại.
  3. Tạo thư mục mới và thay đổi 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 bằng nội dung bên dưới.
  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ụ về Python này sử dụng khung Flask và thư viện Requests (Yêu cầu) để minh hoạ quy trình web OAuth 2.0. Bạn nên sử dụng Thư viện ứng dụng Python cho API của Google cho quy trình này. (Ví dụ trong thẻ Python sẽ 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/drive.metadata.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/drive/v2/files'
    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 chuyển hướng URI chuyển hướng

Google áp dụng các quy tắc xác thực sau đây để chuyển hướng URI nhằm giúp nhà phát triển bảo mật ứ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. Xem RFC 3986 phần 3 để biết định nghĩa về miền, máy chủ, đường dẫn, truy vấn, lược đồ và thông tin người dùng, được đề cập bên dưới.

Các quy tắc xác thực
Sơ đồ

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

Máy chủ

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 khỏi quy tắc này.

Miền
  • Các 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”.
  • URI chuyển hướng không được chứa các miền rút ngắn URL (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 một 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ụ userinfo.

    Đường dẫn

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

    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 được 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 thể 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 dạng mã hoá URL của 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 đã mã hoá, ví dụ: %00, %C0%80)

    Ủy quyền gia tăng

    Trong giao thức OAuth 2.0, ứng dụng sẽ yêu cầu cấp quyền truy cập vào tài nguyên (phạm vi đượ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 cấp phép đối với các tài nguyên tại thời điểm bạn cần các tài nguyên đó. Để bật phương thức đó, máy chủ uỷ quyền của Google sẽ hỗ trợ việc uỷ quyền dần dần. Tính năng này cho phép bạn yêu cầu phạm vi khi cần và nếu người dùng cấp quyền cho phạm vi mới, sẽ trả về một mã ủy quyền có thể được đổi lấy mã thông báo chứa tất cả phạm vi mà người dùng đã cấp dự án.

    Ví dụ: một ứng dụng cho phép mọi người lấy mẫu bản nhạc và tạo danh sách kết hợp có thể cần rất ít tài nguyên tại thời điểm đăng nhập. Đây có thể không phải là gì ngoài tên của người đăng nhập. Tuy nhiên, việc lưu một danh sách kết hợp hoàn chỉnh sẽ yêu cầu quyền truy cập vào Google Drive của họ. Hầu hết mọi người sẽ thấy bình thường nếu họ chỉ được yêu cầu cấp quyền truy cập vào Google Drive vào thời điểm ứng dụng thực sự cần đến.

    Trong trường hợp này, tại thời điểm đăng nhập, ứng dụng có thể yêu cầu phạm vi openidprofile để thực hiện hoạt động đăng nhập cơ bản, sau đó yêu cầu phạm vi https://www.googleapis.com/auth/drive.file tại thời điểm yêu cầu đầu tiên để lưu danh sách kết hợp.

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

    • Bạn có thể sử 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 gán cho một hoạt động cấp phép kết hợp mới.
    • Khi bạn sử dụng mã làm mới cho mã ủy quyền kết hợp để có mã truy cập, mã thông báo truy cập đại diện cho mã ủy quyền kết hợp và có thể được sử dụng cho bất kỳ giá trị scope nào có trong phản hồi.
    • Ủy 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 đã đượ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 một ứng dụng khách trên máy tính và sau đó cấp một phạm vi khác cho cùng một ứng dụng thông qua một ứng dụng di động, thì lệnh ủy quyền kết hợp sẽ bao gồm cả hai phạm vi.
    • Nếu bạn thu hồi mã thông báo đại diện cho một lệnh ủy quyền kết hợp, thì quyền truy cập vào tất cả các phạm vi ủy 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 theo ngôn ngữ cụ thể trong Bước 1: Đặt thông 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 chức năng uỷ quyền tăng dần. Mã mẫu bên dưới cũng hiển thị mã mà bạn cần thêm để sử dụng tính năng uỷ quyền gia tăng.

    PHP

    $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 cấp quyền bao gồm 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ư minh hoạ 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

    GET https://accounts.google.com/o/oauth2/v2/auth?
      client_id=your_client_id&
      response_type=code&
      state=state_parameter_passthrough_value&
      scope=https%3A//www.googleapis.com/auth/drive.file&
      redirect_uri=https%3A//oauth2.example.com/code&
      prompt=consent&
      include_granted_scopes=true

    Làm mới mã thông báo truy cập (truy cập ngoại tuyến)

    Mã truy cập sẽ hết hạn theo định kỳ và trở thành thông tin xác thực không hợp lệ cho yêu cầu API có liên quan. Bạn có thể làm mới mã thông báo truy cập mà không cần nhắc người dùng cấp quyền (bao gồm cả khi không có người dùng) nếu bạn đã yêu cầu quyền truy cập ngoại tuyến vào các phạm vi liên kết với mã thông báo.

    • Nếu bạn sử dụng Thư viện ứng dụng API của Google, đối tượng ứng dụng sẽ làm mới mã thông báo truy cập nếu cần, miễn là bạn định cấu hình đối tượng đó để truy cập ngoại tuyến.
    • Nếu không sử dụng thư viện ứng dụng, bạn cần đặt tham số truy vấn HTTP access_type thành offline khi chuyển hướng người dùng đến máy chủ OAuth 2.0 của Google. Trong trường hợp đó, máy chủ uỷ quyền của Google sẽ trả về một mã làm mới khi bạn trao đổi mã uỷ quyền cho mã truy cập. Sau đó, nếu mã truy cập hết hạn (hoặc vào bất kỳ thời điểm nào khác), bạn có thể sử dụng mã làm mới để lấy mã truy cập mới.

    Yêu cầu quyền truy cập ngoại tuyến là yêu cầu bắt buộc đối với mọi ứng dụng cần truy cập vào API của Google khi người dùng không có mặt. Ví dụ: Một ứng dụng thực hiện các dịch vụ sao lưu hoặc thực hiện các thao tác vào những thời điểm được xác định trước cần phải làm mới mã truy cập khi không có người dùng. Kiểu truy cập mặc định được gọi là online.

    Các ứng dụng web phía máy chủ, ứng dụng đã cài đặt và thiết bị đều nhận được mã thông báo làm mới trong quá trình uỷ quyền. Mã làm mới thường không được dùng trong các ứng dụng web phía máy khách (JavaScript).

    PHP

    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 Google, hãy đặt loại quyền truy cập của ứng dụng API đó thành 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 yêu cầu, bạn có thể tiếp tục sử dụng ứng dụng API để thay mặt người dùng truy cập vào các API của Google khi người dùng đó không có kết nối mạng. Đối tượng khách hàng sẽ làm mới mã thông báo 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 sẽ có thể làm mới mã truy cập mà không phải nhắc lại người dùng 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ư minh hoạ 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')

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

    Mã truy cập sẽ hết hạn. Thư viện này sẽ tự động sử dụng mã làm mới để lấy mã truy cập mới nếu mã sắp hết hạn. Một cách dễ dàng để đảm bảo bạn luôn lưu trữ 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 đặt access_type thành offline khi gọi phương thức generateAuthUrl để nhận mã làm mới. Nếu đã từng cấp cho ứng dụng của bạn quyền yêu cầu mà không thiết lập các hạn chế thích hợp để nhận mã làm mới, thì bạn sẽ cần phải ủy quyền lại ứ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ã thông báo truy cập sẽ tự động được lấy và làm mới trong lệnh gọi API tiếp theo.

    HTTP/REST

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

    Các trường
    client_id Mã ứng dụng thu được từ API Console.
    client_secret Mật khẩu ứng dụng khách lấy từ API Console.
    grant_type Như đã nêu trong thông số kỹ thuật 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ừ sàn giao dịch 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ề đố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ó 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 khách hà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ả khách hàng. Bạn nên lưu các mã làm mới trong bộ nhớ dài hạn và tiếp tục sử dụng các mã đó miễn là mã còn lại hợp lệ. Nếu ứng dụng của bạn yêu cầu quá nhiều mã làm mới, thì ứng dụng có thể bị giới hạn các trường hợp này. Trong trường hợp đó, các mã thông báo làm mới cũ 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 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. Xem phần Xóa trang web hoặc quyền truy cập ứng dụng của trang web và ứng dụng bên thứ ba; ứng dụng có quyền truy cập vào tài khoản của bạn tài liệu hỗ trợ để biết thêm thông tin.

    Ứng dụng cũng có thể bị thu hồi quyền truy cập theo phương thức lập trình. Thu hồi theo chương trình có ý nghĩa quan trọng trong trường hợp người dùng hủy đăng ký, xoá ứng dụng hoặc tài nguyên API mà một ứ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 xóa có thể bao gồm một yêu cầu API để đảm bảo các quyền trước đây được cấp cho ứng dụng sẽ bị xóa.

    PHP

    Để 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

    Để tự động thu hồi mã thông báo, hãy gửi yêu cầu tới https://oauth2.googleapis.com/revoke chứa mã thông báo dưới dạng thông số và đặt 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 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ã này có thể là mã truy cập hoặc mã làm mới. Nếu mã là mã truy cập và có mã làm mới tương ứng, thì mã thông báo 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 của phản hồi sẽ là 200. Đối với đ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 yêu cầu POST qua HTTPS đến điểm cuối /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();
    

    Thông số mã thông báo có thể là mã truy cập hoặc mã làm mới. Nếu mã là mã truy cập và có mã làm mới tương ứng, thì mã thông báo 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 của phản hồi sẽ là 200. Đối với đ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

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

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

    Mã này có thể là mã truy cập hoặc mã làm mới. Nếu mã là mã truy cập và có mã làm mới tương ứng, thì mã thông báo 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 điều kiện lỗi, mã trạng thái HTTP 400 được trả về cùng với mã lỗi.