Kết nối OpenID

API OAuth 2.0 của Google có thể dùng để xác thực và uỷ quyền. Tài liệu này mô tả cách triển khai OAuth 2.0 cho hoạt động xác thực, tuân thủ quy cách OpenID Connectđược chứng nhận OpenID. Tài liệu trong bài viết Sử dụng OAuth 2.0 để truy cập API Google cũng áp dụng cho dịch vụ này. Nếu muốn khám phá giao thức này theo cách tương tác, bạn nên sử dụng Google OAuth 2.0 Playground. Để nhận trợ giúp về Stack Overflow, hãy gắn thẻ cho câu hỏi của bạn bằng "google- OAuth".

Thiết lập OAuth 2.0

Trước khi ứng dụng của bạn có thể sử dụng hệ thống xác thực OAuth 2.0 của Google để đăng nhập cho người dùng, bạn phải thiết lập dự án trong Google API Console để lấy thông tin xác thực OAuth 2.0, đặt URI chuyển hướng và tuỳ chỉnh thông tin thương hiệu mà người dùng nhìn thấy trên màn hình lấy sự đồng ý của người dùng. Bạn cũng có thể sử dụng API Console để tạo tài khoản dịch vụ, bật tính năng thanh toán, thiết lập tính năng lọc và làm những việc khác. Để biết thêm thông tin, hãy xem trang Trợ giúp Google API Console.

Lấy thông tin xác thực OAuth 2.0

Bạn cần có thông tin xác thực OAuth 2.0, bao gồm mã ứng dụng khách và mật khẩu ứng dụng khách, để xác thực người dùng và có được quyền truy cập vào các API của Google.

To view the client ID and client secret for a given OAuth 2.0 credential, click the following text: Select credential. In the window that opens, choose your project and the credential you want, then click View.

Or, view your client ID and client secret from the Credentials page in API Console:

  1. Go to the Credentials page.
  2. Click the name of your credential or the pencil () icon. Your client ID and secret are at the top of the page.

Đặt URI chuyển hướng

URI chuyển hướng mà bạn đặt trong API Console sẽ xác định nơi Google gửi phản hồi đến các yêu cầu xác thực của bạn.

To create, view, or edit the redirect URIs for a given OAuth 2.0 credential, do the following:

  1. Go to the Credentials page.
  2. In the OAuth 2.0 client IDs section of the page, click a credential.
  3. View or edit the redirect URIs.

If there is no OAuth 2.0 client IDs section on the Credentials page, then your project has no OAuth credentials. To create one, click Create credentials.

Tuỳ chỉnh màn hình xin phép của người dùng

Đối với người dùng của bạn, trải nghiệm xác thực OAuth 2.0 sẽ bao gồm một màn hình xin phép để mô tả thông tin mà người dùng đang phát hành và các điều khoản áp dụng. Ví dụ: khi đăng nhập, người dùng có thể được yêu cầu cấp cho ứng dụng của bạn quyền truy cập vào địa chỉ email và thông tin tài khoản cơ bản của họ. Bạn yêu cầu quyền truy cập vào thông tin này bằng cách sử dụng thông số scope mà ứng dụng của bạn đã đưa vào yêu cầu xác thực. Bạn cũng có thể sử dụng các phạm vi để yêu cầu quyền truy cập vào các API khác của Google.

Màn hình lấy sự đồng ý của người dùng cũng trình bày thông tin thương hiệu như tên sản phẩm, biểu trưng và URL của trang chủ. Bạn có thể kiểm soát thông tin thương hiệu trong API Console.

To enable your project's consent screen:

  1. Open the Consent Screen page in the Google API Console.
  2. If prompted, select a project, or create a new one.
  3. Fill out the form and click Save.

Hộp thoại đồng ý sau đây hiển thị nội dung mà người dùng sẽ nhìn thấy khi kết hợp phạm vi OAuth 2.0 và Google Drive trong yêu cầu. (Hộp thoại chung này được tạo bằng Google OAuth 2.0 Playground, vì vậy, hộp thoại này không chứa thông tin thương hiệu sẽ được đặt trong API Console.)

Ảnh chụp màn hình trang đồng ý

Truy cập dịch vụ

Google và bên thứ ba cung cấp các thư viện mà bạn có thể dùng để xử lý nhiều chi tiết triển khai liên quan đến quy trình xác thực người dùng và lấy quyền truy cập vào các API của Google. Ví dụ như Dịch vụ nhận dạng của Googlethư viện ứng dụng của Google. Những thư viện này được cung cấp cho nhiều nền tảng.

Nếu bạn chọn không sử dụng thư viện, hãy làm theo hướng dẫn trong phần còn lại của tài liệu này. Phần này mô tả các luồng yêu cầu HTTP không có trong các thư viện có sẵn.

Xác thực người dùng

Việc xác thực người dùng bao gồm cả việc lấy mã nhận dạng và xác thực mã đó. Mã thông báo mã nhận dạng là một tính năng chuẩn của OpenID Connect được thiết kế để sử dụng trong việc chia sẻ các câu nhận định danh tính trên Internet.

Phương pháp thường dùng nhất để xác thực người dùng và lấy mã thông báo mã nhận dạng được gọi là quy trình "máy chủ" và quy trình "ngầm ẩn". Luồng máy chủ cho phép máy chủ phụ trợ của ứng dụng xác minh danh tính của người sử dụng trình duyệt hoặc thiết bị di động. Luồng ngầm ẩn được sử dụng khi ứng dụng phía máy khách (thường là ứng dụng JavaScript chạy trong trình duyệt) cần truy cập trực tiếp vào API thay vì thông qua máy chủ phụ trợ.

Tài liệu này mô tả cách thực hiện quy trình xác thực người dùng trên máy chủ. Luồng ngầm ẩn phức tạp hơn đáng kể do có các rủi ro bảo mật trong việc xử lý và sử dụng mã thông báo ở phía máy khách. Nếu cần triển khai một quy trình ngầm ẩn, bạn nên sử dụng Dịch vụ nhận dạng của Google.

