OAuth 2.0

Dokumen ini menjelaskan OAuth 2.0, kapan harus menggunakannya, cara mendapatkan client ID, dan cara menggunakannya dengan Library Klien Google API untuk .NET.

Protokol OAuth 2.0

OAuth 2.0 adalah protokol otorisasi yang digunakan oleh Google API. Anda harus memahami protokol tersebut dengan membaca tautan berikut:

Memperoleh client ID dan secret

Anda bisa mendapatkan client ID dan rahasia pada Konsol API Google. Ada berbagai jenis client ID, jadi pastikan untuk mendapatkan jenis yang tepat untuk permohonan Anda:

Dalam setiap cuplikan kode di bawah ini (kecuali Akun layanan satu), Anda harus mendownload rahasia klien dan menyimpannya sebagai client_secrets.json dalam project Anda.

Kredensial

Kredensial pengguna

UserCredential adalah class helper yang aman untuk thread untuk menggunakan token akses guna mengakses resource yang dilindungi. Masa berlaku token akses biasanya berakhir setelah 1 jam, setelah itu Anda akan mendapatkan error jika mencoba menggunakannya.

UserCredential dan AuthorizationCodeFlow menangani "pembaruan" token secara otomatis, yang berarti mendapatkan token akses baru. Hal ini dilakukan menggunakan token refresh yang berumur panjang, yang Anda terima bersama dengan token akses jika Anda menggunakan parameter access_type=offline selama alur kode otorisasi.

Pada sebagian besar aplikasi, sebaiknya simpan token akses kredensial dan token refresh dalam penyimpanan persisten. Jika tidak, Anda harus menampilkan halaman otorisasi di browser kepada pengguna akhir setiap jam, karena masa berlaku token akses berakhir satu jam setelah Anda menerimanya.

Untuk memastikan token akses dan refresh tetap ada, Anda dapat memberikan implementasi IDataStore Anda sendiri, atau Anda dapat menggunakan salah satu implementasi berikut yang disediakan oleh library:

  • FileDataStore untuk .NET memastikan bahwa kredensial akan dipertahankan dalam file.

ServiceAccountCredential

ServiceAccountCredential mirip dengan UserCredential, tetapi memiliki tujuan yang berbeda. Google OAuth 2.0 mendukung interaksi server-ke-server seperti interaksi antara aplikasi web dan Google Cloud Storage. Aplikasi yang meminta harus membuktikan identitasnya sendiri untuk mendapatkan akses ke API, dan pengguna akhir tidak perlu dilibatkan. ServiceAccountCredential menyimpan kunci pribadi, yang digunakan untuk menandatangani permintaan guna mendapatkan token akses baru.

UserCredential dan ServiceAccountCredential mengimplementasikan IConfigurableHttpClientInitializer sehingga Anda dapat mendaftarkan setiap kode ini sebagai:

  • Pengendali respons yang gagal, sehingga akan memperbarui token jika menerima kode status HTTP 401.
  • Interseptor, untuk menangkap header Authorization pada setiap permintaan.

Aplikasi terpasang

Kode contoh menggunakan 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();
            ...
        }
    }
}
  
  • Dalam kode contoh ini, instance UserCredential baru dibuat dengan memanggil metode GoogleWebAuthorizationBroker.AuthorizeAsync. Metode statis ini mendapatkan hal berikut:

    • Rahasia klien (atau stream ke rahasia klien).
    • Cakupan yang diperlukan.
    • ID pengguna.
    • Token pembatalan untuk membatalkan operasi.
    • Penyimpanan data opsional. Jika penyimpanan data tidak ditentukan, defaultnya adalah FileDataStore dengan folder Google.Apis.Auth default. Folder dibuat di Environment.SpecialFolder.ApplicationData.
  • UserCredential yang ditampilkan oleh metode ini ditetapkan sebagai HttpClientInitializer pada BooksService (menggunakan penginisialisasi). Seperti yang dijelaskan di atas, UserCredential mengimplementasikan penginisialisasi klien HTTP.

  • Perhatikan bahwa dalam kode contoh di atas, informasi rahasia klien dimuat dari file, tetapi Anda juga dapat melakukan hal berikut:

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

Lihat Contoh buku kami.

Aplikasi web (ASP.NET Core 3)

Google API mendukung OAuth 2.0 untuk Aplikasi Server Web.

Google.Apis.Auth.AspNetCore3 adalah library yang direkomendasikan untuk digunakan dalam sebagian besar skenario OAuth 2.0 berbasis Google dalam aplikasi ASP.NET Core 3. Implementasi ini mengimplementasikan pengendali autentikasi OpenIdConnect khusus Google. Library ini mendukung autentikasi inkremental, dan menentukan IGoogleAuthProvider yang dapat dimasukkan untuk memasok kredensial Google yang dapat digunakan dengan Google API.

Bagian ini menjelaskan cara mengonfigurasi dan menggunakan Google.Apis.Auth.AspNetCore3. Kode yang ditampilkan di sini didasarkan pada Google.Apis.Auth.AspNetCore3.IntegrationTests yang merupakan aplikasi ASP.NET Core 3 standar dan berfungsi sepenuhnya.

Jika ingin mengikuti dokumentasi ini sebagai tutorial, Anda memerlukan aplikasi ASP.NET Core 3 sendiri dan menyelesaikan langkah-langkah ini sebagai prasyarat.

