OAuth 2.0

Questo documento descrive OAuth 2.0, quando utilizzarla, come acquisire gli ID cliente, e come utilizzarlo con la libreria client dell'API di Google per .NET.

Protocollo OAuth 2.0

OAuth 2.0 è il protocollo di autorizzazione utilizzato dalle API di Google. Dovresti acquisire familiarità con il protocollo leggendo i seguenti link:

Acquisizione di client ID e secret

Puoi ottenere gli ID client e i secret nella console API di Google. Esistono diversi tipi di ID cliente, quindi assicurati di scegliere il tipo corretto per la tua applicazione:

di Gemini Advanced.

In ciascuno degli snippet di codice riportati di seguito (tranne in quello dell'account di servizio), devi scaricare il e archivialo come client_secrets.json nel tuo progetto.

Credenziali

Credenziali utente

UserCredential è una classe helper sicura per i thread che consente di utilizzare un token di accesso per accedere alle risorse protette. In genere un token di accesso scade dopo un'ora dopodiché riceverai un messaggio di errore se tenti di utilizzarlo.

UserCredential e AuthorizationCodeFlow aggiorna automaticamente il token, il che significa semplicemente un nuovo token di accesso. Per farlo, utilizza un token di aggiornamento di lunga durata, che ricevi insieme al token il token di accesso access_type=offline durante il flusso del codice di autorizzazione.

Nella maggior parte delle applicazioni, è consigliabile archiviare il token di accesso e il token di aggiornamento nello spazio di archiviazione permanente. In caso contrario, dovrai presentare all'utente finale pagina di autorizzazione nel browser ogni ora, poiché l'accesso scade un'ora dopo la ricezione.

Per assicurarti che i token di accesso e di aggiornamento vengano mantenuti, puoi fornire la tua implementazione IDataStore, In alternativa, puoi utilizzare una delle seguenti implementazioni fornite dalla libreria:

  • FileDataStore per .NET assicura che la credenziale sia permanente in un file.

ServiceAccountCredential

ServiceAccountCredential è simile a UserCredential, ma ha uno scopo diverso. Google OAuth 2.0 supporta le interazioni server-to-server, come quelle tra un'applicazione web e Google Cloud Storage. L'applicazione richiedente deve dimostrare la propria identità per ottenere l'accesso a un'API e non è necessario coinvolgere un utente finale. ServiceAccountCredential archivia una chiave privata che viene utilizzata per firmare una richiesta e ottenere un nuovo token di accesso.

Sia UserCredential che ServiceAccountCredential implementano IConfigurableHttpClientInitializer: quindi puoi registrarle come:

  • Un gestore di risposte non riuscite, in modo da aggiornare il token se riceve un codice di stato HTTP 401.
  • Un intercettore, per intercettare Authorization per ogni richiesta.

Applicazioni installate

Codice campione utilizzando l'API Books:

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();
            ...
        }
    }
}
  
  • In questo codice di esempio, viene creata una nuova istanza UserCredential chiamando il metodo Metodo GoogleWebAuthorizationBroker.AuthorizeAsync. Questo metodo statico genera quanto segue:

    • Il client secret (o un flusso al client secret).
    • Gli ambiti richiesti.
    • L'identificatore dell'utente.
    • Il token di annullamento per l'annullamento di un'operazione.
    • Un datastore facoltativo. Se il datastore non è specificato, il valore predefinito è FileDataStore con una cartella Google.Apis.Auth predefinita. La cartella viene creata in Environment.SpecialFolder.ApplicationData.
  • Il valore UserCredential restituito da questo metodo è impostato su HttpClientInitializer su BooksService (utilizzando l'inizializzatore). Come spiegato in precedenza, UserCredential implementa una Inizializzatore del client HTTP.

  • Nota che nel codice campione precedente, le informazioni del client secret vengono caricate da un file, ma puoi anche fare quanto segue:

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

Dai un'occhiata al nostro esempio di Libri.

Applicazioni web (ASP.NET Core 3)

Assistenza per le API di Google OAuth 2.0 per applicazioni server web.

Lo Google.Apis.Auth.AspNetCore3 è la libreria consigliata da utilizzare per la maggior parte delle soluzioni Scenari di OAuth 2.0 nelle applicazioni ASP.NET Core 3. Implementa una strategia di offerta Gestore di autenticazione OpenIdConnect. Supporta l'autenticazione incrementale e definisce un valore IGoogleAuthProvider per fornire le credenziali Google che possono essere utilizzate con le API di Google.

Questa sezione descrive come configurare e utilizzare Google.Apis.Auth.AspNetCore3. Il codice mostrato si basa su Google.Apis.Auth.AspNetCore3.IntegrationTests, che è un ASP.NET standard completamente funzionante dell'applicazione Core 3.

Se vuoi seguire questa documentazione come tutorial, avrai bisogno di un tuo ASP.NET Core 3 e completare questi passaggi come prerequisito.

Prerequisiti

  • Installa il Google.Apis.Auth.AspNetCore3.
  • Stiamo usando l'API Google Drive per devi installare Google.Apis.Drive.v3 pacchetto.
  • Crea un progetto Google Cloud se non ne hai già uno. Segui queste istruzioni. Questo sarà il progetto con cui è identificata la tua app.
  • Assicurati di attivare l'API Google Drive. Per abilitare le API: queste istruzioni.
  • Crea credenziali di autorizzazione che identificheranno la tua app per Google. Segui queste istruzioni per creare le credenziali di autorizzazione e scaricare client_secrets.json file. Due punti salienti:
    • Tieni presente che le credenziali il tipo deve essere Applicazione web.
    • Per l'esecuzione di questa app, l'unico URI di reindirizzamento che devi aggiungere è https://localhost:5001/signin-oidc.

Configura l'applicazione per utilizzare Google.Apis.Auth.AspNetCore3

Google.Apis.Auth.AspNetCore3 è configurato nella classe Startup o in una classe simile l'alternativa che potresti utilizzare. I seguenti snippet vengono estratti Startup.cs nel progetto Google.Apis.Auth.AspNetCore3.IntegrationTests.

  • Aggiungi la seguente istruzione d'uso al tuo file Startup.cs.
    using Google.Apis.Auth.AspNetCore3;
  • Nel metodo Startup.ConfigureServices aggiungi il seguente codice, modifica il i segnaposto ID client e client secret con i valori contenuti nei client_secrets.json file. Puoi caricare questi valori direttamente dal file JSON o in qualsiasi altro modo sicuro. Dai un'occhiata Metodo ClientInfo.Load nel Google.Apis.Auth.AspNetCore3.IntegrationTests per un esempio su come caricare questi valori direttamente dal 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};
            });
    }
          
  • Nel metodo Startup.Configure, assicurati di aggiungere l'autenticazione ASP.NET Core 3 e i componenti middleware di autorizzazione per la pipeline, nonché i reindirizzamenti HTTPS:
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        ...
        app.UseHttpsRedirection();
        ...
    
        app.UseAuthentication();
        app.UseAuthorization();
    
        ...
    }
          