Luồng máy chủ

Hãy nhớ thiết lập ứng dụng của bạn trong API Console để cho phép ứng dụng dùng các giao thức này và xác thực người dùng. Khi người dùng cố gắng đăng nhập bằng Google, bạn cần phải:

  1. Tạo mã thông báo trạng thái chống giả mạo
  2. Gửi yêu cầu xác thực đến Google
  3. Xác nhận mã thông báo trạng thái chống giả mạo
  4. Trao đổi code để lấy mã truy cập và mã thông báo mã nhận dạng
  5. Lấy thông tin người dùng từ mã thông báo mã nhận dạng
  6. Xác thực người dùng

1. Tạo mã thông báo trạng thái chống giả mạo

Bạn phải bảo vệ sự an toàn của người dùng bằng cách ngăn chặn các cuộc tấn công giả mạo yêu cầu. Bước đầu tiên là tạo một mã phiên duy nhất chứa trạng thái giữa ứng dụng của bạn và ứng dụng của người dùng. Sau đó, bạn sẽ so khớp mã thông báo phiên duy nhất này với phản hồi xác thực do dịch vụ Đăng nhập OAuth của Google trả về để xác minh rằng người dùng đang đưa ra yêu cầu chứ không phải là kẻ tấn công độc hại. Những mã thông báo này thường được gọi là mã giả mạo yêu cầu trên nhiều trang web (CSRF).

Một lựa chọn tốt cho mã thông báo trạng thái là một chuỗi gồm 30 ký tự trở lên, được tạo bằng trình tạo số ngẫu nhiên chất lượng cao. Một hàm băm khác là hàm băm được tạo bằng cách ký một số biến trạng thái phiên của bạn bằng một khoá được bảo mật trên máy chủ phụ trợ.

Mã sau đây minh hoạ cách tạo mã phiên duy nhất.

1.199

Bạn phải tải thư viện ứng dụng API của Google cho PHP xuống để sử dụng mẫu này.

// Create a state token to prevent request forgery.
// Store it in the session for later validation.
$state = bin2hex(random_bytes(128/8));
$app['session']->set('state', $state);
// Set the client ID, token state, and application name in the HTML while
// serving it.
return $app['twig']->render('index.html', array(
    'CLIENT_ID' => CLIENT_ID,
    'STATE' => $state,
    'APPLICATION_NAME' => APPLICATION_NAME
));

Java

Bạn phải tải thư viện ứng dụng API của Google cho Java xuống để sử dụng mẫu này.

// Create a state token to prevent request forgery.
// Store it in the session for later validation.
String state = new BigInteger(130, new SecureRandom()).toString(32);
request.session().attribute("state", state);
// Read index.html into memory, and set the client ID,
// token state, and application name in the HTML before serving it.
return new Scanner(new File("index.html"), "UTF-8")
    .useDelimiter("\\A").next()
    .replaceAll("[{]{2}\\s*CLIENT_ID\\s*[}]{2}", CLIENT_ID)
    .replaceAll("[{]{2}\\s*STATE\\s*[}]{2}", state)
    .replaceAll("[{]{2}\\s*APPLICATION_NAME\\s*[}]{2}",
    APPLICATION_NAME);

Python

Bạn phải tải thư viện ứng dụng API của Google cho Python xuống để dùng mẫu này.

# Create a state token to prevent request forgery.
# Store it in the session for later validation.
state = hashlib.sha256(os.urandom(1024)).hexdigest()
session['state'] = state
# Set the client ID, token state, and application name in the HTML while
# serving it.
response = make_response(
    render_template('index.html',
                    CLIENT_ID=CLIENT_ID,
                    STATE=state,
                    APPLICATION_NAME=APPLICATION_NAME))

2. Gửi yêu cầu xác thực đến Google

Bước tiếp theo là tạo một yêu cầu HTTPS GET với tham số URI thích hợp. Xin lưu ý rằng bạn nên sử dụng HTTPS thay vì HTTP trong tất cả các bước của quy trình này; kết nối HTTP bị từ chối. Bạn nên truy xuất URI cơ sở từ Tài liệu khám phá bằng cách sử dụng giá trị siêu dữ liệu authorization_endpoint. Cuộc thảo luận sau đây giả định URI cơ sở là https://accounts.google.com/o/oauth2/v2/auth.

Đối với yêu cầu cơ bản, hãy chỉ định các tham số sau:

  • client_id mà bạn lấy được từ API Console Credentials page.
  • response_type. Giá trị này trong yêu cầu luồng mã uỷ quyền cơ bản phải là code. (Đọc thêm tại response_type.)
  • scope, trong yêu cầu cơ bản phải là openid email. (Đọc thêm tại scope.)
  • redirect_uri phải là điểm cuối HTTP trên máy chủ của bạn và sẽ nhận phản hồi từ Google. Giá trị này phải khớp chính xác với một trong các URI chuyển hướng được uỷ quyền cho ứng dụng OAuth 2.0 mà bạn đã định cấu hình trong API Console Credentials page. Nếu giá trị này không khớp với một URI được uỷ quyền, thì yêu cầu sẽ không thành công do lỗi redirect_uri_mismatch.
  • state phải bao gồm giá trị của mã thông báo phiên duy nhất chống giả mạo, cũng như mọi thông tin cần thiết khác để khôi phục ngữ cảnh khi người dùng quay lại ứng dụng của bạn, chẳng hạn như URL bắt đầu. (Đọc thêm tại state.)
  • nonce là một giá trị ngẫu nhiên do ứng dụng của bạn tạo ra để bật tính năng bảo vệ phát lại khi có.
  • login_hint có thể là địa chỉ email của người dùng hoặc chuỗi sub, tương đương với mã nhận dạng Google của người dùng. Nếu bạn không cung cấp login_hint và người dùng đang đăng nhập, thì màn hình xin phép sẽ hiển thị yêu cầu phê duyệt để phát hành địa chỉ email của người dùng cho ứng dụng của bạn. (Đọc thêm tại login_hint.)
  • Sử dụng tham số hd để tối ưu hoá quy trình OpenID Connect cho người dùng của một miền cụ thể liên kết với một tổ chức Google Workspace hoặc Cloud (đọc thêm tại hd).

