Sử dụng OAuth 2.0 cho ứng dụng từ máy chủ đến máy chủ

Hệ thống người dùng sử dụng các tính năng cơ chế đã có trong ứng dụng:ngủi năng sử dụng các tính năng tốt hơn Một tiện ích dành cho người dùng sử dụng Để biết thêm thông tin, hãy xem phần Tổng quan về quy trình xác thực trong tài liệu của Google Cloud Platform.

Hệ thống Google OAuth 2.0 hỗ trợ các hoạt động tương tác từ máy chủ đến máy chủ, chẳng hạn như các hoạt động tương tác giữa ứng dụng web và dịch vụ của Google. Trong trường hợp này, bạn cần có một tài khoản dịch vụ, tức là tài khoản thuộc về ứng dụng của bạn thay vì thuộc về người dùng cuối. Ứng dụng của bạn gọi API Google thay mặt cho tài khoản dịch vụ, vì vậy, người dùng không được tham gia trực tiếp. Tình huống này đôi khi được gọi là "OAuth hai chân" hoặc "2LO". (Thuật ngữ liên quan đến "OAuth thành phần" là các tình huống mà trong đó ứng dụng của bạn gọi API của Google thay mặt cho người dùng cuối và đôi khi bắt buộc phải có sự đồng ý của người dùng.)

Thông thường, một ứng dụng sử dụng tài khoản dịch vụ khi ứng dụng đó sử dụng API của Google để làm việc với dữ liệu của chính nó thay vì dữ liệu của người dùng. Ví dụ: một ứng dụng sử dụng DataStore của Google Cloud để lưu trữ dữ liệu sẽ sử dụng tài khoản dịch vụ để xác thực lệnh gọi của ứng dụng đó đến API Google Cloud Datastore.

Quản trị viên miền Google Workspace cũng có thể cấp quyền cho toàn bộ tài khoản dịch vụ để truy cập vào dữ liệu người dùng thay mặt người dùng trong miền.

Tài liệu này mô tả cách một ứng dụng có thể hoàn tất quy trình OAuth 2.0 từ máy chủ đến máy chủ bằng cách sử dụng thư viện ứng dụng API của Google (nên dùng) hoặc HTTP.

Tổng quan

Để hỗ trợ tương tác giữa các máy chủ, trước tiên, hãy tạo một tài khoản dịch vụ cho dự án của bạn trong . Nếu bạn muốn truy cập vào dữ liệu người dùng cho người dùng trong tài khoản Google Workspace của mình, hãy uỷ quyền truy cập trên toàn miền vào tài khoản dịch vụ.

Sau đó, ứng dụng của bạn chuẩn bị thực hiện lệnh gọi API được ủy quyền bằng cách sử dụng thông tin đăng nhập của tài khoản dịch vụ để yêu cầu mã truy cập từ máy chủ xác thực OAuth 2.0.

Cuối cùng, ứng dụng có thể dùng mã truy cập để gọi API của Google.

Tạo một tài khoản dịch vụ

Thông tin xác thực của tài khoản dịch vụ bao gồm một địa chỉ email được tạo riêng biệt và ít nhất một cặp khoá công khai/riêng tư. Nếu bạn bật tính năng ủy quyền trên toàn miền, thì mã ứng dụng khách cũng là một phần trong thông tin đăng nhập của tài khoản dịch vụ.

Nếu ứng dụng của bạn chạy trên Google App Engine, thì một tài khoản dịch vụ sẽ tự động được thiết lập khi bạn tạo dự án.

Nếu ứng dụng của bạn chạy trên Google Compute Engine, thì một tài khoản dịch vụ cũng sẽ được thiết lập tự động khi bạn tạo dự án, nhưng bạn phải chỉ định các phạm vi mà ứng dụng cần truy cập khi bạn tạo một bản sao của Google Compute Engine. Để biết thêm thông tin, hãy xem phần Chuẩn bị một phiên bản để sử dụng tài khoản dịch vụ.

Nếu ứng dụng của bạn không chạy trên Google App Engine hoặc Google Compute Engine, thì bạn phải lấy những thông tin đăng nhập này trong . Để tạo thông tin xác thực của tài khoản dịch vụ hoặc để xem thông tin xác thực công khai mà bạn đã tạo, hãy làm như sau:

首先,创建一个服务帐户:

  1. 打开 Service accounts page
  2. If prompted, select a project, or create a new one.
  3. 单击创建服务帐户
  4. Service account details下,键入服务帐户的名称、ID 和描述,然后点击Create and continue
  5. 可选:在Grant this service account access to project下,选择要授予服务帐户的 IAM 角色。
  6. 单击继续
  7. 可选:在Grant users access to this service account下,添加允许使用和管理服务帐户的用户或组。
  8. 单击完成

