เอกสารนี้อธิบาย OAuth 2.0, กรณีที่ควรใช้, วิธีรับรหัสไคลเอ็นต์ และวิธีใช้กับไลบรารีของไคลเอ็นต์ Google API สําหรับ .NET
โปรโตคอล OAuth 2.0
OAuth 2.0 คือโปรโตคอลการให้สิทธิ์ที่ Google APIs ใช้ คุณควรทำความคุ้นเคยกับโปรโตคอลนี้โดยอ่านลิงก์ต่อไปนี้
รับรหัสไคลเอ็นต์และรหัสลับ
คุณดูรหัสไคลเอ็นต์และข้อมูลลับได้ในคอนโซล Google API รหัสไคลเอ็นต์มีหลายประเภท ดังนั้นโปรดตรวจสอบว่าคุณได้รับรหัสประเภทที่ถูกต้องสำหรับแอปพลิเคชัน
- รหัสไคลเอ็นต์เว็บแอปพลิเคชัน
- รหัสไคลเอ็นต์แอปพลิเคชันที่ติดตั้ง
- รหัสไคลเอ็นต์ของบัญชีบริการ
คุณต้องดาวน์โหลดข้อมูลลับของลูกค้าและจัดเก็บเป็น client_secrets.json
ในโปรเจ็กต์ของคุณสำหรับข้อมูลโค้ดแต่ละรายการที่แสดง (ยกเว้นข้อมูลโค้ดของบัญชีบริการ)
ข้อมูลเข้าสู่ระบบ
ข้อมูลรับรองของผู้ใช้
UserCredential
เป็นคลาสตัวช่วยที่ปลอดภัยสำหรับเธรดสำหรับการใช้โทเค็นการเข้าถึงเพื่อเข้าถึงทรัพยากรที่มีการป้องกัน
โดยปกติแล้วโทเค็นการเข้าถึงจะหมดอายุหลังผ่านไป 1 ชั่วโมง
หลังจากนั้นคุณจะได้รับข้อผิดพลาดหากพยายามใช้โทเค็น
UserCredential
และ
AuthorizationCodeFlow
จะดูแล "รีเฟรช" โทเค็นโดยอัตโนมัติ ซึ่งหมายความว่าจะได้รับโทเค็นการเข้าถึงใหม่
ซึ่งทำได้โดยใช้โทเค็นการรีเฟรชที่ใช้ได้นาน ซึ่งคุณจะได้รับพร้อมกับโทเค็นการเข้าถึงหากใช้พารามิเตอร์ access_type=offline
ในระหว่างขั้นตอนการใช้รหัสการให้สิทธิ์
ในแอปพลิเคชันส่วนใหญ่ เราขอแนะนำให้จัดเก็บโทเค็นการเข้าถึงและโทเค็นรีเฟรชของข้อมูลเข้าสู่ระบบไว้ในพื้นที่เก็บข้อมูลถาวร มิฉะนั้น คุณจะต้องแสดงหน้าการให้สิทธิ์ในเบราว์เซอร์ให้ผู้ใช้ปลายทางเห็นทุกชั่วโมง เนื่องจากโทเค็นการเข้าถึงจะหมดอายุภายใน 1 ชั่วโมงหลังจากที่คุณได้รับ
หากต้องการให้โทเค็นการเข้าถึงและโทเค็นรีเฟรชคงอยู่ คุณสามารถระบุการใช้งาน IDataStore
ของคุณเอง หรือจะใช้การใช้งานอย่างใดอย่างหนึ่งต่อไปนี้จากไลบรารีก็ได้
-
FileDataStore
สำหรับ .NET จะทำให้ข้อมูลเข้าสู่ระบบคงอยู่ในไฟล์
ServiceAccountCredential
ServiceAccountCredential
คล้ายกับ UserCredential
แต่มีวัตถุประสงค์ต่างกัน
Google OAuth 2.0 รองรับการโต้ตอบระหว่างเซิร์ฟเวอร์ เช่น การโต้ตอบระหว่างเว็บแอปพลิเคชันกับ Google Cloud Storage
แอปพลิเคชันที่ขอต้องพิสูจน์ตัวตนของตนเองเพื่อรับสิทธิ์เข้าถึง API และผู้ใช้ปลายทางไม่จำเป็นต้องเกี่ยวข้อง
ServiceAccountCredential
จัดเก็บคีย์ส่วนตัว ซึ่งใช้ในการลงนามในคําขอรับโทเค็นการเข้าถึงใหม่
ทั้ง UserCredential
และ ServiceAccountCredential
ใช้ IConfigurableHttpClientInitializer
คุณจึงลงทะเบียนแต่ละรายการได้ดังนี้
- แฮนเดิลการตอบกลับที่ไม่สําเร็จ ดังนั้นจึงจะรีเฟรชโทเค็นหากได้รับรหัสสถานะ HTTP
401
- Interceptor เพื่อสกัดกั้นส่วนหัว
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
เมธอดแบบคงที่นี้จะรับข้อมูลต่อไปนี้- รหัสลับไคลเอ็นต์ (หรือสตรีมไปยังรหัสลับไคลเอ็นต์)
- ขอบเขตที่จําเป็น
- ตัวระบุผู้ใช้
- โทเค็นการยกเลิกสําหรับการยกเลิกการดําเนินการ
- พื้นที่เก็บข้อมูล (ไม่บังคับ) หากไม่ได้ระบุที่เก็บข้อมูล ระบบจะใช้
FileDataStore
ที่มีโฟลเดอร์Google.Apis.Auth
เริ่มต้นเป็นค่าเริ่มต้น ระบบจะสร้างโฟลเดอร์ในEnvironment.SpecialFolder.ApplicationData
-
UserCredential
ที่แสดงผลโดยเมธอดนี้จะตั้งค่าเป็นHttpClientInitializer
ในBooksService
(โดยใช้ตัวเริ่มต้น) ตามที่อธิบายไว้ก่อนหน้านี้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.Apis.Auth.AspNetCore3 เป็นไลบรารีที่แนะนําให้ใช้ในสถานการณ์ OAuth 2.0 ส่วนใหญ่ที่อิงตาม Google ในแอปพลิเคชัน ASP.NET Core 3 โดยใช้ตัวแฮนเดิลการตรวจสอบสิทธิ์OpenIdConnect
เฉพาะ Google โดยรองรับการตรวจสอบสิทธิ์แบบเพิ่ม และกำหนด IGoogleAuthProvider
ที่ฉีดได้เพื่อระบุข้อมูลเข้าสู่ระบบ Google ที่ใช้กับ Google APIs ได้
ส่วนนี้จะอธิบายวิธีกําหนดค่าและใช้ Google.Apis.Auth.AspNetCore3 โค้ดที่แสดงที่นี่จะอิงตาม Google.Apis.Auth.AspNetCore3.IntegrationTests ซึ่งเป็นแอปพลิเคชัน ASP.NET Core 3 มาตรฐานที่ใช้งานได้อย่างสมบูรณ์
หากต้องการทําตามเอกสารประกอบนี้เป็นบทแนะนํา คุณจะต้องมีแอปพลิเคชัน ASP.NET Core 3 ของคุณเอง และต้องทําตามขั้นตอนเหล่านี้ก่อน
ข้อกำหนดเบื้องต้น
- ติดตั้งแพ็กเกจ Google.Apis.Auth.AspNetCore3
- เราใช้ Google Drive API คุณจึงต้องติดตั้งแพ็กเกจ Google.Apis.Drive.v3 ด้วย
- สร้างโปรเจ็กต์ Google Cloud หากยังไม่มี โดยทําตาม วิธีการเหล่านี้ โปรเจ็กต์นี้จะเป็นโปรเจ็กต์ที่ระบุแอปของคุณ
- อย่าลืมเปิดใช้ Google Drive API หากต้องการเปิดใช้ API ให้ทำตาม วิธีการเหล่านี้
-
สร้างข้อมูลเข้าสู่ระบบการให้สิทธิ์ที่จะระบุแอปของคุณให้ Google ทราบ ทําตาม
วิธีการเหล่านี้เพื่อสร้างข้อมูลเข้าสู่ระบบการให้สิทธิ์และดาวน์โหลดไฟล์
client_secrets.json
ไฮไลต์ 2 ข้อ ได้แก่- โปรดทราบว่าประเภทข้อมูลเข้าสู่ระบบต้องเป็นเว็บแอปพลิเคชัน
- หากต้องการเรียกใช้แอปนี้ URI การเปลี่ยนเส้นทางเพียงรายการเดียวที่คุณต้องเพิ่มคือ
https://localhost:5001/signin-oidc
กำหนดค่าแอปพลิเคชันเพื่อใช้ Google.Apis.Auth.AspNetCore3
Google.Apis.Auth.AspNetCore3 ได้รับการกําหนดค่าในคลาส Startup
หรือคลาสอื่นที่คล้ายกันซึ่งคุณอาจใช้อยู่ ข้อมูลโค้ดต่อไปนี้ดึงมาจาก
Startup.cs
ในโปรเจ็กต์ Google.Apis.Auth.AspNetCore3.IntegrationTests
-
เพิ่มคำสั่ง "using" ต่อไปนี้ลงในไฟล์
Startup.cs
using Google.Apis.Auth.AspNetCore3;
-
ในเมธอด
Startup.ConfigureServices
ให้เพิ่มโค้ดต่อไปนี้ โดยเปลี่ยนตัวยึดตําแหน่งรหัสไคลเอ็นต์และรหัสลับไคลเอ็นต์เป็นค่าที่อยู่ในไฟล์client_secrets.json
คุณสามารถโหลดค่าเหล่านี้จากไฟล์ JSON ได้โดยตรง หรือจะจัดเก็บค่าเหล่านี้ในลักษณะที่ปลอดภัยอื่นๆ ก็ได้ ดูตัวอย่างวิธีโหลดค่าเหล่านี้จากไฟล์ JSON โดยตรงได้ที่เมธอดClientInfo.Load
ในโปรเจ็กต์ Google.Apis.Auth.AspNetCore3.IntegrationTestspublic 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 APIs ในนามของผู้ใช้
ตอนนี้คุณพร้อมที่จะเพิ่มเมธอดการดำเนินการไปยังตัวควบคุมที่ต้องใช้ข้อมูลเข้าสู่ระบบของผู้ใช้เพื่อเข้าถึง Google APIs ในนามของผู้ใช้แล้ว ข้อมูลโค้ดต่อไปนี้แสดงวิธีแสดงรายการไฟล์ในบัญชี Google ไดรฟ์ของผู้ใช้ที่ตรวจสอบสิทธิ์แล้ว โปรดสังเกต 2 สิ่งต่อไปนี้เป็นหลัก
-
ผู้ใช้ไม่เพียงต้องได้รับการตรวจสอบสิทธิ์เท่านั้น แต่ยังต้องให้สิทธิ์
https://www.googleapis.com/auth/drive.readonly
แก่แอปพลิเคชันของคุณด้วย ซึ่งคุณระบุโดยใช้แอตทริบิวต์GoogleScopedAuthorize
-
เราใช้กลไกการฉีดข้อมูล Dependency Injection มาตรฐานของ 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); }
ข้อมูลเบื้องต้นมีดังนี้ คุณสามารถดูตัวอย่างจาก
HomeController.cs
จากโปรเจ็กต์ Google.Apis.Auth.AspNetCore3.IntegrationTests เพื่อดูวิธีดำเนินการต่อไปนี้
- การตรวจสอบสิทธิ์ของผู้ใช้เท่านั้นโดยไม่มีขอบเขตที่เฉพาะเจาะจง
- ผู้ใช้ออกจากระบบ
- การให้สิทธิ์เพิ่มเติมด้วยรหัส โปรดทราบว่าตัวอย่างนี้แสดงการให้สิทธิ์แบบเพิ่มทีละรายการพร้อมแอตทริบิวต์
- ตรวจสอบขอบเขตที่อนุญาต
- ตรวจสอบโทเค็นการเข้าถึงและโทเค็นการรีเฟรช
- บังคับให้รีเฟรชโทเค็นการเข้าถึง โปรดทราบว่าคุณไม่จำเป็นต้องดำเนินการนี้ด้วยตนเอง เนื่องจาก Google.Apis.Auth.AspNetCore3 จะตรวจจับว่าโทเค็นการเข้าถึงหมดอายุหรือใกล้จะหมดอายุหรือไม่ และจะรีเฟรชโทเค็นโดยอัตโนมัติ
บัญชีบริการ
นอกจากนี้ Google APIs ยังรองรับบัญชีบริการด้วย บัญชีบริการจะให้สิทธิ์เข้าถึงข้อมูลของแอปพลิเคชันไคลเอ็นต์เอง ซึ่งแตกต่างจากกรณีที่แอปพลิเคชันไคลเอ็นต์ขอสิทธิ์เข้าถึงข้อมูลของผู้ใช้ปลายทาง
แอปพลิเคชันไคลเอ็นต์จะลงนามในคําขอโทเค็นการเข้าถึงโดยใช้คีย์ส่วนตัวที่ดาวน์โหลดจากคอนโซล Google API หลังจากสร้างรหัสไคลเอ็นต์ใหม่แล้ว คุณควรเลือกประเภทแอปพลิเคชันบัญชีบริการ จากนั้นจึงดาวน์โหลดคีย์ส่วนตัวได้ ดูตัวอย่าง บัญชีบริการที่ใช้ 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 { /// <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