OAuth 2.0

本文件說明 OAuth 2.0、 適用時機 如何取得用戶端 ID 以及如何與 .NET 的 Google API 用戶端程式庫搭配使用

OAuth 2.0 通訊協定

OAuth 2.0 是 Google API 使用的授權通訊協定, 請參閱下列連結,熟悉通訊協定:

取得用戶端 ID 和密鑰

您可以在 Google API 控制台取得用戶端 ID 和密鑰。 用戶端 ID 類型各有不同 因此請務必為應用程式取得正確的類型:

,瞭解如何調查及移除這項存取權。

在下列任一程式碼片段 (服務帳戶 1 除外) 中,您必須下載 用戶端密鑰,並將其儲存為 client_secrets.json 項目。

憑證

使用者憑證

UserCredential敬上 是一種執行緒安全的輔助類別,可使用存取權杖存取受保護的資源。 存取權杖通常會在 1 小時後失效, 否則會收到錯誤訊息。

UserCredential敬上 和 AuthorizationCodeFlow。 自動「重新整理」也就是取得 新的存取權杖 方法是使用長期更新權杖,然後與 存取權杖 access_type=offline敬上 參數。

在大多數應用程式中,我們建議將 憑證的存取權杖和更新權杖,位於永久儲存空間中。 否則,您就必須提供 瀏覽器內的授權頁面,因為存取作業 。

為確保能保留存取權和更新權杖, 您可以自行提供導入 IDataStore、 您也可以使用程式庫提供的這些實作項目:

  • FileDataStore敬上 的 .NET 可確保憑證會永久保存在檔案中。

ServiceAccountCredential

ServiceAccountCredential敬上 與 UserCredential 類似,但用途不同 Google OAuth 2.0 支援伺服器對伺服器的互動,例如網頁應用程式和 Google Cloud Storage 之間的互動。 提出要求的應用程式必須證明自己的身分才能存取 API,讓使用者不必參與其中。 ServiceAccountCredential 會儲存私密金鑰,可用來簽署要求以取得新的存取權杖。

UserCredentialServiceAccountCredential 都會實作 IConfigurableHttpClientInitializer敬上 因此,您可將各個項目註冊為:

  • 失敗的回應處理常式, ,這樣一來,如果權杖收到 HTTP 401 狀態碼,就會重新整理權杖。
  • 攔截器,用於攔截 Authorization 標頭。

已安裝的應用程式

使用 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();
            ...
        }
    }
}
  
  • 在本程式碼範例中,系統會透過呼叫UserCredential GoogleWebAuthorizationBroker.AuthorizeAsync 方法。 這個靜態方法可取得下列項目:

    • 用戶端密鑰 (或串流至用戶端密鑰)。
    • 所需範圍。
    • 使用者 ID。
    • 取消作業的取消權杖。
    • 選用的資料儲存庫。如未指定資料儲存庫,則預設值為 FileDataStore 其中含有預設的 Google.Apis.Auth 資料夾 系統會在「Environment.SpecialFolder.ApplicationData」中建立資料夾。
  • 這個方法傳回的 UserCredential 已設為 HttpClientInitializerBooksService 上執行 (使用初始化工具)。 如上所述,UserCredential 會實作 HTTP 用戶端初始化器

  • 請注意,在上述程式碼範例中,用戶端密鑰資訊是從檔案載入。 但也可以執行以下動作:

    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"));
          

查看圖書範例

網頁應用程式 (ASP.NET Core 3)

Google API 支援 網路伺服器應用程式的 OAuth 2.0

大部分以 Google 為基礎的服務都建議使用 Google.Apis.Auth.AspNetCore3 程式庫 ASP.NET Core 3 應用程式中的 OAuth 2.0 情境。導入 Google 專屬的 OpenIdConnect 驗證處理常式。這項功能支援漸進式驗證機制,並會定義 IGoogleAuthProvider 來提供可搭配 Google API 使用的 Google 憑證。

本節說明如何設定及使用 Google.Apis.Auth.AspNetCore3。顯示的代碼 這個心率是根據 Google.Apis.Auth.AspNetCore3.IntegrationTests 是正常運作的標準 ASP.NET Core 3 應用程式。

如要按照教學課程操作,您必須使用自己的 ASP.NET。 核心 3 應用程式及完成這些步驟。