接下来,创建一个服务帐户密钥:

  1. 单击您创建的服务帐户的电子邮件地址。
  2. 单击密钥选项卡。
  3. 添加密钥下拉列表中,选择创建新密钥
  4. 单击创建

您的新公钥/私钥对已生成并下载到您的机器上;它作为私钥的唯一副本。您有责任安全地存储它。如果您丢失了这个密钥对,您将需要生成一个新的。

Bạn có thể quay lại API Console bất cứ lúc nào để xem địa chỉ email, vân tay số của khoá công khai và các thông tin khác hoặc tạo thêm cặp khoá công khai/riêng tư. Để biết thêm thông tin về thông tin đăng nhập vào tài khoản dịch vụ trong API Console, hãy xem phần Tài khoản dịch vụ trong tệp trợ giúp API Console.

Hãy ghi lại địa chỉ email của tài khoản dịch vụ và lưu trữ tệp khóa riêng tư của tài khoản dịch vụ ở một vị trí mà ứng dụng của bạn có thể truy cập. Ứng dụng của bạn cần các mã này để thực hiện lệnh gọi API được ủy quyền.

Uỷ thác quyền trên toàn miền cho tài khoản dịch vụ

Nếu bạn có tài khoản Google Workspace, quản trị viên của tổ chức có thể thay mặt người dùng trong miền Google Workspace truy cập vào dữ liệu người dùng. Ví dụ: một ứng dụng dùng API Lịch Google để thêm sự kiện vào lịch của tất cả người dùng trong một miền Google Workspace sẽ thay mặt người dùng sử dụng tài khoản dịch vụ để truy cập API Lịch Google. Việc cấp phép cho một tài khoản dịch vụ thay mặt người dùng trong miền truy cập dữ liệu đôi khi được gọi là "uỷ quyền trên toàn miền" cho một tài khoản dịch vụ.

Để uỷ quyền trên toàn miền cho một tài khoản dịch vụ, quản trị viên cấp cao của miền Google Workspace phải hoàn thành các bước sau:

  1. Từ Bảng điều khiển dành cho quản trị viên của miền Google Workspace, hãy chuyển đến Trình đơn chính > Bảo mật > Quyền truy cập và kiểm soát dữ liệu > Điều khiển API.
  2. Trong ngăn Ủy quyền trên toàn miền, hãy chọn Quản lý ủy quyền trên toàn miền.
  3. Nhấp vào Thêm mới.
  4. Trong trường Mã khách hàng, hãy nhập Mã khách hàng của tài khoản dịch vụ. Bạn có thể tìm thấy mã khách hàng của tài khoản dịch vụ trong Service accounts page.
  5. Trong trường OAuth scope (được phân tách bằng dấu phẩy), hãy nhập danh sách các phạm vi mà ứng dụng của bạn sẽ được cấp quyền truy cập. Ví dụ: nếu ứng dụng của bạn cần quyền truy cập đầy đủ vào toàn bộ API Google Drive và API Lịch Google, hãy nhập: https://www.googleapis.com/auth/drive, https://www.googleapis.com/auth/calendar.
  6. Nhấp vào Uỷ quyền.

Giờ đây, ứng dụng của bạn có quyền thực hiện các lệnh gọi API với tư cách là người dùng trong miền của bạn (đối với người dùng "mạo danh"). Khi chuẩn bị thực hiện các lệnh gọi API được ủy quyền, bạn chỉ định người dùng mạo danh.

Chuẩn bị thực hiện lệnh gọi API được ủy quyền

Java

Sau khi bạn lấy địa chỉ email khách hàng và khoá riêng tư từ API Console, hãy sử dụng Thư viện ứng dụng Java cho API của Google để tạo đối tượng GoogleCredential từ thông tin xác thực của tài khoản dịch vụ và phạm vi mà ứng dụng của bạn cần truy cập. Ví dụ:

import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.services.sqladmin.SQLAdminScopes;

// ...

GoogleCredential credential = GoogleCredential.fromStream(new FileInputStream("MyProject-1234.json"))
    .createScoped(Collections.singleton(SQLAdminScopes.SQLSERVICE_ADMIN));

Nếu đang phát triển một ứng dụng trên Google Cloud Platform, bạn có thể sử dụng thông tin xác thực mặc định của ứng dụng để đơn giản hoá quy trình này.

Uỷ quyền trên toàn miền

Nếu bạn được uỷ quyền truy cập trên toàn miền vào tài khoản dịch vụ và muốn mạo danh một tài khoản người dùng, hãy chỉ định địa chỉ email của tài khoản người dùng bằng phương thức createDelegated của đối tượng GoogleCredential. Ví dụ:

GoogleCredential credential = GoogleCredential.fromStream(new FileInputStream("MyProject-1234.json"))
    .createScoped(Collections.singleton(SQLAdminScopes.SQLSERVICE_ADMIN))
    .createDelegated("user@example.com");

Sử dụng đối tượng GoogleCredential để gọi các API Google trong ứng dụng của bạn.

Python

Sau khi bạn lấy địa chỉ email khách hàng và khoá riêng tư từ API Console, hãy sử dụng Thư viện ứng dụng API của Google cho Python để hoàn tất các bước sau:

  1. Tạo một đối tượng Credentials từ thông tin xác thực của tài khoản dịch vụ và phạm vi mà ứng dụng của bạn cần truy cập. Ví dụ:
    from google.oauth2 import service_account
    
    SCOPES = ['https://www.googleapis.com/auth/sqlservice.admin']
    SERVICE_ACCOUNT_FILE = '/path/to/service.json'
    
    credentials = service_account.Credentials.from_service_account_file(
            SERVICE_ACCOUNT_FILE, scopes=SCOPES)

    Nếu đang phát triển một ứng dụng trên Google Cloud Platform, bạn có thể sử dụng thông tin xác thực mặc định của ứng dụng để đơn giản hoá quy trình này.

  2. Uỷ quyền trên toàn miền

    Nếu bạn được uỷ quyền truy cập trên toàn miền vào tài khoản dịch vụ và muốn mạo danh một tài khoản người dùng, hãy sử dụng phương thức with_subject của đối tượng ServiceAccountCredentials hiện có. Ví dụ:

    delegated_credentials = credentials.with_subject('user@example.org')

Sử dụng đối tượng Thông tin xác thực để gọi các API của Google trong ứng dụng của bạn.

HTTP/REST (Hệ thống HTTP/REST)

Sau khi bạn có được mã ứng dụng khách và khoá riêng tư từ API Console, ứng dụng của bạn cần phải hoàn tất những bước sau:

  1. Tạo Mã thông báo web JSON (JWT, phát âm, "jot") trong đó có tiêu đề, tập hợp thông báo xác nhận quyền sở hữu và chữ ký.
  2. Yêu cầu mã truy cập từ Máy chủ uỷ quyền Google OAuth 2.0.
  3. Xử lý phản hồi JSON mà Máy chủ uỷ quyền trả về.

Phần sau đây mô tả cách hoàn tất các bước này.

Nếu phản hồi đó có mã truy cập, bạn có thể dùng mã truy cập để gọi một API Google. (Nếu phản hồi không bao gồm mã truy cập, yêu cầu mã thông báo JWT và mã thông báo của bạn có thể không được tạo đúng cách hoặc tài khoản dịch vụ có thể không có quyền truy cập vào các phạm vi được yêu cầu.)

Khi mã truy cập hết hạn, ứng dụng sẽ tạo một JWT khác, ký mã này và yêu cầu một mã truy cập khác.

Ứng dụng máy chủ của bạn sử dụng JWT để yêu cầu mã thông báo từ Máy chủ uỷ quyền của Google, sau đó dùng mã này để gọi một điểm cuối API của Google. Không có người dùng cuối nào tham gia.

Phần còn lại của mục này mô tả các chi tiết cụ thể của việc tạo JWT, ký JWT, hình thành yêu cầu mã truy cập và xử lý phản hồi.

Tạo JWT

JWT bao gồm ba phần: tiêu đề, tập hợp xác nhận quyền sở hữu và chữ ký. Tiêu đề và tập hợp xác nhận quyền sở hữu là các đối tượng JSON. Các đối tượng JSON này được chuyển đổi tuần tự thành byte UTF-8, sau đó được mã hoá bằng phương thức mã hoá Base64url. Việc mã hoá này giúp bạn có khả năng phục hồi trước những thay đổi về mã hoá do thao tác mã hoá lặp lại. Tiêu đề, tập hợp xác nhận quyền sở hữu và chữ ký được nối với nhau bằng một ký tự dấu chấm (.).

JWT được cấu tạo như sau:

{Base64url encoded header}.{Base64url encoded claim set}.{Base64url encoded signature}

Chuỗi cơ sở cho chữ ký như sau:

{Base64url encoded header}.{Base64url encoded claim set}
Hình thành tiêu đề JWT

Tiêu đề bao gồm hai trường cho biết thuật toán ký và định dạng của câu nhận định. Cả hai trường đều là bắt buộc và mỗi trường chỉ có một giá trị. Khi chúng tôi ra mắt các thuật toán và định dạng khác, tiêu đề này sẽ thay đổi theo.

Tài khoản dịch vụ dựa vào thuật toán RSA SHA-256 và định dạng mã thông báo JWT. Do đó, cách biểu diễn JSON của tiêu đề sẽ như sau:

{"alg":"RS256","typ":"JWT"}

Cách biểu diễn Base64url như sau:

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9
Hình thành nhóm xác nhận quyền sở hữu JWT

Tập hợp thông báo xác nhận quyền sở hữu của JWT chứa thông tin về JWT, bao gồm các quyền được yêu cầu (phạm vi), mục tiêu của mã thông báo, nhà phát hành, thời gian mã thông báo được phát hành và vòng đời của mã thông báo. Hầu hết các trường là bắt buộc. Giống như tiêu đề JWT, nhóm thông báo xác nhận quyền sở hữu JWT là đối tượng JSON và được dùng để tính toán chữ ký.

Thông báo xác nhận quyền sở hữu bắt buộc

Dưới đây là các thông báo xác nhận quyền sở hữu bắt buộc trong tập hợp thông báo xác nhận quyền sở hữu của JWT. Các yêu cầu này có thể xuất hiện theo thứ tự bất kỳ trong thông báo xác nhận quyền sở hữu đã đặt.

Tên Mô tả
iss Địa chỉ email của tài khoản dịch vụ.
scope Danh sách các quyền được phân tách bằng dấu cách mà ứng dụng yêu cầu.
aud Phần mô tả mục tiêu dự kiến của câu nhận định. Khi tạo mã truy cập yêu cầu, giá trị này luôn là https://oauth2.googleapis.com/token.
exp Thời gian hết hạn của câu nhận định, được chỉ định bằng giây kể từ 00:00:00 giờ UTC, ngày 1 tháng 1 năm 1970. Giá trị này có tối đa 1 giờ sau thời gian phát hành.
iat Thời gian khẳng định được đưa ra, được chỉ định bằng giây kể từ 00:00:00 giờ UTC, ngày 1 tháng 1 năm 1970.

Dưới đây là cách trình bày JSON của các trường bắt buộc trong nhóm thông báo xác nhận quyền sở hữu JWT:

{
  "iss": "761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer.gserviceaccount.com",
  "scope": "https://www.googleapis.com/auth/devstorage.read_only",
  "aud": "https://oauth2.googleapis.com/token",
  "exp": 1328554385,
  "iat": 1328550785
}
Thông báo xác nhận quyền sở hữu khác

Trong một số trường hợp doanh nghiệp, ứng dụng có thể dùng tính năng uỷ quyền trên toàn miền để thay mặt cho một người dùng cụ thể trong tổ chức. Quyền thực hiện loại mạo danh này phải được cấp trước khi ứng dụng có thể mạo danh người dùng và thường do quản trị viên cấp cao xử lý. Để biết thêm thông tin, hãy xem bài viết Kiểm soát quyền truy cập của API bằng tính năng uỷ quyền trên toàn miền.

Để nhận được mã truy cập cấp cho một ứng dụng quyền truy cập được ủy quyền vào một tài nguyên, hãy thêm địa chỉ email của người dùng trong xác nhận quyền sở hữu JWT làm giá trị của trường sub.

Tên Mô tả
sub Địa chỉ email của người dùng mà ứng dụng đang yêu cầu quyền truy cập được uỷ quyền.

Nếu một ứng dụng không có quyền mạo danh người dùng, thì phản hồi cho yêu cầu mã truy cập có chứa trường sub sẽ là lỗi.

Dưới đây là ví dụ về nhóm thông báo xác nhận quyền sở hữu của JWT bao gồm trường sub:

{
  "iss": "761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer.gserviceaccount.com",
  "sub": "some.user@example.com",
  "scope": "https://www.googleapis.com/auth/prediction",
  "aud": "https://oauth2.googleapis.com/token",
  "exp": 1328554385,
  "iat": 1328550785
}
Mã hoá nhóm thông báo xác nhận quyền sở hữu JWT

Giống như tiêu đề JWT, nhóm thông báo xác nhận quyền sở hữu JWT phải được chuyển đổi tuần tự thành UTF-8 và Base64url được mã hoá an toàn. Dưới đây là ví dụ về cách biểu diễn JSON của nhóm Thông báo xác nhận quyền sở hữu JWT:

{
  "iss": "761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer.gserviceaccount.com",
  "scope": "https://www.googleapis.com/auth/prediction",
  "aud": "https://oauth2.googleapis.com/token",
  "exp": 1328554385,
  "iat": 1328550785
}
Tính toán chữ ký

Chữ ký web JSON (JWS) là thông số kỹ thuật hướng dẫn cơ chế tạo chữ ký cho JWT. Dữ liệu đầu vào cho chữ ký là mảng byte của nội dung sau:

{Base64url encoded header}.{Base64url encoded claim set}