Dưới đây là một ví dụ về URI xác thực OpenID Connect hoàn chỉnh, có dấu ngắt dòng và dấu cách để bạn dễ đọc:

https://accounts.google.com/o/oauth2/v2/auth?
 response_type=code&
 client_id=424911365001.apps.googleusercontent.com&
 scope=openid%20email&
 redirect_uri=https%3A//oauth2.example.com/code&
 state=security_token%3D138r5719ru3e1%26url%3Dhttps%3A%2F%2Foauth2-login-demo.example.com%2FmyHome&
 login_hint=jsmith@example.com&
 nonce=0394852-3190485-2490358&
 hd=example.com

Người dùng phải đồng ý nếu ứng dụng của bạn yêu cầu thông tin mới về họ hoặc nếu ứng dụng của bạn yêu cầu quyền truy cập vào tài khoản mà trước đây họ chưa phê duyệt.

3. Xác nhận mã thông báo trạng thái chống giả mạo

Phản hồi được gửi đến redirect_uri mà bạn đã chỉ định trong yêu cầu. Mọi phản hồi đều được trả về trong chuỗi truy vấn, như thể hiện dưới đây:

https://oauth2.example.com/code?state=security_token%3D138r5719ru3e1%26url%3Dhttps%3A%2F%2Foa2cb.example.com%2FmyHome&code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7&scope=openid%20email%20https://www.googleapis.com/auth/userinfo.email

Trên máy chủ, bạn phải xác nhận rằng state nhận được từ Google khớp với mã phiên hoạt động mà bạn đã tạo trong Bước 1. Quá trình xác minh trọn vòng này giúp đảm bảo rằng người dùng đang đưa ra yêu cầu chứ không phải tập lệnh độc hại.

Mã sau đây minh hoạ việc xác nhận mã thông báo phiên mà bạn đã tạo ở Bước 1:

1.199

Bạn phải tải thư viện ứng dụng API của Google cho PHP xuống để sử dụng mẫu này.

// Ensure that there is no request forgery going on, and that the user
// sending us this connect request is the user that was supposed to.
if ($request->get('state') != ($app['session']->get('state'))) {
  return new Response('Invalid state parameter', 401);
}

Java

Bạn phải tải thư viện ứng dụng API của Google cho Java xuống để sử dụng mẫu này.

// Ensure that there is no request forgery going on, and that the user
// sending us this connect request is the user that was supposed to.
if (!request.queryParams("state").equals(
    request.session().attribute("state"))) {
  response.status(401);
  return GSON.toJson("Invalid state parameter.");
}

Python

Bạn phải tải thư viện ứng dụng API của Google cho Python xuống để dùng mẫu này.

# Ensure that the request is not a forgery and that the user sending
# this connect request is the expected user.
if request.args.get('state', '') != session['state']:
  response = make_response(json.dumps('Invalid state parameter.'), 401)
  response.headers['Content-Type'] = 'application/json'
  return response

4. Đổi code để lấy mã truy cập và mã thông báo

Phản hồi này bao gồm tham số code. Mã này là mã uỷ quyền một lần mà máy chủ của bạn có thể đổi lấy mã truy cập và mã thông báo nhận dạng. Máy chủ của bạn thực hiện trao đổi này bằng cách gửi một yêu cầu HTTPS POST. Yêu cầu POST được gửi đến điểm cuối của mã thông báo. Bạn nên truy xuất điểm cuối này từ Tài liệu khám phá bằng cách sử dụng giá trị siêu dữ liệu token_endpoint. Cuộc thảo luận sau đây giả định điểm cuối là https://oauth2.googleapis.com/token. Yêu cầu phải bao gồm các tham số sau trong phần nội dung POST:

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

Yêu cầu thực tế có thể giống như ví dụ sau:

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

Phản hồi thành công cho yêu cầu này chứa các trường sau trong mảng JSON:

Các trường
access_token Mã thông báo có thể được gửi tới một API của Google.
expires_in Thời gian tồn tại còn lại của mã truy cập tính bằng giây.
id_token Một JWT chứa thông tin nhận dạng của người dùng được Google ký dưới dạng chữ ký số.
scope Phạm vi truy cập do access_token cấp được biểu thị dưới dạng danh sách các chuỗi được phân tách bằng dấu cách và phân biệt chữ hoa chữ thường.
token_type Xác định loại mã thông báo được trả về. Hiện tại, trường này luôn có giá trị Bearer.
refresh_token (không bắt buộc)

Trường này chỉ xuất hiện nếu thông số access_type được đặt thành offline trong yêu cầu xác thực. Để biết thông tin chi tiết, hãy xem phần Làm mới mã thông báo.

5. Lấy thông tin người dùng từ mã thông báo mã nhận dạng

Mã thông báo mã nhận dạng là một JWT (Mã thông báo web JSON), tức là một đối tượng JSON được mã hoá Base64 được mã hoá. Thông thường, điều quan trọng là bạn phải xác thực mã thông báo mã nhận dạng trước khi sử dụng. Tuy nhiên, vì bạn đang giao tiếp trực tiếp với Google qua kênh HTTPS không có trung gian và sử dụng mật khẩu ứng dụng khách để xác thực bạn với Google, nên bạn có thể yên tâm rằng mã thông báo mà bạn nhận được thực sự là do Google cung cấp và hợp lệ. Nếu máy chủ của bạn chuyển mã thông báo mã nhận dạng đến các thành phần khác trong ứng dụng, điều cực kỳ quan trọng là các thành phần khác phải xác thực mã thông báo trước khi sử dụng.

Vì hầu hết các thư viện API đều kết hợp việc xác thực với hoạt động giải mã các giá trị được mã hoá base64url và phân tích cú pháp JSON trong đó, nên có thể bạn vẫn sẽ xác thực mã thông báo khi truy cập vào các xác nhận quyền sở hữu trong mã thông báo mã nhận dạng.

