OAuth 2.0

Bu belgede OAuth 2.0, ne zaman kullanılacağı, istemci kimliklerinin nasıl alınacağı 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 edinebilirsiniz:

İstemci kimliklerini ve gizli anahtarlarını edinme

İstemci kimlikleri ve gizli anahtarları Google API Konsolu'ndan edinebilirsiniz. Farklı istemci kimliği türleri bulunduğundan uygulamanız için doğru türü aldığınızdan emin olun:

Aşağıdaki kod snippet'lerinin her birinde (Hizmet hesabı hariç) istemci gizli anahtarını indirmeniz ve projenizde client_secrets.json olarak depolamanız gerekir.

Kimlik bilgileri

Kullanıcı kimlik bilgileri

UserCredential, korunan kaynaklara erişmek için erişim jetonu kullanmaya yönelik iş parçacığı güvenli bir yardımcı sınıftır. Bir erişim jetonunun süresi genellikle 1 saat sonra dolar. Bu sürenin sonunda jetonu kullanmaya çalışırsanız hata alırsınız.

UserCredential ve AuthorizationCodeFlow, jetonu otomatik olarak "yenileme" işlemini üstlenir. Bu işlem, yalnızca yeni bir erişim jetonu almak anlamına gelir. Bu işlem, uzun süreli yenileme jetonu kullanılarak yapılır. Yetkilendirme kodu akışı sırasında access_type=offline parametresini kullanırsanız bu jeton erişim jetonuyla birlikte alırsınız.

Çoğu uygulamada, kimlik bilgilerinin erişim jetonunun depolanması ve kalıcı depolama alanının yenilenmesi önerilir. Aksi takdirde, erişim jetonunun süresi alındıktan bir saat sonra sona erdiğinden, son kullanıcıya tarayıcıda her saat bir yetkilendirme sayfası sunmanız gerekir.

Erişim ve yenileme jetonlarının korunduğundan emin olmak için IDataStore için kendi uygulamanızı sağlayabilir veya kitaplık tarafından sağlanan aşağıdaki uygulamalardan birini kullanabilirsiniz:

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

ServiceAccountCredential

ServiceAccountCredential, UserCredential özelliğine benzer ancak farklı bir amaca hizmet eder. Google OAuth 2.0, bir web uygulaması ile Google Cloud Storage arasındaki etkileşimler gibi sunucular arası etkileşimleri destekler. İstekte bulunan uygulamanın API'ye erişebilmesi için kendi kimliğini kanıtlaması gerekir ve son kullanıcının müdahalesine gerek yoktur. ServiceAccountCredential, yeni bir erişim jetonu alma isteğini imzalamak için kullanılan bir özel anahtar depolar.

Hem UserCredential hem de ServiceAccountCredential, IConfigurableHttpClientInitializer'i uygular. Böylece bunların her birini şu şekilde kaydedebilirsiniz:

  • Başarısız bir yanıt işleyici olduğu için HTTP 401 durum kodu alırsa jetonu yeniler.
  • Her istekte Authorization başlığına müdahale etmek için bir müdahale aracı.

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 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 deposu. Veri deposu belirtilmezse varsayılan olarak Google.Apis.Auth klasörü içeren bir FileDataStore öğesi kullanılır. Klasör, Environment.SpecialFolder.ApplicationData konumunda oluşturulur.
  • Bu yöntemin döndürdüğü UserCredential, BooksService üzerinde (başlayıcı kullanılarak) HttpClientInitializer olarak ayarlanır. Yukarıda açıklandığı gibi UserCredential, bir HTTP istemci başlatıcı uygular.

  • Yukarıdaki örnek kodda, istemci gizli anahtarı bilgilerinin bir dosyadan yüklendiğine dikkat edin. Ancak 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.

Google.Apis.Auth.AspNetCore3, ASP.NET Core 3 uygulamasındaki çoğu Google tabanlı OAuth 2.0 senaryosu için kullanılması önerilen kitaplıktır. Google'a özel 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 eklenebilir bir IGoogleAuthProvider tanımlar.

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

Eğitim olarak bu dokümanları izlemek isterseniz kendi ASP.NET Core 3 uygulamanıza sahip olmanız ve ön koşul olarak bu adımları tamamlamanız gerekir.