Bạn phải sử dụng thuật toán ký trong tiêu đề JWT khi tính toán chữ ký. Thuật toán ký duy nhất được Máy chủ uỷ quyền Google OAuth 2.0 hỗ trợ là RSA sử dụng thuật toán băm SHA-256. Điều này được biểu thị dưới dạng RS256 trong trường alg của tiêu đề JWT.

Ký đại diện UTF-8 của đầu vào bằng cách sử dụng SHA256withRSA (còn được gọi là RSASSA-PKCS1-V1_5-SIGN với hàm băm SHA-256) bằng khóa riêng tư thu được từ Google API Console. Kết quả sẽ là một mảng byte.

Sau đó, chữ ký phải được mã hoá bằng Base64url. Tiêu đề, tập hợp xác nhận quyền sở hữu và chữ ký được nối với nhau bằng một ký tự dấu chấm (.). Kết quả là JWT. Thông số này phải như sau (dấu ngắt dòng được thêm vào để rõ ràng):

{Base64url encoded header}.
{Base64url encoded claim set}.
{Base64url encoded signature}

Dưới đây là ví dụ về JWT trước khi mã hoá Base64url:

{"alg":"RS256","typ":"JWT"}.
{
"iss":"761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer.gserviceaccount.com",
"scope":"https://www.googleapis.com/auth/prediction",
"aud":"https://oauth2.googleapis.com/token",
"exp":1328554385,
"iat":1328550785
}.
[signature bytes]

Dưới đây là một ví dụ về JWT đã được ký và sẵn sàng để truyền:

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI3NjEzMjY3OTgwNjktcjVtbGpsbG4xcmQ0bHJiaGc3NWVmZ2lncDM2bTc4ajVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzY29wZSI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2F1dGgvcHJlZGljdGlvbiIsImF1ZCI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL29hdXRoMi92NC90b2tlbiIsImV4cCI6MTMyODU1NDM4NSwiaWF0IjoxMzI4NTUwNzg1fQ.UFUt59SUM2_AW4cRU8Y0BYVQsNTo4n7AFsNrqOpYiICDu37vVt-tw38UKzjmUKtcRsLLjrR3gFW3dNDMx_pL9DVjgVHDdYirtrCekUHOYoa1CMR66nxep5q5cBQ4y4u2kIgSvChCTc9pmLLNoIem-ruCecAJYgI9Ks7pTnW1gkOKs0x3YpiLpzplVHAkkHztaXiJdtpBcY1OXyo6jTQCa3Lk2Q3va1dPkh_d--GU2M5flgd8xNBPYw4vxyt0mP59XZlHMpztZt0soSgObf7G3GXArreF_6tpbFsS3z2t5zkEiHuWJXpzcYr5zWTRPDEHsejeBSG8EgpLDce2380ROQ

Tạo yêu cầu mã thông báo truy cập

Sau khi tạo JWT đã ký, ứng dụng có thể dùng JWT để yêu cầu mã truy cập. Yêu cầu mã thông báo truy cập này là một yêu cầu HTTPS POST và nội dung được mã hóa URL. URL xuất hiện bên dưới:

https://oauth2.googleapis.com/token

Các thông số sau đây là bắt buộc trong yêu cầu HTTPS POST:

Tên Mô tả
grant_type Sử dụng chuỗi sau, được mã hoá URL nếu cần: urn:ietf:params:oauth:grant-type:jwt-bearer
assertion JWT, bao gồm cả chữ ký.

Dưới đây là tệp kết xuất thô của yêu cầu HTTPS POST sử dụng trong yêu cầu mã truy cập:

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

grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI3NjEzMjY3OTgwNjktcjVtbGpsbG4xcmQ0bHJiaGc3NWVmZ2lncDM2bTc4ajVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzY29wZSI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2F1dGgvcHJlZGljdGlvbiIsImF1ZCI6Imh0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbS9vL29hdXRoMi90b2tlbiIsImV4cCI6MTMyODU3MzM4MSwiaWF0IjoxMzI4NTY5NzgxfQ.ixOUGehweEVX_UKXv5BbbwVEdcz6AYS-6uQV6fGorGKrHf3LIJnyREw9evE-gs2bmMaQI5_UbabvI4k-mQE4kBqtmSpTzxYBL1TCd7Kv5nTZoUC1CmwmWCFqT9RE6D7XSgPUh_jF1qskLa2w0rxMSjwruNKbysgRNctZPln7cqQ

Dưới đây là yêu cầu tương tự, sử dụng curl:

curl -d 'grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI3NjEzMjY3OTgwNjktcjVtbGpsbG4xcmQ0bHJiaGc3NWVmZ2lncDM2bTc4ajVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzY29wZSI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2F1dGgvcHJlZGljdGlvbiIsImF1ZCI6Imh0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbS9vL29hdXRoMi90b2tlbiIsImV4cCI6MTMyODU3MzM4MSwiaWF0IjoxMzI4NTY5NzgxfQ.RZVpzWygMLuL-n3GwjW1_yhQhrqDacyvaXkuf8HcJl8EtXYjGjMaW5oiM5cgAaIorrqgYlp4DPF_GuncFqg9uDZrx7pMmCZ_yHfxhSCXru3gbXrZvAIicNQZMFxrEEn4REVuq7DjkTMyCMGCY1dpMa8aWfTQFt3Eh7smLchaZsU
' https://oauth2.googleapis.com/token

Xử lý phản hồi

Nếu yêu cầu mã thông báo truy cập và JWT được tạo đúng cách và tài khoản dịch vụ có quyền để thực hiện thao tác, thì phản hồi JSON qua Máy chủ uỷ quyền sẽ bao gồm mã truy cập. Dưới đây là phản hồi mẫu:

{
  "access_token": "1/8xbJqaOZXSUZbHLl5EOtu1pxz3fmmetKx9W8CV4t79M",
  "scope": "https://www.googleapis.com/auth/prediction"
  "token_type": "Bearer",
  "expires_in": 3600
}

Bạn có thể sử dụng lại mã thông báo truy cập trong khoảng thời gian được chỉ định bằng giá trị expires_in.

Gọi API của Google

Java

Sử dụng đối tượng GoogleCredential để gọi các API của Google bằng cách hoàn tất 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 bằng cách sử dụng đối tượng GoogleCredential. Ví dụ:
    SQLAdmin sqladmin =
        new SQLAdmin.Builder(httpTransport, JSON_FACTORY, credential).build();
  2. Tạo yêu cầu cho 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ụ: để liệt kê các thực thể của cơ sở dữ liệu Cloud SQL trong dự án example-123:
    SQLAdmin.Instances.List instances =
        sqladmin.instances().list("exciting-example-123").execute();

Python

Sử dụng đối tượng Credentials được ủy quyền để gọi các API của Google bằng cách hoàn tất các bước sau:

  1. Xây dựng 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 hàm build kèm theo tên, phiên bản của API và đối tượng Credentials được uỷ quyền. Ví dụ: để gọi phiên bản 1beta3 của API Quản trị Cloud SQL:
    import googleapiclient.discovery
    
    sqladmin = googleapiclient.discovery.build('sqladmin', 'v1beta3', credentials=credentials)
  2. Tạo yêu cầu cho 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ụ: để liệt kê các thực thể của cơ sở dữ liệu Cloud SQL trong dự án example-123:
    response = sqladmin.instances().list(project='exciting-example-123').execute()

HTTP/REST (Hệ thống 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 để gọi API Google thay mặt cho một tài khoản dịch vụ hoặc tài khoản người dùng nhất định nếu API đó đã cấp(các) phạm vi quyền truy cập mà ứng dụng yêu cầu. Để thực hiện việc này, hãy đưa mã truy cập vào một yêu cầu tới API bằng cách thêm giá trị tham số truy vấn access_token hoặc Authorization tiêu đề HTTP Bearer. Khi có thể, bạn nên chọn tiêu đề HTTP vì các chuỗi cụm từ tìm kiếm có xu hướng xuất hiện trong nhật ký máy chủ. Trong hầu hết trường hợp, bạn có thể sử dụng một 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 Files).

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

Ví dụ về HTTP GET

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

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

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

GET https://www.googleapis.com/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ề cách sử dụng 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

Khi mã truy cập hết hạn

Mã truy cập do Máy chủ uỷ quyền Google OAuth 2.0 phát hành sẽ hết hạn sau thời hạn do giá trị expires_in cung cấp. Khi một mã truy cập hết hạn, ứng dụng đó sẽ tạo một WWT khác, ký và yêu cầu một mã truy cập khác.

Mã lỗi JWT

Trường error Trường error_description Ý nghĩa Cách giải quyết
unauthorized_client Unauthorized client or scope in request. Nếu bạn đang cố gắng sử dụng tính năng uỷ quyền trên toàn miền, thì tài khoản dịch vụ đó không được phép sử dụng trong Bảng điều khiển dành cho quản trị viên trên miền của người dùng đó.

Đảm bảo rằng tài khoản dịch vụ đã được ủy quyền trên trang Ủy quyền trên toàn miền của Bảng điều khiển dành cho quản trị viên cho người dùng trong thông báo xác nhận quyền sở hữu sub (trường).

Mặc dù thường mất vài phút, nhưng quá trình uỷ quyền có thể mất tối đa 24 giờ để áp dụng cho tất cả người dùng trong Tài khoản Google của bạn.