Tải trọng của mã thông báo giá trị nhận dạng

Mã thông báo mã nhận dạng là một đối tượng JSON chứa một tập hợp các cặp tên/giá trị. Sau đây là ví dụ được định dạng để dễ đọc:

{
  "iss": "https://accounts.google.com",
  "azp": "1234987819200.apps.googleusercontent.com",
  "aud": "1234987819200.apps.googleusercontent.com",
  "sub": "10769150350006150715113082367",
  "at_hash": "HK6E_P6Dh8Y93mRNtsDB1Q",
  "hd": "example.com",
  "email": "jsmith@example.com",
  "email_verified": "true",
  "iat": 1353601026,
  "exp": 1353604926,
  "nonce": "0394852-3190485-2490358"
}

Mã thông báo nhận dạng của Google có thể chứa các trường sau (được gọi là thông báo xác nhận quyền sở hữu):

Claim Đã cung cấp Nội dung mô tả
aud mọi lúc Đối tượng mà mã thông báo mã nhận dạng này dành cho. Đó phải là một trong các mã ứng dụng khách OAuth 2.0 của ứng dụng.
exp mọi lúc Thời gian hết hạn vào hoặc sau đó mã thông báo nhận dạng không được chấp nhận. Được biểu thị bằng thời gian Unix (giây nguyên).
iat mọi lúc Thời điểm phát hành mã thông báo nhận dạng. Được biểu thị bằng thời gian Unix (giây nguyên).
iss mọi lúc Giá trị nhận dạng nhà phát hành của phản hồi. Luôn là https://accounts.google.com hoặc accounts.google.com đối với mã thông báo giá trị nhận dạng của Google.
sub mọi lúc Giá trị nhận dạng của người dùng, duy nhất trong số tất cả các Tài khoản Google và không bao giờ được sử dụng lại. Một Tài khoản Google có thể có nhiều địa chỉ email tại các thời điểm khác nhau, nhưng giá trị sub sẽ không bao giờ thay đổi. Sử dụng sub trong ứng dụng của bạn làm khoá giá trị nhận dạng duy nhất cho người dùng. Độ dài tối đa là 255 ký tự ASCII phân biệt chữ hoa chữ thường.
at_hash Hàm băm mã truy cập. Cung cấp thông tin xác thực rằng mã truy cập được liên kết với mã thông báo nhận dạng. Nếu mã thông báo nhận dạng được phát hành kèm theo giá trị access_token trong quy trình của máy chủ, thì thông báo xác nhận quyền sở hữu này sẽ luôn được đưa vào. Thông báo xác nhận quyền sở hữu này có thể được dùng như một cơ chế thay thế để ngăn chặn các cuộc tấn công giả mạo yêu cầu trên nhiều trang web. Tuy nhiên, nếu làm theo Bước 1Bước 3 thì bạn không cần phải xác minh mã truy cập.
azp client_id của người trình bày được uỷ quyền. Thông báo xác nhận quyền sở hữu này chỉ cần thiết khi bên yêu cầu mã thông báo giá trị nhận dạng không giống với đối tượng của mã thông báo giá trị nhận dạng đó. Đây có thể là trường hợp tại Google đối với các ứng dụng kết hợp, trong đó một ứng dụng web và ứng dụng Android có client_id OAuth 2.0 khác nhau nhưng có cùng một dự án API Google.
email Địa chỉ email của người dùng. Chỉ được cung cấp nếu bạn đưa phạm vi email vào yêu cầu của mình. Giá trị của thông báo xác nhận quyền sở hữu này có thể không phải là giá trị của riêng tài khoản này và có thể thay đổi theo thời gian. Do đó, bạn không nên dùng giá trị này làm giá trị nhận dạng chính để liên kết đến hồ sơ người dùng của mình. Bạn cũng không thể dựa vào miền của thông báo xác nhận quyền sở hữu email để xác định người dùng của các tổ chức Google Workspace hoặc Cloud. Thay vào đó, hãy sử dụng thông báo xác nhận quyền sở hữu hd.
email_verified Đúng nếu địa chỉ email của người dùng đã được xác minh; nếu không thì sai.
family_name Họ của người dùng. Có thể được cung cấp khi có thông báo xác nhận quyền sở hữu name.
given_name Tên hoặc tên của người dùng. Có thể được cung cấp khi có thông báo xác nhận quyền sở hữu name.
hd Miền liên kết với tổ chức Google Workspace hoặc tổ chức trên Cloud của người dùng. Chỉ được cung cấp nếu người dùng thuộc một tổ chức trên Google Cloud. Bạn phải đánh dấu vào thông báo xác nhận quyền sở hữu này khi chỉ cho phép các thành viên của một số miền truy cập vào tài nguyên. Việc không có xác nhận quyền sở hữu này cho biết rằng tài khoản không thuộc về tên miền do Google lưu trữ.
locale Ngôn ngữ của người dùng, được biểu thị bằng thẻ ngôn ngữ BCP 47. Có thể được cung cấp khi có thông báo xác nhận quyền sở hữu name.
name Tên đầy đủ của người dùng, ở dạng hiển thị được. Có thể được cung cấp khi:
  • Phạm vi yêu cầu bao gồm chuỗi "hồ sơ"
  • Mã thông báo nhận dạng được trả về khi làm mới mã thông báo

Khi có thông báo xác nhận quyền sở hữu name, bạn có thể sử dụng các thông báo này để cập nhật hồ sơ người dùng của ứng dụng. Lưu ý rằng chúng tôi không bao giờ đảm bảo rằng thông báo xác nhận quyền sở hữu này sẽ có.

nonce Giá trị của nonce mà ứng dụng của bạn cung cấp trong yêu cầu xác thực. Bạn nên thực thi biện pháp bảo vệ khỏi các cuộc tấn công phát lại bằng cách đảm bảo rằng cuộc tấn công chỉ xuất hiện một lần.
picture URL ảnh hồ sơ của người dùng. Có thể được cung cấp khi:
  • Phạm vi yêu cầu bao gồm chuỗi "hồ sơ"
  • Mã thông báo nhận dạng được trả về khi làm mới mã thông báo