Prasyarat

  • Instal paket Google.Apis.Auth.AspNetCore3.
  • Kami menggunakan Google Drive API, sehingga Anda juga harus menginstal paket Google.Apis.Drive.v3.
  • Buat project Google Cloud jika Anda belum memilikinya. Ikuti petunjuk berikut untuk melakukannya. Project ini adalah project yang diidentifikasi dengan aplikasi Anda.
  • Pastikan untuk mengaktifkan Google Drive API. Untuk mengaktifkan API, ikuti petunjuk ini.
  • Buat kredensial otorisasi yang akan mengidentifikasi aplikasi Anda ke Google. Ikuti petunjuk berikut untuk membuat kredensial otorisasi dan mendownload file client_secrets.json. Dua sorotan:
    • Perhatikan bahwa jenis kredensial harus berupa Aplikasi web.
    • Untuk menjalankan aplikasi ini, satu-satunya URI pengalihan yang perlu Anda tambahkan adalah https://localhost:5001/signin-oidc.

Konfigurasi aplikasi Anda untuk menggunakan Google.Apis.Auth.AspNetCore3

Google.Apis.Auth.AspNetCore3 dikonfigurasi di class Startup atau alternatif serupa yang mungkin Anda gunakan. Cuplikan berikut diekstrak dari Startup.cs dalam project Google.Apis.Auth.AspNetCore3.IntegrationTests.

  • Tambahkan perintah penggunaan berikut ke file Startup.cs Anda.
    using Google.Apis.Auth.AspNetCore3;
  • Pada metode Startup.ConfigureServices, tambahkan kode berikut, ubah placeholder Client ID dan Rahasia Klien dengan nilai yang terdapat dalam file client_secrets.json. Anda dapat memuat nilai ini langsung dari file JSON atau menyimpannya dengan cara yang aman lainnya. Lihat metode ClientInfo.Load di project Google.Apis.Auth.AspNetCore3.IntegrationTests untuk contoh cara memuat nilai-nilai ini langsung dari file 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};
            });
    }
          
  • Dalam metode Startup.Configure, pastikan untuk menambahkan komponen autentikasi dan middleware otorisasi ASP.NET Core 3 ke pipeline, serta pengalihan HTTPS:
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        ...
        app.UseHttpsRedirection();
        ...
    
        app.UseAuthentication();
        app.UseAuthorization();
    
        ...
    }
          

Menggunakan kredensial pengguna untuk mengakses Google API atas nama mereka

Sekarang Anda siap menambahkan metode tindakan ke pengontrol yang memerlukan kredensial pengguna untuk mengakses Google API atas nama mereka. Cuplikan berikut menunjukkan cara menampilkan daftar file di akun Google Drive pengguna yang diautentikasi. Perhatikan dua hal yang terutama:

  • Pengguna tidak hanya perlu diautentikasi, tetapi juga harus memberikan cakupan https://www.googleapis.com/auth/drive.readonly ke aplikasi Anda, yang Anda tentukan melalui atribut GoogleScopedAuthorize.
  • Kami menggunakan mekanisme injeksi dependensi standar ASP.NET Core 3 untuk menerima IGoogleAuthProvider yang digunakan untuk mendapatkan kredensial pengguna.

Kode:

  • Pertama-tama tambahkan perintah berikut menggunakan direktif ke pengontrol Anda.
    using Google.Apis.Auth.AspNetCore3;
    using Google.Apis.Auth.OAuth2;
    using Google.Apis.Drive.v3;
    using Google.Apis.Services;
          
  • Tambahkan tindakan pengontrol, sebagai berikut (dan sertakan dengan tampilan sederhana yang menerima model 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);
    }
          

Dan inilah dasar-dasarnya. Anda dapat melihat HomeController.cs dari project Google.Apis.Auth.AspNetCore3.IntegrationTests untuk mengetahui cara mencapainya:

  • Khusus autentikasi pengguna, tanpa cakupan spesifik
  • Fungsi logout
  • Otorisasi inkremental melalui kode. Perhatikan bahwa cuplikan di atas menunjukkan otorisasi inkremental melalui atribut.
  • Memeriksa cakupan yang saat ini diberikan
  • Memeriksa akses dan token refresh
  • Muat ulang token akses secara paksa. Perhatikan bahwa Anda tidak perlu melakukannya sendiri karena Google.Apis.Auth.AspNetCore3 akan mendeteksi apakah token akses sudah tidak berlaku atau hampir habis masa berlakunya, dan akan otomatis memperbaruinya.

Akun layanan

Google API juga mendukung Akun layanan. Tidak seperti skenario ketika aplikasi klien meminta akses ke data pengguna akhir, akun layanan memberikan akses ke data aplikasi klien itu sendiri.

Aplikasi klien Anda menandatangani permintaan token akses menggunakan kunci pribadi yang didownload dari Konsol API Google. Setelah membuat client ID baru, Anda harus memilih jenis aplikasi “Akun Layanan”, lalu mendownload kunci pribadi. Lihat contoh akun layanan kami yang menggunakan 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();
        }
    }
}

Kode contoh di atas membuat ServiceAccountCredential. Cakupan yang diperlukan telah ditetapkan dan terdapat panggilan ke FromCertificate, yang memuat kunci pribadi dari X509Certificate2 yang ditentukan. Seperti di semua kode contoh lainnya, kredensial ditetapkan sebagai HttpClientInitializer.