เอกสารนี้อธิบายเกี่ยวกับ OAuth 2.0 เวลาที่ควรใช้ วิธีหารหัสลูกค้า และวิธีใช้งานร่วมกับไลบรารีของไคลเอ็นต์ Google API สำหรับ .NET
โปรโตคอล OAuth 2.0
OAuth 2.0 เป็นโปรโตคอลการให้สิทธิ์ที่ Google APIs ใช้ คุณควรทำความคุ้นเคยกับโปรโตคอลโดยการอ่านลิงก์ต่อไปนี้:
การรับรหัสไคลเอ็นต์และข้อมูลลับ
คุณสามารถรับรหัสไคลเอ็นต์และรหัสลับได้ในคอนโซล Google API รหัสลูกค้ามีอยู่หลายประเภท ดังนั้น ตรวจสอบให้แน่ใจว่าแอปพลิเคชันของคุณเป็นประเภทที่ถูกต้อง:
- รหัสไคลเอ็นต์ของเว็บแอปพลิเคชัน
- รหัสไคลเอ็นต์ของแอปพลิเคชันที่ติดตั้ง
- รหัสไคลเอ็นต์ของบัญชีบริการ
ในแต่ละข้อมูลโค้ดด้านล่าง (ยกเว้นบัญชีบริการ) คุณจะต้องดาวน์โหลด
รหัสลับไคลเอ็นต์และจัดเก็บไว้เป็น client_secrets.json
ในโปรเจ็กต์ของคุณ
ข้อมูลเข้าสู่ระบบ
ข้อมูลรับรองของผู้ใช้
UserCredential
เป็นคลาสตัวช่วยแบบ Thread-safe สำหรับการใช้โทเค็นเพื่อการเข้าถึงเพื่อเข้าถึงทรัพยากรที่มีการป้องกัน
โดยทั่วไปโทเค็นเพื่อการเข้าถึงจะหมดอายุหลังจากผ่านไป 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
- ตัวสกัดกั้น เพื่อสกัดกั้น
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 APIs OAuth 2.0 สำหรับแอปพลิเคชันเว็บเซิร์ฟเวอร์
Google.Apis.Auth.AspNetCore3 เป็นไลบรารีที่แนะนำเพื่อใช้กับผลิตภัณฑ์ส่วนใหญ่ที่มาจาก Google
สถานการณ์ OAuth 2.0 ในแอปพลิเคชัน ASP.NET Core 3 นำอินเทอร์เฟซสำหรับ Google โดยเฉพาะ
ตัวแฮนเดิลการตรวจสอบสิทธิ์ OpenIdConnect
รองรับการตรวจสอบสิทธิ์ที่เพิ่มขึ้นและกำหนด Injectable
IGoogleAuthProvider
เพื่อให้ข้อมูลเข้าสู่ระบบของ Google ที่ใช้กับ Google APIs ได้
ส่วนนี้จะอธิบายวิธีกำหนดค่าและใช้ Google.Apis.Auth.AspNetCore3 รหัสที่แสดง อิงตาม Google.Apis.Auth.AspNetCore3.IntegrationTests ซึ่งเป็น ASP.NET มาตรฐานที่ทำงานได้อย่างสมบูรณ์ แอปพลิเคชัน Core 3
หากคุณต้องการทำตามเอกสารนี้เพื่อเป็นบทแนะนำ คุณจะต้องใช้ ASP.NET ของคุณเอง การสมัครหลัก 3 และดำเนินการขั้นตอนเหล่านี้ให้เสร็จสมบูรณ์เป็นข้อกำหนดเบื้องต้น
ข้อกำหนดเบื้องต้น
- ติดตั้ง แพ็กเกจ Google.Apis.Auth.AspNetCore3
- เราใช้ API ของ Google ไดรฟ์ คุณจะ ต้องติดตั้ง 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
-
เพิ่มคำสั่งต่อไปนี้ลงในไฟล์
Startup.cs
using Google.Apis.Auth.AspNetCore3;
-
ในเมธอด
Startup.ConfigureServices
ให้เพิ่มโค้ดต่อไปนี้เพื่อเปลี่ยนค่า ตัวยึดตำแหน่งของรหัสไคลเอ็นต์และรหัสลับไคลเอ็นต์ที่มีค่าที่มีอยู่ในclient_secrets.json
คุณจะโหลดค่าเหล่านี้ได้โดยตรงจากไฟล์ JSON หรือคุณจะจัดเก็บคีย์ด้วยวิธีอื่นๆ ที่ปลอดภัยได้ ดูที่ClientInfo.Load
ใน Google.Apis.Auth.AspNetCore3.IntegrationTests สำหรับตัวอย่างวิธีโหลดค่าเหล่านี้โดยตรงจากไฟล์ JSONpublic 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 แล้ว และคอมโพเนนต์มิดเดิลแวร์การให้สิทธิ์ไปยังไปป์ไลน์ รวมถึงการเปลี่ยนเส้นทาง HTTPSpublic void Configure(IApplicationBuilder app, IWebHostEnvironment env) { ... app.UseHttpsRedirection(); ... app.UseAuthentication(); app.UseAuthorization(); ... }
ใช้ข้อมูลเข้าสู่ระบบของผู้ใช้เพื่อเข้าถึง Google API ในนามของผู้ใช้
ตอนนี้คุณพร้อมที่จะเพิ่มวิธีดำเนินการกับตัวควบคุมที่ต้องใช้ข้อมูลเข้าสู่ระบบของผู้ใช้ เข้าถึง Google APIs ในนามของผู้ใช้ ข้อมูลโค้ดต่อไปนี้แสดงวิธีแสดงรายการไฟล์ใน บัญชี Google ไดรฟ์ของผู้ใช้ที่ได้รับการตรวจสอบสิทธิ์แล้ว สังเกตพบ 2 สิ่งเป็นส่วนใหญ่:
-
ผู้ใช้ไม่เพียงต้องได้รับการตรวจสอบสิทธิ์เท่านั้น แต่ยังต้องให้
https://www.googleapis.com/auth/drive.readonly
ขอบเขตสำหรับแอปพลิเคชันของคุณ ซึ่ง ที่คุณระบุผ่านแอตทริบิวต์GoogleScopedAuthorize
-
เราใช้กลไกการแทรกทรัพยากร Dependency มาตรฐานของ 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
เช่นเดียวกับโค้ดตัวอย่างอื่นๆ ทั้งหมด