Khi có thông báo xác nhận quyền sở hữu picture, bạn có thể sử dụng các thông báo này để cập nhật hồ sơ người dùng của ứng dụng. Lưu ý rằng chúng tôi không bao giờ đảm bảo rằng thông báo xác nhận quyền sở hữu này sẽ có.

profile URL trang hồ sơ của người dùng. Có thể được cung cấp khi:
  • Phạm vi yêu cầu bao gồm chuỗi "hồ sơ"
  • Mã thông báo nhận dạng được trả về khi làm mới mã thông báo

Khi có thông báo xác nhận quyền sở hữu profile, bạn có thể sử dụng các thông báo này để cập nhật hồ sơ người dùng của ứng dụng. Lưu ý rằng chúng tôi không bao giờ đảm bảo rằng thông báo xác nhận quyền sở hữu này sẽ có.

6. Xác thực người dùng

Sau khi lấy thông tin người dùng từ mã thông báo mã nhận dạng, bạn nên truy vấn cơ sở dữ liệu người dùng của ứng dụng. Nếu người dùng đã tồn tại trong cơ sở dữ liệu của bạn, thì bạn nên bắt đầu phiên đăng ký cho người dùng đó nếu phản hồi API của Google đáp ứng tất cả các yêu cầu đăng nhập.

Nếu người dùng không tồn tại trong cơ sở dữ liệu người dùng của bạn, bạn nên chuyển hướng người dùng đó đến quy trình đăng ký của người dùng mới. Bạn có thể tự động đăng ký người dùng dựa trên thông tin bạn nhận được từ Google, hoặc ít nhất bạn có thể điền sẵn nhiều trường mà bạn yêu cầu trên biểu mẫu đăng ký của mình. Ngoài thông tin trong mã thông báo mã nhận dạng, bạn có thể lấy thêm thông tin hồ sơ người dùng tại các điểm cuối hồ sơ người dùng của chúng tôi.

Chủ đề nâng cao

Các phần sau đây sẽ mô tả chi tiết hơn về API Google OAuth 2.0. Thông tin này là dành cho những nhà phát triển có yêu cầu nâng cao về việc xác thực và uỷ quyền.

Quyền truy cập vào các API khác của Google

Một trong những ưu điểm của việc sử dụng OAuth 2.0 để xác thực là ứng dụng có thể được người dùng cấp quyền sử dụng các API khác của Google (chẳng hạn như YouTube, Google Drive, Lịch hoặc Danh bạ) cùng lúc khi bạn xác thực người dùng. Để làm việc này, hãy thêm các phạm vi khác mà bạn cần vào yêu cầu xác thực mà bạn gửi tới Google. Ví dụ: để thêm nhóm tuổi của người dùng vào yêu cầu xác thực, hãy chuyển tham số phạm vi là openid email https://www.googleapis.com/auth/profile.agerange.read. Người dùng sẽ nhận được lời nhắc thích hợp trên màn hình lấy sự đồng ý. Mã truy cập mà bạn nhận lại từ Google cho phép bạn truy cập vào tất cả API liên quan đến phạm vi truy cập mà bạn đã yêu cầu và đã được cấp.

Làm mới mã thông báo

Trong yêu cầu cấp quyền truy cập API, bạn có thể yêu cầu trả về một mã làm mới trong quá trình trao đổi code. Mã làm mới cấp cho ứng dụng của bạn quyền truy cập liên tục vào các API của Google khi người dùng không có mặt trong ứng dụng của bạn. Để yêu cầu mã làm mới, hãy thêm tham số access_type thành offline trong yêu cầu xác thực của bạn.

Những điều cần lưu ý:

  • Hãy nhớ lưu trữ mã làm mới một cách an toàn và vĩnh viễn vì bạn chỉ có thể lấy mã làm mới vào lần đầu tiên thực hiện quy trình trao đổi mã.
  • Có giới hạn về số lượng mã làm mới được cấp: một giới hạn cho mỗi tổ hợp ứng dụng/người dùng và một giới hạn khác cho mỗi người dùng trên tất cả các ứng dụng. 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ể đạt đến các giới hạn này. Trong trường hợp đó, mã làm mới cũ hơn sẽ ngừng hoạt động.

Để biết thêm thông tin, hãy xem phần Làm mới mã truy cập (truy cập ngoại tuyến).

Bạn có thể nhắc người dùng uỷ quyền lại cho ứng dụng bằng cách đặt tham số prompt thành consent trong yêu cầu xác thực. Khi bạn đưa prompt=consent vào, màn hình xin phép sẽ hiển thị mỗi khi ứng dụng của bạn yêu cầu cấp quyền cho các phạm vi truy cập, ngay cả khi tất cả các phạm vi đã được cấp trước đó cho dự án API của Google. Vì lý do này, chỉ thêm prompt=consent khi cần thiết.

Để biết thêm về tham số prompt, hãy xem prompt trong bảng Tham số URI xác thực.

Tham số URI xác thực

Bảng sau đây cung cấp nội dung mô tả đầy đủ hơn về các tham số được API xác thực OAuth 2.0 của Google chấp nhận.

Thông số Bắt buộc Nội dung mô tả
client_id (Bắt buộc) Chuỗi mã ứng dụng khách mà bạn lấy được từ API Console Credentials page, như mô tả trong phần Lấy thông tin xác thực OAuth 2.0.
nonce (Bắt buộc) Một giá trị ngẫu nhiên do ứng dụng của bạn tạo ra để bật tính năng bảo vệ phát lại.
response_type (Bắt buộc) Nếu giá trị là code, hãy chạy một Quy trình mã uỷ quyền cơ bản, yêu cầu phải có POST đến điểm cuối của mã thông báo để lấy mã thông báo. Nếu giá trị là token id_token hoặc id_token token, hãy chạy một Luồng ngầm ẩn, yêu cầu sử dụng JavaScript tại URI chuyển hướng để truy xuất mã thông báo từ giá trị nhận dạng #fragment của URI.
redirect_uri (Bắt buộc) Xác định nơi gửi phản hồi. Giá trị của thông số này phải khớp chính xác với một trong các giá trị chuyển hướng được uỷ quyền mà bạn đã đặt trong API Console Credentials page (bao gồm cả lược đồ HTTP hoặc HTTPS, chữ hoa chữ thường và dấu "/" ở cuối, nếu có).
scope (Bắt buộc)

