OAuth 2.0

Tài liệu này mô tả OAuth 2.0, thời điểm sử dụng, cách lấy ID khách hàng, và cách sử dụng thư viện này với Thư viện ứng dụng API của Google dành cho .NET.

Giao thức OAuth 2.0

OAuth 2.0 là giao thức uỷ quyền được các API của Google sử dụng. Bạn sẽ làm quen với giao thức này bằng cách đọc các liên kết sau:

Đang lấy mã ứng dụng khách và khoá bí mật

Bạn có thể lấy mã ứng dụng khách và khoá bí mật trên Google API Console. Có nhiều loại mã ứng dụng khách, nên hãy nhớ tìm đúng loại đơn đăng ký của bạn:

Trong mỗi đoạn mã bên dưới (ngoại trừ đoạn mã Tài khoản dịch vụ), bạn phải tải mật khẩu ứng dụng khách và lưu trữ dưới dạng client_secrets.json trong dự án của bạ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ã truy cập để truy cập vào các tài nguyên được bảo vệ. Mã truy cập thường hết hạn sau 1 giờ, Sau đó, bạn sẽ gặp lỗi nếu cố sử dụng.

UserCredentialAuthorizationCodeFlow xử lý việc tự động "làm mới" mã thông báo, chỉ đơn giản là việc nhận được một mã truy cập mới. Bạn có thể thực hiện việc này bằng cách sử dụng mã làm mới dài hạn mà bạn nhận được cùng với nếu bạn sử dụng mã truy cập 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ã truy cập và mã làm mới của thông tin đăng nhập trong bộ nhớ liên tục. Nếu không, bạn sẽ cần cung cấp cho người dùng cuối trong trình duyệt mỗi giờ, vì khi truy cập mã thông báo sẽ hết hạn sau một giờ kể từ khi bạn nhận được.

Để đảm bảo mã truy cập và mã làm mới vẫn tồn tại, bạn có thể cung cấp cách triển khai của riêng mình IDataStore! hoặc có thể dùng một trong các cách triển khai sau đây do thư viện cung cấp:

  • FileDataStore dành cho .NET đảm bảo thông tin đăng nhập sẽ luôn tồn tại trong tệp.

ServiceAccountCredential

ServiceAccountCredential tương tự như UserCredential nhưng phục vụ một 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ư các hoạt động tương tác giữa ứ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 mình để 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ã truy cập mới.

Cả UserCredentialServiceAccountCredential đều triển khai IConfigurableHttpClientInitializer để bạn có thể đăng ký từng miền dưới dạng:

  • Trình xử lý phản hồi không thành công, do đó, mã sẽ làm mới mã thông báo nếu nhận được mã trạng thái HTTP 401.
  • Một thiết bị chặn để chặn Authorization trên mỗi yêu cầu.

Các ứng dụng đã cài đặt