必要條件

  • 安裝 Google.Apis.Auth.AspNetCore3 套件。
  • 我們目前使用 Google Drive API,方便您 您還必須安裝 Google.Apis.Drive.v3 套件。
  • 如果您還沒有 Google Cloud 專案,請建立專案。追蹤 這些步驟。也就是應用程式用來識別的專案。
  • 請務必啟用 Google Drive API。如要啟用 API,請按照下列步驟操作 此處
  • 建立授權憑證,方便 Google 識別您的應用程式。追蹤 這些指示建立授權憑證並下載 client_secrets.json 檔案。兩大重點:
    • 請注意,憑證類型必須是網頁應用程式
    • 執行這個應用程式時,唯一隻需新增的重新導向 URI 是 https://localhost:5001/signin-oidc

設定應用程式以使用 Google.Apis.Auth.AspNetCore3

Google.Apis.Auth.AspNetCore3 是在 Startup 類別或類似的類別中設定 可能使用的替代方案系統擷取的程式碼片段 Startup.cs

  • 將下列指令使用指令新增至 Startup.cs 檔案。
    using Google.Apis.Auth.AspNetCore3;
  • Startup.ConfigureServices 方法中新增下列程式碼,讓 用戶端 ID 和用戶端密鑰預留位置,其中包含 client_secrets.json 檔案。您可以直接從 JSON 檔案載入這些值 也能以其他安全的方式儲存查看 Google.Apis.Auth.AspNetCore3.IntegrationTests 中的 ClientInfo.Load 方法 範例,瞭解如何直接從 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};
            });
    }
          
  • Startup.Configure 方法中,請務必新增 ASP.NET Core 3 驗證 和授權中介軟體元件到管道,以及 HTTPS 重新導向:
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        ...
        app.UseHttpsRedirection();
        ...
    
        app.UseAuthentication();
        app.UseAuthorization();
    
        ...
    }
          
    敬上

使用使用者憑證,代表使用者存取 Google API

您現在可以在控制器中新增需要使用者憑證的動作方法 存取 Google API以下程式碼片段說明如何列出 已驗證使用者的 Google 雲端硬碟帳戶。大部分會留意以下兩件事:

  • 使用者不僅須進行驗證,也需要獲得 https://www.googleapis.com/auth/drive.readonly 範圍授予應用程式,而 透過 GoogleScopedAuthorize 屬性指定
  • 我們使用 ASP.NET Core 3 的標準依附元件插入機制,以 用於取得使用者憑證的 IGoogleAuthProvider

程式碼:

  • 首先,使用指令將以下內容新增至控制器。
    using Google.Apis.Auth.AspNetCore3;
    using Google.Apis.Auth.OAuth2;
    using Google.Apis.Drive.v3;
    using Google.Apis.Services;
          
  • 按照下列方式新增控制器動作 (並伴隨簡易檢視畫面 接收 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);
    }
          

這些都是基本概念您可以查看 來自 Google.Apis.Auth.AspNetCore3.IntegrationTests 專案的 HomeController.cs ,瞭解如何達成下列目標:

  • 僅限使用者驗證 (不含特定範圍)
  • 登出功能
  • 透過代碼漸進式授權。請注意,上方程式碼片段顯示 透過屬性取得授權
  • 查看目前授予的範圍
  • 檢查存取權和更新權杖
  • 強制重新整理存取權杖。請注意,您不必自行操作 Google.Apis.Auth.AspNetCore3 會偵測存取權杖已過期或即將過期 並會自動重新整理

服務帳戶

也支援 Google API 服務帳戶。 與用戶端應用程式要求存取使用者資料的情況不同, 服務帳戶可讓您存取用戶端應用程式自己的資料。

您的用戶端應用程式使用下載的私密金鑰,簽署存取權杖的要求 Google API 控制台。 建立新的用戶端 ID 後,您應選擇「服務帳戶」 應用程式類型,然後下載私密金鑰。 請參閱 使用 Google+ API 的服務帳戶範例

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();
        }
    }
}

上述程式碼範例會建立 ServiceAccountCredential。 已設定必要的範圍,並有呼叫 FromCertificate。 ,從指定 X509Certificate2 載入私密金鑰。 與所有其他程式碼範例一樣,憑證會設為 HttpClientInitializer