Thông số phạm vi phải bắt đầu bằng giá trị openid, sau đó bao gồm giá trị profile, giá trị email hoặc cả hai.

Nếu có giá trị phạm vi profile, mã thông báo mã nhận dạng có thể (nhưng không đảm bảo) bao gồm các thông báo xác nhận quyền sở hữu profile mặc định của người dùng.

Nếu có giá trị phạm vi email, thì mã thông báo mã nhận dạng sẽ bao gồm các thông báo xác nhận quyền sở hữu emailemail_verified.

Ngoài các phạm vi dành riêng cho OpenID này, đối số phạm vi của bạn cũng có thể bao gồm các giá trị phạm vi khác. Tất cả giá trị phạm vi phải được phân tách bằng dấu cách. Ví dụ: nếu bạn muốn mỗi tệp đều có quyền truy cập vào Google Drive của người dùng, thì tham số phạm vi của bạn có thể là openid profile email https://www.googleapis.com/auth/drive.file.

Để biết thông tin về các phạm vi có sẵn, hãy xem bài viết Các phạm vi OAuth 2.0 cho API Google hoặc tài liệu về API Google mà bạn muốn sử dụng.

state (Không bắt buộc, nhưng bạn nên dùng)

Một chuỗi mờ bị loại bỏ làm tròn trong giao thức; nghĩa là chuỗi này được trả về dưới dạng tham số URI trong luồng cơ bản và trong giá trị nhận dạng URI #fragment trong luồng ngầm ẩn.

state có thể hữu ích cho việc liên kết yêu cầu và phản hồi. Vì có thể đoán được redirect_uri, nên việc sử dụng giá trị state có thể giúp tăng cường đảm bảo rằng kết nối đến là kết quả của một yêu cầu xác thực do ứng dụng của bạn khởi tạo. Nếu bạn tạo một chuỗi ngẫu nhiên hoặc mã hoá hàm băm của một số trạng thái ứng dụng (ví dụ: cookie) trong biến state này, thì bạn có thể xác thực phản hồi nhằm đả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. Điều này giúp ngăn chặn các cuộc tấn công, chẳng hạn như giả mạo yêu cầu trên nhiều trang web.

access_type (Không bắt buộc) Giá trị được phép là offlineonline. Hiệu ứng này được ghi lại trong phần Truy cập ngoại tuyến; nếu mã truy cập đang được yêu cầu, thì ứng dụng sẽ không nhận được mã làm mới trừ phi giá trị offline được chỉ định.
display (Không bắt buộc) Giá trị chuỗi ASCII để chỉ định cách máy chủ uỷ quyền hiển thị các trang giao diện người dùng xác thực và sự đồng ý. Các giá trị sau được chỉ định và được máy chủ Google chấp nhận nhưng không có bất kỳ ảnh hưởng nào đến hoạt động của các giá trị đó: page, popup, touchwap.
hd (Không bắt buộc)

Đơn giản hoá quy trình đăng nhập cho tài khoản do một tổ chức trên Google Cloud sở hữu. Khi thêm miền tổ chức Google Cloud (ví dụ: mycollege.edu), bạn có thể cho biết rằng giao diện người dùng chọn tài khoản cần được tối ưu hoá cho các tài khoản ở miền đó. Để tối ưu hoá cho tài khoản của tổ chức Google Cloud nói chung thay vì chỉ một miền của tổ chức trên Google Cloud, hãy đặt giá trị của dấu hoa thị (*): hd=*.

Đừng dựa vào tính năng tối ưu hoá giao diện người dùng này để kiểm soát những người có thể truy cập vào ứng dụng của bạn, vì các yêu cầu phía máy khách có thể được sửa đổi. Hãy nhớ validate để đảm bảo rằng mã thông báo nhận dạng được trả về có giá trị xác nhận quyền sở hữu hd khớp với giá trị bạn mong đợi (ví dụ: mycolledge.edu). Không giống như tham số yêu cầu, thông báo xác nhận quyền sở hữu mã thông báo nhận dạng hd có trong một mã thông báo bảo mật của Google, do đó giá trị này có thể đáng tin cậy.

include_granted_scopes (Không bắt buộc) Nếu tham số này được cung cấp với giá trị true và yêu cầu uỷ quyền đã được cấp, thì yêu cầu uỷ quyền sẽ bao gồm mọi khoản uỷ quyền trước đó đã được cấp cho tổ hợp người dùng/ứng dụng này trong các phạm vi khác; hãy xem phần Uỷ quyền gia tăng.

Xin lưu ý rằng bạn không thể thực hiện việc uỷ quyền gia tăng thông qua quy trình Ứng dụng đã cài đặt.

