OAuth 2.0 (original) (raw)
本文件將說明 OAuth 2.0、使用時機、取得用戶端 ID 的方式,以及如何搭配 .NET 適用的 Google API 用戶端程式庫使用。
OAuth 2.0 通訊協定
OAuth 2.0 是 Google API 使用的授權通訊協定。請參閱下列連結,熟悉這個通訊協定:
取得用戶端 ID 和密鑰
您可以在 Google API 控制台取得用戶端 ID 和密鑰。 用戶端 ID 有不同類型,因此請務必取得應用程式所需的正確類型:
在每個顯示的程式碼片段中 (服務帳戶除外),您都必須下載用戶端密鑰,並將其儲存在專案中,做為 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 會儲存私密金鑰,用於簽署要求以取得新的存取權存取權杖。
UserCredential 和 ServiceAccountCredential 都實作 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
{
///
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();
...
}
}}
- 在這個範例程式碼中,我們會透過呼叫
GoogleWebAuthorizationBroker.AuthorizeAsync方法來建立新的UserCredential例項。這個靜態方法會取得下列項目:- 用戶端密鑰 (或用戶端密鑰的串流)。
- 必要的範圍。
- 使用者 ID。
- 用於取消作業的取消權杖。
- 選用的資料儲存庫。如果未指定資料儲存庫,預設會使用含有預設
Google.Apis.Auth資料夾的FileDataStore。資料夾會在Environment.SpecialFolder.ApplicationData中建立。
- 這個方法傳回的
UserCredential會設為BooksService上的HttpClientInitializer(使用初始化器)。如先前所述,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。
在 ASP.NET Core 3 應用程式中, Google.Apis.Auth.AspNetCore3 是建議用於大多數 Google 架構 OAuth 2.0 情境的程式庫。實作 Google 專屬的 OpenIdConnect 驗證處理常式。它支援漸進式驗證,並定義可供注入的 IGoogleAuthProvider,以提供可與 Google API 搭配使用的 Google 憑證。
本節說明如何設定及使用 Google.Apis.Auth.AspNetCore3。這裡顯示的程式碼是根據 Google.Apis.Auth.AspNetCore3.IntegrationTests 所提供的標準 ASP.NET Core 3 應用程式,這也是完整運作的應用程式。
如果您想按照本說明文件中的教學課程操作,則必須先完成下列步驟,並使用自己的 ASP.NET Core 3 應用程式。
必要條件
- 安裝 Google.Apis.Auth.AspNetCore3 套件。
- 我們使用的是 Google 雲端硬碟 API,因此您還需要安裝 Google.Apis.Drive.v3 套件。
- 如果您還沒有 Google Cloud 專案,請建立一個。請按照 這篇文章中的操作說明進行操作。這將是應用程式識別的專案。
- 請務必啟用 Google 雲端硬碟 API。如要啟用 API,請按照 這些操作說明進行。
- 建立授權憑證,讓 Google 識別您的應用程式。請按照 這些操作說明建立授權憑證,並下載
client_secrets.json檔案。兩個重點:- 請注意,憑證類型必須是「網頁應用程式」。
- 如要執行這個應用程式,您只需要新增
https://localhost:5001/signin-oidc這個重新導向 URI。
將應用程式設為使用 Google.Apis.Auth.AspNetCore3
Google.Apis.Auth.AspNetCore3 會在 Startup 類別或您可能使用的類似替代方案中設定。以下程式碼片段是從 Google.Apis.Auth.AspNetCore3.IntegrationTests 專案的 Startup.cs 中擷取。
- 將下列 using 指令新增至
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 指令新增至控制器。
using Google.Apis.Auth.AspNetCore3;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Drive.v3;
using Google.Apis.Services; - 新增控制器動作,如下所示 (並搭配接收
IList<string>模型的檢視畫面):
///
/// Lists the authenticated user's Google Drive files.
/// Specifying the will guarantee that the code
/// executes only if the user is authenticated and has granted the scope specified in the attribute
/// to this application.
///
/// The Google authorization provider.
/// This can also be injected on the controller constructor.
[GoogleScopedAuthorize(DriveService.ScopeConstants.DriveReadonly)]
public async Task 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 Plus 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
{
///
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。