unauthorized_client Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested. Tài khoản dịch vụ được uỷ quyền bằng địa chỉ email khách hàng thay vì mã khách hàng (số) trong Bảng điều khiển dành cho quản trị viên. Trên trang Uỷ quyền trên toàn miền trong Bảng điều khiển dành cho quản trị viên, hãy xoá ứng dụng rồi thêm lại bằng mã dạng số.
access_denied (giá trị bất kỳ) Nếu bạn đang dùng tính năng Ủy quyền trên toàn miền, thì một hoặc nhiều phạm vi yêu cầu sẽ không được phép trong Bảng điều khiển dành cho quản trị viên.

Đảm bảo rằng tài khoản dịch vụ được phép trên trang Ủy quyền trên toàn miền của Bảng điều khiển dành cho quản trị viên cho người dùng trong thông báo xác nhận quyền sở hữu sub (trường) và có toàn bộ phạm vi mà bạn yêu cầu trong thông báo xác nhận quyền sở hữu scope của JWT.

Mặc dù thường mất vài phút, nhưng quá trình uỷ quyền có thể mất tối đa 24 giờ để áp dụng cho tất cả người dùng trong Tài khoản Google của bạn.

admin_policy_enforced (giá trị bất kỳ) Tài khoản Google không thể uỷ quyền cho một hoặc nhiều phạm vi yêu cầu theo chính sách của quản trị viên Google Workspace.

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 nội bộ có quyền truy cập vào dữ liệu trên 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 bạn cấp quyền truy cập rõ ràng cho mã ứng dụng khách OAuth.

invalid_client (giá trị bất kỳ)

Ứng dụng OAuth hoặc mã thông báo JWT không hợp lệ hoặc được định cấu hình không chính xác.

Hãy tham khảo nội dung mô tả lỗi để biết thông tin chi tiết.

Đảm bảo mã thông báo JWT là hợp lệ và chứa đúng thông báo xác nhận quyền sở hữu.

Kiểm tra để chắc chắn rằng tài khoản dịch vụ và ứng dụng OAuth được định cấu hình đúng cách và bạn đang sử dụng đúng địa chỉ email.

Kiểm tra để đảm bảo mã thông báo JWT đã chính xác và được cấp cho mã ứng dụng khách trong yêu cầu.

invalid_grant Not a valid email. Người dùng không tồn tại. Kiểm tra để đảm bảo địa chỉ email trong thông báo xác nhận quyền sở hữu sub (trường) là chính xác.
invalid_grant

Invalid JWT: Token must be a short-lived token (60 minutes) and in a reasonable timeframe. Check your 'iat' and 'exp' values and use a clock with skew to account for clock differences between systems.

Thông thường, điều đó có nghĩa là giờ địa phương không chính xác. Điều này cũng có thể xảy ra nếu giá trị exp cách thời điểm hiện tại quá 65 phút từ giá trị iat, hoặc giá trị exp thấp hơn giá trị iat.

Đảm bảo rằng đồng hồ trên hệ thống đã tạo JWT là chính xác. Nếu cần, hãy đồng bộ hoá thời gian của bạn với Google NTP.

invalid_grant Invalid JWT Signature.

Xác nhận JWT được ký bằng một khoá riêng tư không liên kết với tài khoản dịch vụ được xác định qua email khách hàng hoặc khoá được dùng đã bị xoá, vô hiệu hoá hoặc hết hạn.

Ngoài ra, xác nhận JWT có thể được mã hoá không chính xác – phải được mã hoá bằng Base64, không có dòng mới hoặc dấu bằng khoảng đệm.

Giải mã nhóm thông báo xác nhận quyền sở hữu của JWT và xác minh khoá đã ký xác nhận được liên kết với tài khoản dịch vụ.

Hãy thử sử dụng thư viện OAuth do Google cung cấp để đảm bảo JWT được tạo chính xác.

invalid_scope Invalid OAuth scope or ID token audience provided. Không có phạm vi nào được yêu cầu (danh sách phạm vi trống) hoặc một trong các phạm vi được yêu cầu không tồn tại (tức là không hợp lệ).

Hãy đảm bảo rằng scope thông báo xác nhận quyền sở hữu (trường) của JWT được điền sẵn và so sánh các phạm vi của trường đó với các phạm vi được ghi nhận trong các API mà bạn muốn sử dụng, để đảm bảo không có lỗi hoặc lỗi chính tả.

Xin lưu ý rằng danh sách các phạm vi trong thông báo xác nhận quyền sở hữu scope cần được phân tách bằng dấu cách, chứ không phải bằng dấu phẩy.

disabled_client The OAuth client was disabled. Khoá dùng để ký xác nhận JWT đã bị vô hiệu hoá.