login_hint (Không bắt buộc) Khi biết người dùng nào đang cố gắng xác thực, ứng dụng của bạn có thể cung cấp tham số này dưới dạng một gợi ý cho máy chủ xác thực. Việc chuyển gợi ý này sẽ ngăn trình chọn tài khoản và điền sẵn vào hộp email trên biểu mẫu đăng nhập hoặc chọn phiên thích hợp (nếu người dùng đang sử dụng tính năng đăng nhập nhiều tài khoản), nhờ đó, bạn có thể tránh các sự cố xảy ra nếu ứng dụng của bạn đăng nhập sai tài khoản người dùng. Giá trị này có thể là địa chỉ email hoặc chuỗi sub, tương đương với mã nhận dạng Google của người dùng.
prompt (Không bắt buộc) Danh sách các giá trị chuỗi được phân tách bằng dấu cách sẽ chỉ định xem máy chủ uỷ quyền có nhắc người dùng xác thực lại và đồng ý hay không. Các giá trị có thể sử dụng là:
  • none

    Máy chủ uỷ quyền không hiển thị bất kỳ màn hình xác thực hay màn hình đồng ý nào của người dùng. Máy chủ này sẽ trả về lỗi nếu người dùng chưa được xác thực và chưa định cấu hình trước sự đồng ý cho các phạm vi được yêu cầu. Bạn có thể sử dụng none để kiểm tra quy trình xác thực và/hoặc sự đồng ý hiện có.

  • consent

    Máy chủ uỷ quyền sẽ nhắc người dùng đồng ý trước khi trả về thông tin cho ứng dụng.

  • select_account

    Máy chủ uỷ quyền sẽ nhắc người dùng chọn một tài khoản người dùng. Điều này cho phép người dùng có nhiều tài khoản tại máy chủ uỷ quyền có thể chọn trong số nhiều tài khoản mà họ có thể đang có phiên hoạt động.

Nếu bạn không chỉ định giá trị nào và trước đó chưa cấp quyền truy cập, thì người dùng sẽ thấy màn hình xin phép.

Xác thực mã thông báo nhận dạng

Bạn cần xác thực tất cả các mã thông báo mã nhận dạng trên máy chủ của mình trừ phi bạn biết rằng các mã này đến trực tiếp từ Google. Ví dụ: máy chủ của bạn phải xác minh là mã thông báo nhận dạng đáng tin cậy mà máy chủ nhận được từ các ứng dụng khách.

Sau đây là những tình huống phổ biến mà bạn có thể gửi mã thông báo mã nhận dạng đến máy chủ của mình:

  • Gửi mã thông báo nhận dạng có yêu cầu cần xác thực. Mã thông báo mã nhận dạng cho bạn biết người dùng cụ thể đưa ra yêu cầu và mã thông báo được cấp cho ứng dụng nào.

Mã thông báo giá trị nhận dạng có tính nhạy cảm và có thể bị sử dụng sai mục đích nếu bị chặn. Bạn phải đảm bảo rằng các mã thông báo này được xử lý an toàn bằng cách chỉ truyền mã qua HTTPS và chỉ qua dữ liệu POST hoặc trong tiêu đề của yêu cầu. Nếu lưu trữ mã thông báo nhận dạng trên máy chủ của mình, bạn cũng phải lưu trữ mã thông báo một cách an toàn.

Mã thông báo giá trị nhận dạng có một điều hữu ích là bạn có thể truyền mã này qua nhiều thành phần của ứng dụng. Các thành phần này có thể dùng mã thông báo giá trị nhận dạng làm cơ chế xác thực đơn giản để xác thực ứng dụng và người dùng. Tuy nhiên, trước khi có thể sử dụng thông tin trong mã nhận dạng hoặc dựa vào thông tin đó làm câu nhận định mà người dùng đã xác thực, bạn phải xác thực thông tin đó.

Việc xác thực mã thông báo giá trị nhận dạng yêu cầu một số bước:

  1. Xác minh rằng tổ chức phát hành đã ký đúng mã thông báo nhận dạng. Mã thông báo do Google cấp được ký bằng một trong các chứng chỉ có tại URI được chỉ định trong giá trị siêu dữ liệu jwks_uri của Tài liệu khám phá.
  2. Xác minh rằng giá trị của thông báo xác nhận quyền sở hữu iss trong mã thông báo mã nhận dạng là https://accounts.google.com hoặc accounts.google.com.
  3. Xác minh rằng giá trị của thông báo xác nhận quyền sở hữu aud trong mã thông báo mã nhận dạng bằng với mã ứng dụng khách của ứng dụng.
  4. Xác minh rằng chưa đến thời gian hết hạn (xác nhận quyền sở hữu exp) của mã thông báo giá trị nhận dạng.
  5. Nếu bạn đã chỉ định một giá trị thông số hd trong yêu cầu, hãy xác minh rằng mã thông báo mã nhận dạng có xác nhận quyền sở hữu hd khớp với miền được chấp nhận liên kết với một tổ chức trên Google Cloud.

Các bước từ 2 đến 5 chỉ liên quan đến các phép so sánh chuỗi và ngày khá đơn giản. Vì vậy, chúng tôi sẽ không trình bày chi tiết ở đây.

Bước đầu tiên phức tạp hơn và liên quan đến việc kiểm tra chữ ký bằng mật mã. Đối với mục đích gỡ lỗi, bạn có thể sử dụng điểm cuối tokeninfo của Google để so sánh với quá trình xử lý cục bộ được triển khai trên máy chủ hoặc thiết bị của bạn. Giả sử giá trị của mã thông báo giá trị nhận dạng của bạn là XYZ123. Sau đó, bạn sẽ huỷ tham chiếu URI https://oauth2.googleapis.com/tokeninfo?id_token=XYZ123. Nếu chữ ký mã thông báo hợp lệ, phản hồi sẽ là tải trọng JWT trong dạng đối tượng JSON đã giải mã.

Điểm cuối tokeninfo rất hữu ích cho việc gỡ lỗi, nhưng đối với mục đích phát hành chính thức, hãy truy xuất khoá công khai của Google từ điểm cuối khoá và thực hiện xác thực cục bộ. Bạn nên truy xuất URI khoá trong Tài liệu khám phá bằng cách sử dụng giá trị siêu dữ liệu jwks_uri. Các yêu cầu đến điểm cuối gỡ lỗi có thể bị điều tiết hoặc gặp lỗi không liên tục.

Vì Google không thường xuyên thay đổi khoá công khai, nên bạn có thể lưu các khoá này vào bộ nhớ đệm bằng cách sử dụng các lệnh trong bộ nhớ đệm của phản hồi HTTP. Trong phần lớn trường hợp, hãy thực hiện việc xác thực cục bộ hiệu quả hơn nhiều so với việc sử dụng điểm cuối tokeninfo. Quá trình xác thực này yêu cầu truy xuất và phân tích cú pháp các chứng chỉ, đồng thời thực hiện các lệnh gọi mã hoá thích hợp để kiểm tra chữ ký. Thật may là có các thư viện được gỡ lỗi tốt bằng nhiều ngôn ngữ để làm việc này (xem jwt.io).