Ön koşullar

  • Google.Apis.Auth.AspNetCore3 paketini yükleyin.
  • Google Drive API'yi kullandığımızdan Google.Apis.Drive.v3 paketini de yüklemeniz gerekiyor.
  • Henüz yoksa bir Google Cloud projesi oluşturun. Bunu yapmak için bu talimatları uygulayın. Bu, uygulamanızın tanımlandığı 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ıtacak yetkilendirme kimlik bilgileri oluşturun. Yetkilendirme kimlik bilgileri oluşturmak ve client_secrets.json dosyasını indirmek için bu talimatları uygulayın. İki önemli nokta:
    • Kimlik bilgisi türünün Web application (Web uygulaması) olması gerektiğine dikkat edin.
    • Bu uygulamayı çalıştırmak için eklemeniz gereken tek yönlendirme URI'si: https://localhost:5001/signin-oidc.

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

Google.Apis.Auth.AspNetCore3, Startup sınıfında veya kullanıyor olabileceğiniz benzer bir alternatifte yapılandırılmıştır. Aşağıdaki snippet'ler, Google.Apis.Auth.AspNetCore3.IntegrationTests projesindeki Startup.cs kaynağından ayıklanmıştır.

  • Startup.cs dosyanıza aşağıdaki yönergeyi kullanarak ekleyin.
    using Google.Apis.Auth.AspNetCore3;
  • Startup.ConfigureServices yönteminde aşağıdaki kodu ekleyin, İstemci Kimliği ve İstemci Gizli Anahtarı yer tutucularını client_secrets.json dosyasındaki değerlerle değiştirin. Bu değerleri doğrudan JSON dosyasından yükleyebilir veya başka bir güvenli yöntemle depolayabilirsiniz. Bu değerlerin doğrudan JSON dosyasından nasıl yükleneceğine ilişkin 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, ardışık düzene ASP.NET Core 3 kimlik doğrulama ve yetkilendirme ara katman yazılımı bileşenlerinin yanı sıra HTTPS yönlendirmelerini 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 bilgisini kullanın

Artık denetleyicilerinize, kendi adlarına Google API'lerine erişmek için kullanıcı kimlik bilgisi 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 şeye dikkat edin:

  • Kullanıcının hem kimliğinin doğrulanması hem de GoogleScopedAuthorize özelliği ile belirttiğiniz https://www.googleapis.com/auth/drive.readonly kapsamını uygulamanıza vermiş olması gerekir.
  • Kullanıcının kimlik bilgilerini edinmek için kullandığımız bir IGoogleAuthProvider almak için ASP.NET Core 3'ün standart bağımlılık ekleme mekanizmasını kullanıyoruz.

Kod:

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

Bunlar en temel bilgiler. Aşağıdakileri nasıl yapabileceğinizi öğrenmek için Google.Apis.Auth.AspNetCore3.IntegrationTests projesindeki HomeController.cs öğesine göz atabilirsiniz:

  • Belirli kapsamlar olmadan yalnızca kullanıcı kimlik doğrulaması
  • Çıkış işlevi
  • Kod aracılığıyla artımlı yetkilendirme. Yukarıdaki snippet'in özellikler aracılığıyla artımlı yetkilendirmeyi gösterdiğine dikkat edin.
  • Şu anda izin verilmiş kapsamları inceleme
  • Erişim ve yenileme jetonlarını inceleme
  • Erişim jetonunu zorla yenileyin. Bu işlemi kendiniz yapmanız gerekmez. Google.Apis.Auth.AspNetCore3, erişim jetonunun süresinin dolduğunu veya süresinin dolmak üzere olduğunu algılayıp jetonu otomatik olarak yeniler.

Hizmet hesabı

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

İstemci uygulamanız, Google API Konsolu'ndan indirilen bir özel anahtarı kullanarak erişim jetonu isteğini imzalar. Yeni bir istemci kimliği oluşturduktan sonra "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();
        }
    }
}

Yukarıdaki örnek kod bir ServiceAccountCredential oluşturur. Gerekli kapsamlar ayarlandı ve belirtilen X509Certificate2 öğesinden özel anahtarı yükleyen FromCertificate çağrısı yapıldı. Diğer tüm örnek kodlarında olduğu gibi kimlik bilgisi HttpClientInitializer olarak ayarlanır.