Utilizza le credenziali utente per accedere alle API di Google per loro conto

Ora puoi aggiungere ai tuoi controller metodi di azione che richiedono le credenziali utente per accedono alle API di Google per loro conto. Lo snippet seguente mostra come elencare i file nella dell'utente autenticato su Google Drive. Nota principalmente due cose:

  • L'utente non solo deve essere autenticato, ma deve anche aver concesso https://www.googleapis.com/auth/drive.readonly all'applicazione, che da te specificato tramite l'attributo GoogleScopedAuthorize.
  • Utilizziamo il meccanismo di inserimento delle dipendenze standard di ASP.NET Core 3 per ricevere IGoogleAuthProvider che utilizziamo per ottenere le credenziali dell'utente.

Il codice:

  • Innanzitutto, aggiungi le seguenti istruzioni di utilizzo al controller.
    using Google.Apis.Auth.AspNetCore3;
    using Google.Apis.Auth.OAuth2;
    using Google.Apis.Drive.v3;
    using Google.Apis.Services;
          
  • Aggiungi l'azione del controller, come mostrato di seguito (e accompagnata da una visualizzazione semplice che riceve un modello 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);
    }
          

Queste sono le informazioni di base. Puoi dare un'occhiata alle HomeController.cs del progetto Google.Apis.Auth.AspNetCore3.IntegrationTests per scoprire come ottenere:

  • Solo autenticazione utente, senza ambiti specifici
  • Funzionalità di disconnessione
  • Autorizzazione incrementale tramite codice. Come puoi notare, lo snippet riportato sopra mostra l'autorizzazione tramite attributi.
  • Esamina gli ambiti attualmente concessi
  • Esamina i token di accesso e di aggiornamento
  • Forza l'aggiornamento del token di accesso. Tieni presente che non devi farlo autonomamente perché Google.Apis.Auth.AspNetCore3 rileverà se il token di accesso è scaduto o è prossimo alla scadenza e la aggiornerà automaticamente.

Account di servizio

Le API di Google supportano inoltre Account di servizio. A differenza dello scenario in cui un'applicazione client richiede l'accesso ai dati di un utente finale, gli account di servizio forniscono accesso ai dati dell'applicazione client.

L'applicazione client firma la richiesta di un token di accesso utilizzando una chiave privata scaricata dalla console API di Google. Dopo aver creato un nuovo ID client, devi scegliere un "Account di servizio". un tipo di applicazione e potrai scaricare la chiave privata. Dai un'occhiata al nostro esempio di account di servizio utilizzando l'API Google Plus.

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

Il codice di esempio riportato sopra crea un'istanza ServiceAccountCredential Gli ambiti obbligatori sono impostati ed è in corso una chiamata a FromCertificate, che carica la chiave privata dal valore X509Certificate2 specificato. Come in tutti gli altri codici di esempio, la credenziale è impostata come HttpClientInitializer.