OAuth 2.0

Bu dokümanda OAuth 2.0, ne zaman kullanılacağı, istemci kimliklerinin nasıl edinileceği ve .NET için Google API İstemci Kitaplığı ile nasıl kullanılacağı açıklanmaktadır.

OAuth 2.0 Protokolü

OAuth 2.0, Google API'leri tarafından kullanılan yetkilendirme protokolüdür. Aşağıdaki bağlantıları okuyarak protokol hakkında bilgi edinin:

İstemci kimlikleri ve sırlar edinme

İstemci kimliklerini ve gizli anahtarları Google API Konsolu'ndan alabilirsiniz. Farklı istemci kimliği türleri olduğundan uygulamanız için doğru türü seçtiğinizden emin olun:

Gösterilen kod snippet'lerinin her birinde (hizmet hesabı hariç), istemci gizlisini indirip projenizde client_secrets.json olarak kaydetmeniz gerekir.

Kimlik bilgileri

Kullanıcı kimlik bilgileri

UserCredential korumalı kaynaklara erişmek için erişim jetonu kullanmaya yönelik, iş parçacığı güvenli bir yardımcı sınıftır. Erişim jetonlarının süresi genellikle 1 saat sonra dolar. Bu süre dolduktan sonra jetonu kullanmayı denerseniz hata alırsınız.

UserCredential ve AuthorizationCodeFlow jetonun otomatik olarak "yeniden yenilenmesini" (yani yeni bir erişim jetonu alınmasını) sağlar. Bu işlem, yetkilendirme kodu akışında access_type=offline parametresini kullanırsanız erişim jetonuyla birlikte aldığınız uzun ömürlü bir yenileme jetonu kullanılarak yapılır.

Çoğu uygulamada, kimlik bilgisinin erişim jetonunu ve yenileme jetonunu kalıcı depolama alanında saklamak önerilir. Aksi takdirde, erişim jetonunun süresi aldıktan bir saat sonra sona ereceğinden, son kullanıcıya tarayıcıda her saat bir yetkilendirme sayfası göstermeniz gerekir.

Erişim ve yenileme jetonlarının kalıcı olmasını sağlamak için IDataStore sınıfını kendi uygulamanızla sağlayabilir veya kitaplık tarafından sağlanan aşağıdaki uygulamalardan birini kullanabilirsiniz:

  • .NET için FileDataStore kimlik bilgisinin dosyada kalıcı olmasını sağlar.

ServiceAccountCredential

ServiceAccountCredential UserCredential'e benzer ancak farklı bir amaca hizmet eder. Google OAuth 2.0, bir web uygulaması ile Google Cloud Storage arasındakiler gibi sunucudan sunucuya etkileşimleri destekler. İstekte bulunan uygulamanın, API'ye erişmek için kendi kimliğini kanıtlaması gerekir. Son kullanıcının bu sürece dahil olması gerekmez. ServiceAccountCredential, yeni bir erişim jetonu alma isteğini imzalamak için kullanılan özel bir anahtar depolar.

Hem UserCredential hem de ServiceAccountCredential, IConfigurableHttpClientInitializer özelliğini uygular. Bu nedenle, bunların her birini şu şekilde kaydedebilirsiniz:

  • Başarısız bir yanıt işleyicidir. Bu nedenle, HTTP 401 durum kodu alırsa jetonu yeniler.
  • Her istekteki Authorization başlığını engellemek için bir müdahaleci.

Yüklü uygulamalar

