Tài liệu này mô tả OAuth 2.0, thời điểm sử dụng, cách lấy mã ứng dụng và cách sử dụng OAuth 2.0 với Thư viện ứng dụng Google API cho .NET.
Giao thức OAuth 2.0
OAuth 2.0 là giao thức uỷ quyền mà các API của Google sử dụng. Bạn nên làm quen với giao thức này bằng cách đọc các đường liên kết sau:
Thu thập mã ứng dụng khách và khoá bí mật
Bạn có thể lấy mã ứng dụng và mã xác thực trên Google API Console. Có nhiều loại mã ứng dụng khách, vì vậy, hãy nhớ chọn đúng loại cho ứng dụng của bạn:
- Mã ứng dụng khách ứng dụng web
- Mã ứng dụng khách Ứng dụng đã cài đặt
- Mã ứng dụng của tài khoản dịch vụ
Trong mỗi đoạn mã được hiển thị (ngoại trừ đoạn mã Tài khoản dịch vụ), bạn phải tải khoá bí mật ứng dụng xuống và lưu trữ dưới dạng client_secrets.json
trong dự án.
Thông tin xác thực
Thông tin xác thực người dùng
UserCredential
là một lớp trợ giúp an toàn cho luồng để sử dụng mã thông báo truy cập nhằm truy cập vào các tài nguyên được bảo vệ.
Mã thông báo truy cập thường hết hạn sau 1 giờ, sau đó bạn sẽ gặp lỗi nếu cố gắng sử dụng mã đó.
UserCredential
và AuthorizationCodeFlow
sẽ tự động "làm mới" mã thông báo, tức là nhận mã truy cập mới.
Việc này được thực hiện bằng mã làm mới có thời hạn dài mà bạn nhận được cùng với mã truy cập nếu sử dụng tham số access_type=offline
trong quy trình mã uỷ quyền.
Trong hầu hết các ứng dụng, bạn nên lưu trữ mã thông báo truy cập và mã thông báo làm mới của thông tin xác thực trong bộ nhớ cố định. Nếu không, bạn sẽ cần hiển thị cho người dùng cuối một trang uỷ quyền trong trình duyệt mỗi giờ, vì mã thông báo truy cập sẽ hết hạn một giờ sau khi bạn nhận được mã đó.
Để đảm bảo mã truy cập và mã làm mới vẫn tồn tại, bạn có thể tự triển khai IDataStore
hoặc sử dụng một trong các phương thức triển khai sau do thư viện cung cấp:
-
FileDataStore
cho .NET đảm bảo rằng thông tin xác thực sẽ tồn tại trong tệp.
ServiceAccountCredential
ServiceAccountCredential
tương tự như UserCredential
, nhưng có mục đích khác.
Google OAuth 2.0 hỗ trợ các hoạt động tương tác giữa máy chủ với máy chủ, chẳng hạn như giữa một ứng dụng web và Google Cloud Storage.
Ứng dụng yêu cầu phải chứng minh danh tính của chính nó để có quyền truy cập vào API và người dùng cuối không cần phải tham gia.
ServiceAccountCredential
lưu trữ một khoá riêng tư dùng để ký yêu cầu nhận mã thông báo truy cập mới.
Cả UserCredential
và ServiceAccountCredential
đều triển khai IConfigurableHttpClientInitializer
, vì vậy, bạn có thể đăng ký từng lớp này như sau:
- Trình xử lý phản hồi không thành công, vì vậy, trình xử lý này sẽ làm mới mã thông báo nếu nhận được mã trạng thái HTTP
401
. - Một trình chặn để chặn tiêu đề
Authorization
trên mọi yêu cầu.
Các ứng dụng đã cài đặt
Mã mẫu sử dụng API Sách:
using System; using System.IO; using System.Threading; using System.Threading.Tasks; using Google.Apis.Auth.OAuth2; using Google.Apis.Books.v1; using Google.Apis.Books.v1.Data; using Google.Apis.Services; using Google.Apis.Util.Store; namespace Books.ListMyLibrary { /// <summary> /// Sample which demonstrates how to use the Books API. /// https://developers.google.com/books/docs/v1/getting_started /// <summary> internal class Program { [STAThread] static void Main(string[] args) { Console.WriteLine("Books API Sample: List MyLibrary"); Console.WriteLine("================================"); try { new Program().Run().Wait(); } catch (AggregateException ex) { foreach (var e in ex.InnerExceptions) { Console.WriteLine("ERROR: " + e.Message); } } Console.WriteLine("Press any key to continue..."); Console.ReadKey(); } private async Task Run() { UserCredential credential; using (var stream = new FileStream("client_secrets.json", FileMode.Open, FileAccess.Read)) { credential = await GoogleWebAuthorizationBroker.AuthorizeAsync( GoogleClientSecrets.Load(stream).Secrets, new[] { BooksService.Scope.Books }, "user", CancellationToken.None, new FileDataStore("Books.ListMyLibrary")); } // Create the service. var service = new BooksService(new BaseClientService.Initializer() { HttpClientInitializer = credential, ApplicationName = "Books API Sample", }); var bookshelves = await service.Mylibrary.Bookshelves.List().ExecuteAsync(); ... } } }
-
Trong mã mẫu này, một thực thể
UserCredential
mới được tạo bằng cách gọi phương thứcGoogleWebAuthorizationBroker.AuthorizeAsync
. Phương thức tĩnh này nhận được các thông tin sau:- Khoá bí mật của ứng dụng khách (hoặc luồng đến khoá bí mật của ứng dụng khách).
- Các phạm vi bắt buộc.
- Giá trị nhận dạng người dùng.
- Mã huỷ để huỷ một thao tác.
- Một kho dữ liệu không bắt buộc. Nếu bạn không chỉ định kho dữ liệu, giá trị mặc định sẽ là
FileDataStore
với thư mụcGoogle.Apis.Auth
mặc định. Thư mục được tạo trongEnvironment.SpecialFolder.ApplicationData
.
-
UserCredential
do phương thức này trả về được đặt làmHttpClientInitializer
trênBooksService
(sử dụng trình khởi chạy). Như đã giải thích trước đó,UserCredential
triển khai một trình khởi chạy ứng dụng HTTP. -
Lưu ý rằng trong mã mẫu, thông tin bí mật của ứng dụng được tải từ một tệp, nhưng bạn cũng có thể làm như sau:
credential = await GoogleWebAuthorizationBroker.AuthorizeAsync( new ClientSecrets { ClientId = "PUT_CLIENT_ID_HERE", ClientSecret = "PUT_CLIENT_SECRETS_HERE" }, new[] { BooksService.Scope.Books }, "user", CancellationToken.None, new FileDataStore("Books.ListMyLibrary"));
Hãy xem mẫu Sách của chúng tôi.
Ứng dụng web (ASP.NET Core 3)
API của Google hỗ trợ OAuth 2.0 cho ứng dụng máy chủ web.
Google.Apis.Auth.AspNetCore3 là thư viện được đề xuất để sử dụng cho hầu hết các trường hợp OAuth 2.0 dựa trên Google trong các ứng dụng ASP.NET Core 3. Thư viện này triển khai trình xử lý xác thực OpenIdConnect
dành riêng cho Google. Thư viện này hỗ trợ xác thực gia tăng và xác định một IGoogleAuthProvider
có thể chèn để cung cấp thông tin xác thực của Google có thể dùng được với các API của Google.
Phần này mô tả cách định cấu hình và sử dụng Google.Apis.Auth.AspNetCore3. Mã hiển thị ở đây dựa trên Google.Apis.Auth.AspNetCore3.IntegrationTests, đây là một ứng dụng ASP.NET Core 3 tiêu chuẩn, hoạt động đầy đủ.
Nếu muốn làm theo tài liệu này dưới dạng hướng dẫn, bạn cần có ứng dụng ASP.NET Core 3 của riêng mình và hoàn tất các bước này làm điều kiện tiên quyết.
Điều kiện tiên quyết
- Cài đặt gói Google.Apis.Auth.AspNetCore3.
- Chúng tôi đang sử dụng API Google Drive nên bạn cũng cần cài đặt gói Google.Apis.Drive.v3.
- Tạo một dự án Google Cloud nếu bạn chưa có. Hãy làm theo hướng dẫn này để thực hiện việc này. Đây sẽ là dự án mà ứng dụng của bạn được xác định.
- Hãy nhớ bật API Google Drive. Để bật API, hãy làm theo hướng dẫn này.
-
Tạo thông tin xác thực uỷ quyền để xác định ứng dụng của bạn với Google. Làm theo
hướng dẫn này để tạo thông tin xác thực uỷ quyền và tải tệp
client_secrets.json
xuống. Hai điểm nổi bật:- Xin lưu ý rằng loại thông tin xác thực phải là Ứng dụng web.
- Để chạy ứng dụng này, URI chuyển hướng duy nhất bạn cần thêm là
https://localhost:5001/signin-oidc
.
Định cấu hình ứng dụng để sử dụng Google.Apis.Auth.AspNetCore3
Google.Apis.Auth.AspNetCore3 được định cấu hình trong lớp Startup
hoặc phương án thay thế tương tự mà bạn có thể đang sử dụng. Các đoạn mã sau đây được trích xuất từ
Startup.cs
trong dự án Google.Apis.Auth.AspNetCore3.IntegrationTests.
-
Thêm lệnh sau vào tệp
Startup.cs
.using Google.Apis.Auth.AspNetCore3;
-
Trong phương thức
Startup.ConfigureServices
, hãy thêm mã sau, thay đổi phần giữ chỗ Mã ứng dụng và Mật khẩu ứng dụng bằng các giá trị có trong tệpclient_secrets.json
. Bạn có thể tải các giá trị này trực tiếp từ tệp JSON hoặc lưu trữ các giá trị này theo bất kỳ cách an toàn nào khác. Hãy xem phương thứcClientInfo.Load
trong dự án Google.Apis.Auth.AspNetCore3.IntegrationTests để biết ví dụ về cách tải trực tiếp các giá trị này từ tệp JSON.public void ConfigureServices(IServiceCollection services) { ... // This configures Google.Apis.Auth.AspNetCore3 for use in this app. services .AddAuthentication(o => { // This forces challenge results to be handled by Google OpenID Handler, so there's no // need to add an AccountController that emits challenges for Login. o.DefaultChallengeScheme = GoogleOpenIdConnectDefaults.AuthenticationScheme; // This forces forbid results to be handled by Google OpenID Handler, which checks if // extra scopes are required and does automatic incremental auth. o.DefaultForbidScheme = GoogleOpenIdConnectDefaults.AuthenticationScheme; // Default scheme that will handle everything else. // Once a user is authenticated, the OAuth2 token info is stored in cookies. o.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; }) .AddCookie() .AddGoogleOpenIdConnect(options => { options.ClientId = {YOUR_CLIENT_ID}; options.ClientSecret = {YOUR_CLIENT_SECRET}; }); }
-
Trong phương thức
Startup.Configure
, hãy nhớ thêm các thành phần phần mềm trung gian xác thực và uỷ quyền ASP.NET Core 3 vào quy trình, cũng như các lệnh chuyển hướng HTTPS:public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { ... app.UseHttpsRedirection(); ... app.UseAuthentication(); app.UseAuthorization(); ... }
Sử dụng thông tin xác thực của người dùng để thay mặt họ truy cập vào các API của Google
Bây giờ, bạn đã sẵn sàng thêm các phương thức hành động vào bộ điều khiển yêu cầu thông tin đăng nhập của người dùng để thay mặt họ truy cập vào API của Google. Đoạn mã sau đây cho biết cách liệt kê các tệp trên tài khoản Google Drive của người dùng đã xác thực. Hãy lưu ý hai điều chính:
-
Người dùng không chỉ cần được xác thực mà còn cần cấp phạm vi
https://www.googleapis.com/auth/drive.readonly
cho ứng dụng của bạn. Bạn chỉ định phạm vi này bằng thuộc tínhGoogleScopedAuthorize
. -
Chúng tôi đang sử dụng cơ chế chèn phần phụ thuộc tiêu chuẩn của ASP.NET Core 3 để nhận một
IGoogleAuthProvider
mà chúng tôi sử dụng để lấy thông tin xác thực của người dùng.
Mã:
-
Trước tiên, hãy thêm các lệnh sau vào tay điều khiển.
using Google.Apis.Auth.AspNetCore3; using Google.Apis.Auth.OAuth2; using Google.Apis.Drive.v3; using Google.Apis.Services;
-
Thêm thao tác của tay điều khiển như sau (và đi kèm với thao tác đó là một thành phần hiển thị nhận mô hình
IList<string>
):/// <summary> /// Lists the authenticated user's Google Drive files. /// Specifying the <see cref="GoogleScopedAuthorizeAttribute"> will guarantee that the code /// executes only if the user is authenticated and has granted the scope specified in the attribute /// to this application. /// </summary> /// <param name="auth">The Google authorization provider. /// This can also be injected on the controller constructor.</param> [GoogleScopedAuthorize(DriveService.ScopeConstants.DriveReadonly)] public async Task<IActionResult> DriveFileList([FromServices] IGoogleAuthProvider auth) { GoogleCredential cred = await auth.GetCredentialAsync(); var service = new DriveService(new BaseClientService.Initializer { HttpClientInitializer = cred }); var files = await service.Files.List().ExecuteAsync(); var fileNames = files.Files.Select(x => x.Name).ToList(); return View(fileNames); }
Đó là những kiến thức cơ bản. Bạn có thể xem
HomeController.cs
trong dự án Google.Apis.Auth.AspNetCore3.IntegrationTests để tìm hiểu cách thực hiện:
- Chỉ xác thực người dùng, không có phạm vi cụ thể
- Đăng xuất người dùng
- Uỷ quyền gia tăng bằng mã. Lưu ý rằng mẫu này cho thấy việc uỷ quyền gia tăng bằng các thuộc tính.
- Kiểm tra các phạm vi đã cấp
- Kiểm tra mã truy cập và mã làm mới
- Buộc làm mới mã truy cập. Xin lưu ý rằng bạn không cần tự thực hiện việc này vì Google.Apis.Auth.AspNetCore3 sẽ phát hiện xem mã thông báo truy cập đã hết hạn hay sắp hết hạn và sẽ tự động làm mới mã thông báo đó.
Tài khoản dịch vụ
API của Google cũng hỗ trợ Tài khoản dịch vụ. Không giống như trường hợp ứng dụng khách yêu cầu quyền truy cập vào dữ liệu của người dùng cuối, tài khoản dịch vụ cung cấp quyền truy cập vào dữ liệu của chính ứng dụng khách.
Ứng dụng khách của bạn sẽ ký yêu cầu mã thông báo truy cập bằng khoá riêng tư được tải xuống từ Google API Console. Sau khi tạo mã ứng dụng mới, bạn nên chọn loại ứng dụng Tài khoản dịch vụ, sau đó bạn có thể tải khoá riêng tư xuống. Hãy xem mẫu tài khoản dịch vụ sử dụng API Google Plus.
using System; using System.Security.Cryptography.X509Certificates; using Google.Apis.Auth.OAuth2; using Google.Apis.Plus.v1; using Google.Apis.Plus.v1.Data; using Google.Apis.Services; namespace Google.Apis.Samples.PlusServiceAccount { /// <summary> /// This sample demonstrates the simplest use case for a Service Account service. /// The certificate needs to be downloaded from the Google API Console /// <see cref="https://console.cloud.google.com/"> /// "Create another client ID..." -> "Service Account" -> Download the certificate, /// rename it as "key.p12" and add it to the project. Don't forget to change the Build action /// to "Content" and the Copy to Output Directory to "Copy if newer". /// </summary> public class Program { // A known public activity. private static String ACTIVITY_ID = "z12gtjhq3qn2xxl2o224exwiqruvtda0i"; public static void Main(string[] args) { Console.WriteLine("Plus API - Service Account"); Console.WriteLine("=========================="); String serviceAccountEmail = "SERVICE_ACCOUNT_EMAIL_HERE"; var certificate = new X509Certificate2(@"key.p12", "notasecret", X509KeyStorageFlags.Exportable); ServiceAccountCredential credential = new ServiceAccountCredential( new ServiceAccountCredential.Initializer(serviceAccountEmail) { Scopes = new[] { PlusService.Scope.PlusMe } }.FromCertificate(certificate)); // Create the service. var service = new PlusService(new BaseClientService.Initializer() { HttpClientInitializer = credential, ApplicationName = "Plus API Sample", }); Activity activity = service.Activities.Get(ACTIVITY_ID).Execute(); Console.WriteLine(" Activity: " + activity.Object.Content); Console.WriteLine(" Video: " + activity.Object.Attachments[0].Url); Console.WriteLine("Press any key to continue..."); Console.ReadKey(); } } }
Mẫu này tạo một ServiceAccountCredential
.
Các phạm vi bắt buộc được đặt và có một lệnh gọi đến FromCertificate
, lệnh gọi này sẽ tải khoá riêng tư từ X509Certificate2
đã cho.
Giống như trong tất cả mã mẫu khác, thông tin xác thực được đặt thành HttpClientInitializer
.