Lấy thông tin hồ sơ người dùng

Để có thêm thông tin hồ sơ về người dùng, bạn có thể sử dụng mã truy cập (ứng dụng của bạn nhận được trong quy trình xác thực) và tiêu chuẩn OpenID Connect:

  1. Để tuân thủ OpenID, bạn phải đưa các giá trị phạm vi openid profile vào yêu cầu xác thực của mình.

    Nếu muốn bao gồm địa chỉ email của người dùng, bạn có thể chỉ định một giá trị phạm vi bổ sung là email. Để chỉ định cả profileemail, bạn có thể đưa tham số sau vào URI yêu cầu xác thực:

    scope=openid%20profile%20email
  2. Thêm mã truy cập của bạn vào tiêu đề uỷ quyền và gửi yêu cầu GET HTTPS đến điểm cuối thông tin người dùng. Bạn nên truy xuất điểm cuối này từ Tài liệu khám phá bằng cách sử dụng giá trị siêu dữ liệu userinfo_endpoint. Phản hồi trong thông tin người dùng bao gồm thông tin về người dùng, như mô tả trong OpenID Connect Standard Claims và giá trị siêu dữ liệu claims_supported của tài liệu Khám phá. Người dùng hoặc tổ chức của họ có thể chọn cung cấp hoặc giữ lại một số trường nhất định. Vì vậy, bạn có thể không nhận được thông tin về mọi trường trong phạm vi truy cập được cấp phép.

Tài liệu khám phá

Giao thức OpenID Connect yêu cầu sử dụng nhiều điểm cuối để xác thực người dùng và để yêu cầu tài nguyên bao gồm mã thông báo, thông tin người dùng và khóa công khai.

Để đơn giản hoá quá trình triển khai và tăng tính linh hoạt, OpenID Connect cho phép sử dụng "Tài liệu khám phá", tài liệu JSON được tìm thấy tại một vị trí nổi tiếng chứa các cặp khoá-giá trị, cung cấp thông tin chi tiết về cấu hình của nhà cung cấp OpenID Connect, bao gồm URI của điểm cuối uỷ quyền, mã thông báo, thu hồi, thông tin người dùng và khoá công khai. Tài liệu Khám phá cho dịch vụ OpenID Connect của Google có thể được truy xuất từ:

https://accounts.google.com/.well-known/openid-configuration

Để sử dụng các dịch vụ OpenID Connect của Google, bạn nên mã hóa cứng URI tài liệu Khám phá (https://accounts.google.com/.well-known/openid-configuration) vào ứng dụng của mình. Ứng dụng của bạn tìm nạp tài liệu, áp dụng quy tắc lưu vào bộ nhớ đệm trong phản hồi, sau đó truy xuất URI điểm cuối qua tài liệu đó khi cần. Ví dụ: để xác thực người dùng, mã của bạn sẽ truy xuất giá trị siêu dữ liệu authorization_endpoint (https://accounts.google.com/o/oauth2/v2/auth trong ví dụ bên dưới) làm URI cơ sở cho các yêu cầu xác thực được gửi đến Google.

Sau đây là ví dụ về một tài liệu như vậy. Tên trường sẽ được chỉ định trong OpenID Connect Discovery 1.0 (hãy tham khảo tài liệu này để biết ý nghĩa của chúng). Các giá trị này chỉ mang tính chất minh hoạ và có thể thay đổi, mặc dù các giá trị này được sao chép từ một phiên bản gần đây của tài liệu thực tế về Google Khám phá:

{
  "issuer": "https://accounts.google.com",
  "authorization_endpoint": "https://accounts.google.com/o/oauth2/v2/auth",
  "device_authorization_endpoint": "https://oauth2.googleapis.com/device/code",
  "token_endpoint": "https://oauth2.googleapis.com/token",
  "userinfo_endpoint": "https://openidconnect.googleapis.com/v1/userinfo",
  "revocation_endpoint": "https://oauth2.googleapis.com/revoke",
  "jwks_uri": "https://www.googleapis.com/oauth2/v3/certs",
  "response_types_supported": [
    "code",
    "token",
    "id_token",
    "code token",
    "code id_token",
    "token id_token",
    "code token id_token",
    "none"
  ],
  "subject_types_supported": [
    "public"
  ],
  "id_token_signing_alg_values_supported": [
    "RS256"
  ],
  "scopes_supported": [
    "openid",
    "email",
    "profile"
  ],
  "token_endpoint_auth_methods_supported": [
    "client_secret_post",
    "client_secret_basic"
  ],
  "claims_supported": [
    "aud",
    "email",
    "email_verified",
    "exp",
    "family_name",
    "given_name",
    "iat",
    "iss",
    "locale",
    "name",
    "picture",
    "sub"
  ],
  "code_challenge_methods_supported": [
    "plain",
    "S256"
  ]
}

Bạn có thể tránh hiện tượng HTTP khứ hồi bằng cách lưu các giá trị từ tài liệu Khám phá vào bộ nhớ đệm. Bạn nên sử dụng tiêu đề bộ nhớ đệm tiêu chuẩn của bộ nhớ đệm HTTP.

Thư viện ứng dụng

Các thư viện ứng dụng sau đây giúp việc triển khai OAuth 2.0 trở nên đơn giản hơn bằng cách tích hợp với các khung phổ biến:

Tuân thủ OpenID Connect

Hệ thống xác thực OAuth 2.0 của Google hỗ trợ các tính năng bắt buộc của thông số kỹ thuật OpenID Connect Core. Mọi ứng dụng được thiết kế để hoạt động với OpenID Connect đều phải tương tác với dịch vụ này (ngoại trừ Đối tượng yêu cầu OpenID).