Books API'yi kullanan örnek kod:

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();
            ...
        }
    }
}
  
  • Bu örnek kodda, GoogleWebAuthorizationBroker.AuthorizeAsync yöntemi çağrılarak yeni bir UserCredential örneği oluşturulur. Bu statik yöntem aşağıdakileri alır:

    • İstemci gizli anahtarı (veya istemci gizli anahtarına giden bir akış).
    • Gerekli kapsamlar.
    • Kullanıcı tanımlayıcısı.
    • Bir işlemi iptal etmek için kullanılan iptal jetonu.
    • İsteğe bağlı bir veri kümesi. Veri deposu belirtilmezse varsayılan olarak varsayılan Google.Apis.Auth klasörüne sahip bir FileDataStore kullanılır. Klasör Environment.SpecialFolder.ApplicationData konumunda oluşturulur.
  • Bu yöntem tarafından döndürülen UserCredential, BooksService üzerinde HttpClientInitializer olarak ayarlanır (ilkleştirici kullanılır). Daha önce açıklandığı gibi, UserCredential bir HTTP istemci başlatıcısı uygular.

  • Örnek kodda istemci gizli bilgileri bir dosyadan yüklenmektedir. Bununla birlikte, aşağıdakileri de yapabilirsiniz:

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

Kitaplar örneğimize göz atın.

Web uygulamaları (ASP.NET Core 3)

Google API'leri Web Sunucusu Uygulamaları için OAuth 2.0'ı destekler.

ASP.NET Core 3 uygulamalarındaki çoğu Google tabanlı OAuth 2.0 senaryosu için Google.Apis.Auth.AspNetCore3 kitaplığının kullanılması önerilir. Google'a özgü bir OpenIdConnect kimlik doğrulama işleyicisi uygular. Artımlı kimlik doğrulamayı destekler ve Google API'leriyle kullanılabilecek Google kimlik bilgilerini sağlamak için IGoogleAuthProvider enjeksiyon noktası tanımlar.

Bu bölümde, Google.Apis.Auth.AspNetCore3'ün nasıl yapılandırılacağı ve kullanılacağı açıklanmaktadır. Burada gösterilen kod, tamamen çalışan standart bir ASP.NET Core 3 uygulaması olan Google.Apis.Auth.AspNetCore3.IntegrationTests'e dayanır.

Bu dokümanları eğitim olarak takip etmek istiyorsanız kendi ASP.NET Core 3 uygulamanızı oluşturmanız ve bu adımları tamamlamanız gerekir.

Ön koşullar

  • Google.Apis.Auth.AspNetCore3 paketini yükleyin.
  • Google Drive API'yi kullanıyoruz. Bu nedenle, Google.Apis.Drive.v3 paketini de yüklemeniz gerekir.
  • Henüz yoksa bir Google Cloud projesi oluşturun. Bunu yapmak için bu talimatları uygulayın. Bu, uygulamanızın kimliğiyle ilişkilendirilecek proje olacaktır.
  • Google Drive API'yi etkinleştirdiğinizden emin olun. API'leri etkinleştirmek için bu talimatları uygulayın.
  • Uygulamanızı Google'a tanımlayacak yetkilendirme kimlik bilgileri oluşturun. Yetkilendirme kimlik bilgilerini oluşturmak ve client_secrets.json dosyasını indirmek için bu talimatları uygulayın. İki önemli nokta:
    • Kimlik bilgilerinin türü Web uygulaması olmalıdır.
    • Bu uygulamayı çalıştırmak için eklemeniz gereken tek yönlendirme URI'si https://localhost:5001/signin-oidc'tir.

Uygulamanızı, Google.Apis.Auth.AspNetCore3'ü kullanacak şekilde yapılandırın

Google.Apis.Auth.AspNetCore3, Startup sınıfında veya kullandığınız benzer bir alternatifte yapılandırılmıştır. Aşağıdaki snippet'ler, Google.Apis.Auth.AspNetCore3.IntegrationTests projesindeki Startup.cs dosyasından alınmıştır.

  • Startup.cs dosyanıza aşağıdaki using yönergesini ekleyin.
    using Google.Apis.Auth.AspNetCore3;
  • Startup.ConfigureServices yöntemine aşağıdaki kodu ekleyin. Bu kodda, istemci kimliği ve istemci gizli anahtarı yer tutucularını client_secrets.json dosyasında bulunan değerlerle değiştirin. Bu değerleri doğrudan JSON dosyasından yükleyebilir veya başka bir güvenli şekilde saklayabilirsiniz. Bu değerlerin doğrudan JSON dosyasından nasıl yükleneceğine dair bir örnek için Google.Apis.Auth.AspNetCore3.IntegrationTests projesindeki ClientInfo.Load yöntemine göz atın.
    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 yönteminde, ASP.NET Core 3 kimlik doğrulama ve yetkilendirme ara yazılım bileşenlerinin yanı sıra HTTPS yönlendirmelerini de ardışık düzene eklediğinizden emin olun:
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        ...
        app.UseHttpsRedirection();
        ...
    
        app.UseAuthentication();
        app.UseAuthorization();
    
        ...
    }
          