Chuyển đến Google API Console, và trong phần IAM & Quản trị > Tài khoản dịch vụ, hãy bật tài khoản dịch vụ có chứa "Mã khoá" dùng để xác nhận.

org_internal This client is restricted to users within its organization. Mã ứng dụng khách OAuth trong yêu cầu này là một phần của 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ể.

Hãy sử dụng một tài khoản dịch vụ của tổ chức để xác thực. Xác nhận cấu hình loại người dùng cho ứng dụng OAuth của bạn.

Phụ lục: Uỷ quyền cho tài khoản dịch vụ không có OAuth

Với một số API của Google, bạn có thể thực hiện các lệnh gọi API được uỷ quyền bằng cách sử dụng JWT đã ký trực tiếp làm mã thông báo truy cập thay vì mã truy cập OAuth 2.0. Khi có thể, bạn có thể tránh phải gửi yêu cầu mạng đến máy chủ uỷ quyền của Google trước khi thực hiện lệnh gọi API.

Nếu API bạn muốn gọi có định nghĩa dịch vụ được xuất bản trong Kho lưu trữ GitHub của Google API, thì bạn có thể thực hiện các lệnh gọi API được ủy quyền bằng cách sử dụng JWT thay vì mã truy cập. Cách làm như sau:

  1. Tạo một tài khoản dịch vụ như mô tả ở trên. Hãy nhớ giữ lại tệp JSON mà bạn nhận được khi tạo tài khoản.
  2. Sử dụng bất kỳ thư viện JWT chuẩn nào, chẳng hạn như thư viện có tại jwt.io, tạo JWT có tiêu đề và trọng tải như ví dụ sau:
    {
      "alg": "RS256",
      "typ": "JWT",
      "kid": "abcdef1234567890"
    }
    .
    {
      "iss": "123456-compute@developer.gserviceaccount.com",
      "sub": "123456-compute@developer.gserviceaccount.com",
      "aud": "https://firestore.googleapis.com/",
      "iat": 1511900000,
      "exp": 1511903600
    }
    • Đối với trường kid trong tiêu đề, hãy chỉ định mã khoá riêng tư của tài khoản dịch vụ. Bạn có thể tìm thấy giá trị này trong trường private_key_id của tệp JSON trong tài khoản dịch vụ.
    • Đối với các trường isssub, hãy chỉ định địa chỉ email tài khoản dịch vụ của bạn. Bạn có thể tìm thấy giá trị này trong trường client_email của tệp JSON trong tài khoản dịch vụ.
    • Đối với trường aud, hãy chỉ định điểm cuối API. Ví dụ: https://SERVICE.googleapis.com/.
    • Đối với trường iat, hãy chỉ định thời gian Unix hiện tại và đối với trường exp, hãy chỉ định thời gian chính xác là 3600 giây sau đó, khi JWT hết hạn.

Ký JWT bằng RSA-256 bằng cách sử dụng khoá riêng tư có trong tệp JSON của tài khoản dịch vụ.

Ví dụ:

Java

Sử dụng google-api-java-clientjava-jwt:

GoogleCredential credential =
        GoogleCredential.fromStream(new FileInputStream("MyProject-1234.json"));
PrivateKey privateKey = credential.getServiceAccountPrivateKey();
String privateKeyId = credential.getServiceAccountPrivateKeyId();

long now = System.currentTimeMillis();

try {
    Algorithm algorithm = Algorithm.RSA256(null, privateKey);
    String signedJwt = JWT.create()
        .withKeyId(privateKeyId)
        .withIssuer("123456-compute@developer.gserviceaccount.com")
        .withSubject("123456-compute@developer.gserviceaccount.com")
        .withAudience("https://firestore.googleapis.com/")
        .withIssuedAt(new Date(now))
        .withExpiresAt(new Date(now + 3600 * 1000L))
        .sign(algorithm);
} catch ...

Python

Sử dụng PyJWT:

iat = time.time()
exp = iat + 3600
payload = {'iss': '123456-compute@developer.gserviceaccount.com',
           'sub': '123456-compute@developer.gserviceaccount.com',
           'aud': 'https://firestore.googleapis.com/',
           'iat': iat,
           'exp': exp}
additional_headers = {'kid': PRIVATE_KEY_ID_FROM_JSON}
signed_jwt = jwt.encode(payload, PRIVATE_KEY_FROM_JSON, headers=additional_headers,
                       algorithm='RS256')
  1. Gọi API bằng mã WWT đã ký làm mã thông báo truy cập:
    GET /v1/projects/abc/databases/123/indexes HTTP/1.1
    Authorization: Bearer SIGNED_JWT
    Host: firestore.googleapis.com