Questo documento descrive OAuth 2.0, quando utilizzarlo, come acquisire gli ID client 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 ID client e secret
Puoi ottenere gli ID client e i secret nella console API di Google. Esistono diversi tipi di ID client, pertanto assicurati di scegliere quello corretto per la tua applicazione:
- ID client di applicazioni web
- ID client applicazione installata
- ID client account di servizio
In ognuno degli snippet di codice riportati di seguito (ad eccezione di quello dell'account di servizio), devi scaricare il client secret e archiviarlo come client_secrets.json
nel progetto.
Credenziali
Credenziali utente
UserCredential
è una classe helper sicura per i thread che utilizza un token di accesso per accedere alle risorse protette.
In genere, un token di accesso scade dopo un'ora, dopodiché riceverai un errore se tenti di utilizzarlo.
UserCredential
e
AuthorizationCodeFlow
si occupano di "aggiornare" automaticamente il token, il che significa semplicemente ricevere
un nuovo token di accesso.
A questo scopo, utilizza un token di aggiornamento di lunga durata, che ricevi insieme al token di accesso se utilizzi il parametro access_type=offline
durante il flusso del codice di autorizzazione.
Nella maggior parte delle applicazioni, è consigliabile archiviare il token di accesso della credenziale e il token di aggiornamento in un archivio permanente. In caso contrario, dovrai presentare all'utente finale una pagina di autorizzazione nel browser ogni ora, poiché il token di accesso scade un'ora dopo la ricezione.
Per assicurarti che i token di accesso e aggiornamento vengano mantenuti,
puoi fornire la tua implementazione di
IDataStore
oppure utilizzare una delle seguenti implementazioni fornite dalla libreria:
-
FileDataStore
per .NET assicura che la credenziale sarà 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 poter accedere a un'API, senza che sia necessario coinvolgere un utente finale.
ServiceAccountCredential
memorizza una chiave privata, che viene utilizzata per firmare una richiesta per ottenere un nuovo token di accesso.
Sia UserCredential
che ServiceAccountCredential
implementano
IConfigurableHttpClientInitializer
per consentirti di registrare ognuno di questi come:
- Gestore delle risposte non riuscito, quindi aggiornerà il token se riceve un codice di stato HTTP
401
. - Un intercettore per intercettare l'intestazione
Authorization
su ogni richiesta.
Applicazioni installate
Codice di esempio 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 campione, viene creata una nuova istanza
UserCredential
chiamando il metodoGoogleWebAuthorizationBroker.AuthorizeAsync
. Questo metodo statico ottiene quanto segue:- Il client secret (o un flusso al client secret).
- Gli ambiti richiesti.
- L'identificatore dell'utente.
- Il token per annullare un'operazione.
- Un datastore facoltativo. Se il datastore non è specificato, il valore predefinito è un
FileDataStore
con una cartellaGoogle.Apis.Auth
predefinita. La cartella viene creata inEnvironment.SpecialFolder.ApplicationData
.
-
Il valore
UserCredential
restituito da questo metodo è impostato comeHttpClientInitializer
inBooksService
(mediante l'inizializzazione). Come spiegato in precedenza,UserCredential
implementa un inizializzazione client HTTP. -
Tieni presente 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 alla nostra anteprima di libri.
Applicazioni web (ASP.NET Core 3)
Le API di Google supportano OAuth 2.0 per applicazioni server web.
Google.Apis.Auth.AspNetCore3 è la libreria consigliata da utilizzare per la maggior parte degli scenari OAuth 2.0 basati su Google nelle applicazioni ASP.NET Core 3. Implementa un gestore di autenticazione OpenIdConnect
specifico di Google. Supporta l'autenticazione incrementale e definisce un valore IGoogleAuthProvider
iniettabile 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 qui si basa su Google.Apis.Auth.AspNetCore3.IntegrationTests, un'applicazione ASP.NET Core 3 standard completamente funzionante.
Se vuoi seguire questa documentazione come tutorial, avrai bisogno di una tua applicazione ASP.NET Core 3 e per completare questi passaggi come prerequisito.
Prerequisiti
- Installa il pacchetto Google.Apis.Auth.AspNetCore3.
- Utilizziamo l'API Google Drive, quindi dovrai installare anche il pacchetto Google.Apis.Drive.v3.
- Crea un progetto Google Cloud se non ne hai già uno. Per farlo, segui queste istruzioni. Questo sarà il progetto con cui è identificata la tua app.
- Assicurati di attivare l'API Google Drive. Per abilitare le API, segui queste istruzioni.
-
Crea credenziali di autorizzazione che identificheranno la tua app per Google. Segui
queste istruzioni per creare le credenziali di autorizzazione e scaricare il file
client_secrets.json
. Due punti salienti:- Tieni presente che le credenziali devono essere di tipo Applicazione web.
- Per eseguire questa app, l'unico URI di reindirizzamento che devi aggiungere è
https://localhost:5001/signin-oidc
.
Configura la tua applicazione per utilizzare Google.Apis.Auth.AspNetCore3
Google.Apis.Auth.AspNetCore3 è configurato nella classe Startup
o in un'alternativa simile che potresti utilizzare. I seguenti snippet vengono estratti da
Startup.cs
nel progetto Google.Apis.Auth.AspNetCore3.IntegrationTests.
-
Aggiungi la seguente istruzione "utilizzando" al tuo file
Startup.cs
.using Google.Apis.Auth.AspNetCore3;
-
Nel metodo
Startup.ConfigureServices
, aggiungi il codice seguente, modifica i segnaposto Client ID e Client Secret con i valori contenuti nel fileclient_secrets.json
. Puoi caricare questi valori direttamente dal file JSON oppure archiviarli in qualsiasi altro modo sicuro. Dai un'occhiata al metodoClientInfo.Load
nel progetto 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 alla pipeline i componenti middleware di autenticazione e autorizzazione ASP.NET Core 3, nonché i reindirizzamenti HTTPS:public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { ... app.UseHttpsRedirection(); ... app.UseAuthentication(); app.UseAuthorization(); ... }
Utilizzare le credenziali utente per accedere alle API di Google per loro conto
Ora puoi aggiungere metodi di azione ai controller che richiedono le credenziali utente per accedere alle API di Google per loro conto. Lo snippet seguente mostra come elencare i file nell'account Google Drive dell'utente autenticato. Tieni presente due aspetti principali:
-
L'utente non solo deve essere autenticato, ma deve anche aver concesso all'applicazione
l'ambito
https://www.googleapis.com/auth/drive.readonly
, che specifichi tramite l'attributoGoogleScopedAuthorize
. -
Stiamo utilizzando il meccanismo di inserimento delle dipendenze standard di ASP.NET Core 3 per ricevere un elemento
IGoogleAuthProvider
che utilizziamo per ottenere le credenziali dell'utente.
Il codice:
-
Innanzitutto aggiungi al controller le seguenti istruzioni di utilizzo.
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 segue (e aggiungi 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 a
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. Tieni presente che lo snippet riportato sopra mostra l'autorizzazione incrementale tramite gli attributi.
- Esamina gli ambiti attualmente concessi
- Esaminare 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 rileva se il token di accesso è scaduto o sta per scadere e lo aggiorna automaticamente.
Account di servizio
Le API di Google supportano anche gli account di servizio. A differenza di uno scenario in cui un'applicazione client richiede l'accesso ai dati di un utente finale, gli account di servizio permettono di accedere 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 tipo di applicazione "Account di servizio" e poi scaricare la chiave privata. Dai un'occhiata al nostro esempio di account di servizio che utilizza 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 campione riportato sopra crea un elemento
ServiceAccountCredential
.
Gli ambiti obbligatori sono impostati ed è in corso una chiamata a FromCertificate
, che carica la chiave privata dall'elemento X509Certificate2
specificato.
Come in tutti gli altri codici di esempio, la credenziale è impostata su HttpClientInitializer
.