Kullanıcı adına Google API'lerine erişmek için kullanıcı kimlik bilgilerini kullanın

Artık denetleyicilerinize, kullanıcı kimlik bilgisinin kullanıcı adına Google API'lerine erişmesini gerektiren işlem yöntemleri eklemeye hazırsınız. Aşağıdaki snippet'te, kimliği doğrulanmış kullanıcının Google Drive hesabındaki dosyaların nasıl listeleneceği gösterilmektedir. Genellikle iki noktaya dikkat edin:

  • Kullanıcının kimliğinin doğrulanmasının yanı sıra GoogleScopedAuthorize özelliğini kullanarak belirttiğiniz https://www.googleapis.com/auth/drive.readonly kapsamını da uygulamanıza vermesi gerekir.
  • Kullanıcının kimlik bilgilerini almak için kullandığımız IGoogleAuthProvider değerini almak amacıyla ASP.NET Core 3'ün standart bağımlılık ekleme mekanizmasını kullanıyoruz.

Kod:

  • Öncelikle aşağıdaki talimatları kullanarak kumandanıza ekleyin.
    using Google.Apis.Auth.AspNetCore3;
    using Google.Apis.Auth.OAuth2;
    using Google.Apis.Drive.v3;
    using Google.Apis.Services;
          
  • Kontrolör işlemini aşağıdaki gibi ekleyin (ve IList<string> modeli alan bir görünümle birlikte ekleyin):
    /// <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);
    }
          

Temel bilgiler bunlardır. Aşağıdakileri nasıl başarabileceğinizi öğrenmek için Google.Apis.Auth.AspNetCore3.IntegrationTests projesindeki HomeController.cs dosyasına göz atabilirsiniz:

  • Belirli kapsamlar olmadan yalnızca kullanıcı kimlik doğrulaması
  • Kullanıcının oturumunu kapatma
  • Kodla artımlı yetkilendirme. Örnekte, özelliklerle birlikte artımlı yetkilendirmenin gösterildiğine dikkat edin.
  • Verilen kapsamları inceleme
  • Erişim ve yenileme jetonlarını inceleme
  • Erişim jetonunu zorla yenileyin. Google.Apis.Auth.AspNetCore3, erişim jetonunun süresinin dolup dolmadığını veya süresinin dolmak üzere olup olmadığını algılayıp otomatik olarak yenilediğinden bunu kendiniz yapmanız gerekmez.

Hizmet hesabı

Google API'leri hizmet hesaplarını da destekler. İstemci uygulamasının son kullanıcının verilerine erişim istediği senaryodakinin aksine, hizmet hesapları istemci uygulamasının kendi verilerine erişim sağlar.

İstemci uygulamanız, Google API Konsolu'ndan indirilen gizli bir anahtar kullanarak erişim jetonu isteğini imzalar. Yeni bir istemci kimliği oluşturduktan sonra bir hizmet hesabı uygulama türü seçmeniz gerekir. Ardından özel anahtarı indirebilirsiniz. Google Plus API'yi kullanan hizmet hesabı örneğimize göz atın.

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

Bu örnekte, bir ServiceAccountCredential oluşturulur. Gerekli kapsamlar ayarlanır ve FromCertificate çağrısı yapılır. Bu çağrı, özel anahtarı belirli bir X509Certificate2 kaynağından yükler. Diğer tüm örnek kodlarda olduğu gibi, kimlik bilgisi HttpClientInitializer olarak ayarlanmıştır.