Mã mẫu bằng Books API:

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ức GoogleWebAuthorizationBroker.AuthorizeAsync. Phương thức tĩnh này mang lại những lợi ích sau:

    • Mật khẩu ứng dụng khách (hoặc một luồng tới mật khẩu ứ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ã thông báo huỷ để huỷ một thao tác.
    • Một kho dữ liệu không bắt buộc. Nếu kho dữ liệu không được chỉ định, giá trị mặc định sẽ là FileDataStore có thư mục Google.Apis.Auth mặc định. Thư mục này được tạo trong Environment.SpecialFolder.ApplicationData.
  • UserCredential được phương thức này trả về được đặt thành HttpClientInitializer trên BooksService (sử dụng trình khởi tạo). Như đã giải thích ở trên, UserCredential sẽ triển khai Trình khởi chạy ứng dụng HTTP.

  • Lưu ý rằng trong mã mẫu ở trên, thông tin mật khẩu ứng dụng khách đượ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 tham khảo Sách mẫu của chúng tôi.

Ứng dụng web (ASP.NET Core 3)

Hỗ trợ API của Google 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 sản phẩm dựa trên nền tảng của Google Tình huống OAuth 2.0 trong ứng dụng ASP.NET Core 3. Công cụ này triển khai một giải pháp Trình xử lý xác thực OpenIdConnect. Lớp này hỗ trợ xác thực gia tăng và xác định một URL có thể chèn IGoogleAuthProvider để cung cấp thông tin đăng nhập Google có thể sử dụng 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ã được hiển thị ở đây là dựa trên Google.Apis.Auth.AspNetCore3.IntegrationTests là một ASP.NET tiêu chuẩn, hoạt động hoàn toàn Ứng dụng Core 3.

Nếu muốn làm theo tài liệu này như một hướng dẫn, bạn cần có ASP.NET của riêng mình Đơn đăng ký Core 3 và điều kiện tiên quyết để hoàn thành các bước này.

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

  • Cài đặt Gói Google.Apis.Auth.AspNetCore3.
  • Chúng tôi đang dùng API Google Drive, vì vậy, bạn sẽ bạn cũng cần cài đặt Google.Apis.Drive.v3 .
  • Tạo một dự án trên Google Cloud nếu bạn chưa có. Theo dõi các hướng dẫn này để làm như vậy. Đây sẽ là dự án dùng để xác định ứng dụng của bạn.
  • Hãy nhớ bật API Google Drive. Để bật API, hãy làm theo các hướng dẫn này.
  • Tạo thông tin xác thực uỷ quyền giúp xác định ứng dụng của bạn cho Google. Theo dõi các hướng dẫn này để tạo thông tin xác thực cho phép và tải client_secrets.json. Hai điểm nổi bật:
    • Lưu ý rằng thông tin đăng nhập phải là Ứng dụng web.
    • Để chạy ứng dụng này, bạn cần thêm URI chuyển hướng duy nhất là https://localhost:5001/signin-oidc.

Định cấu hình ứng dụng của bạn để sử dụng Google.Apis.Auth.AspNetCore3

Google.Apis.Auth.AspNetCore3 được định cấu hình trong lớp Startup hoặc tương tự thay thế mà bạn có thể đang sử dụng. Các đoạn mã sau được trích xuất từ Startup.cs trong dự án Google.Apis.Auth.AspNetCore3.IntegrationTests.

  • Thêm lệnh sau bằng 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 khách và Mật khẩu ứng dụng khách có các giá trị có trong client_secrets.json. Bạn có thể tải các giá trị này trực tiếp từ tệp JSON hoặc bạn có thể lưu trữ chúng theo bất kỳ cách thức bảo mật nào khác. Hãy xem ClientInfo.Load trong Google.Apis.Auth.AspNetCore3.IntegrationTests dự án để biết ví dụ về cách tải các giá trị này trực tiếp 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 phương thức xác thực ASP.NET Core 3 và uỷ quyền các thành phần phần mềm trung gian theo 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 đăng nhập của người dùng để truy cập vào các API của Google thay mặt họ

Giờ đây, 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 xác thực của người dùng truy cập các API của Google thay mặt họ. Đ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 chú ý đến 2 điều chủ yếu:

  • Người dùng không chỉ cần được xác thực mà còn cần phải cấp https://www.googleapis.com/auth/drive.readonly phạm vi đối với ứng dụng của bạn. Điều này mà bạn chỉ định thông qua thuộc tính GoogleScopedAuthorize.
  • Chúng tôi đang sử dụng cơ chế chèn phần phụ thuộc chuẩn của ASP.NET Core 3 để nhận IGoogleAuthProvider mà chúng tôi sử dụng để lấy thông tin đăng nhập của người dùng.

Mã:

  • Trước tiên, hãy thêm các lệnh sau vào bộ đ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 bộ điều khiển như sau (và đi kèm với thao tác này bằng một chế độ xem đơn giản nhận được một 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);
    }
          

Và đây là những yêu cầu cơ bản. Bạn có thể xem HomeController.cs của dự án Google.Apis.Auth.AspNetCore3.IntegrationTests để tìm hiểu cách bạn có thể đạt được:

  • Chỉ xác thực người dùng, không có phạm vi cụ thể
  • Chức năng đăng xuất
  • Uỷ quyền tăng dần qua mã. Lưu ý rằng đoạn mã trên cho thấy mức độ tăng dần uỷ quyền thông qua các thuộc tính.
  • Kiểm tra các phạm vi hiện được cấp
  • Kiểm tra mã truy cập và làm mới
  • Buộc làm mới mã truy cập. Lưu ý rằng bạn không phải tự thực hiện việc này vì Google.Apis.Auth.AspNetCore3 sẽ phát hiện xem mã truy cập đã hết hạn hoặc sắp hết hạn chưa và tự động làm mới trang đó.

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 mà ứ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ụ sẽ cấp quyền truy cập vào dữ liệu riêng của ứng dụng khách.

Ứng dụng khách của bạn ký yêu cầu cấp mã truy cập bằng cách sử dụng khoá riêng tư đã tải xuống trên Bảng điều khiển API của Google. Sau khi tạo mã ứng dụng khách mới, bạn nên chọn "Tài khoản dịch vụ" loại ứng dụng và sau đó bạn có thể tải xuống khoá cá nhân. 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ã mẫu ở trên sẽ tạo ra một ServiceAccountCredential. Các phạm vi bắt buộc đã được đặt và có lệnh gọi tới FromCertificate, để tải khoá riêng tư từ X509Certificate2 đã cho. Như trong tất cả mã mẫu khác, thông tin đăng nhập được đặt là HttpClientInitializer.