Este documento descreve o OAuth 2.0, quando usá-lo, como adquirir IDs do cliente e como usá-la com a biblioteca de cliente da API do Google para .NET.
Protocolo OAuth 2.0
OAuth 2.0 é o protocolo de autorização usado pelas APIs do Google. Leia os links abaixo para se familiarizar com o protocolo:
Adquirir IDs e chaves secretas do cliente
É possível conseguir IDs de clientes e chaves secretas no Console de APIs do Google. Há diferentes tipos de IDs do cliente, Portanto, certifique-se de obter o tipo correto para seu aplicativo:
- IDs do cliente de aplicativos da Web
- IDs do cliente do aplicativo instalado
- IDs do cliente da conta de serviço
Em cada um dos snippets de código abaixo (exceto o da conta de serviço), você precisa fazer o download dos
chave secreta do cliente e armazene-a como client_secrets.json
no projeto.
Credenciais
Credenciais do usuário
UserCredential
é uma classe auxiliar thread-safe para usar um token de acesso para acessar recursos protegidos.
Um token de acesso normalmente expira após 1 hora,
Você vai receber um erro se tentar usá-lo.
UserCredential
e
AuthorizationCodeFlow
cuidar da "atualização" automática do token, o que significa simplesmente receber
um novo token de acesso.
Isso é feito usando um token de atualização de longa duração, que você recebe junto com a
token de acesso se você usar o
access_type=offline
durante o fluxo do código de autorização.
Na maioria dos aplicativos, é aconselhável armazenar os token de acesso da credencial e do token de atualização no armazenamento permanente. Caso contrário, será necessário apresentar ao usuário final página de autorização no navegador a cada hora, já que o acesso token expira uma hora depois de ser recebido.
Para garantir que os tokens de acesso e atualização persistam,
você pode fornecer sua própria implementação
IDataStore
,
ou você pode usar uma das seguintes implementações fornecidas pela biblioteca:
-
FileDataStore
para .NET garante que a credencial seja persistente em um arquivo.
ServiceAccountCredential
ServiceAccountCredential
é semelhante ao UserCredential
, mas serve a uma finalidade diferente.
O Google OAuth 2.0 oferece suporte a interações de servidor para servidor, como as que ocorrem entre um aplicativo da Web e o Google Cloud Storage.
O aplicativo solicitante precisa provar a própria identidade para ter acesso a uma API, e o usuário final não precisa estar envolvido.
ServiceAccountCredential
armazena uma chave privada, que é usada para assinar uma solicitação e receber um novo token de acesso.
Tanto UserCredential
quanto ServiceAccountCredential
implementam
IConfigurableHttpClientInitializer
para que você possa registrar cada um deles como:
- Um gerenciador de respostas com falha
Por isso, ele vai atualizar o token se receber um código de status HTTP
401
. - Um interceptador para interceptar o
Authorization
em cada solicitação.
Aplicativos instalados
Exemplo de código usando a 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(); ... } } }
-
Neste exemplo de código, uma nova instância
UserCredential
é criada chamando oGoogleWebAuthorizationBroker.AuthorizeAsync
. Esse método estático recebe o seguinte:- A chave secreta do cliente (ou um stream para a chave secreta do cliente).
- Os escopos necessários.
- É o identificador do usuário.
- O token de cancelamento para cancelar uma operação.
- Um repositório de dados opcional. Se o repositório de dados não for especificado, o padrão será
FileDataStore
. com uma pastaGoogle.Apis.Auth
padrão. A pasta será criada emEnvironment.SpecialFolder.ApplicationData
.
-
O
UserCredential
retornado por esse método é definido como umHttpClientInitializer
. noBooksService
(usando o inicializador). Como explicado acima,UserCredential
implementa uma inicializador de cliente HTTP. -
Observe que, no exemplo de código acima, as informações da chave secreta do cliente são carregadas de um arquivo, mas também é possível fazer o seguinte:
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"));
Confira nossa amostra do Google Livros.
Aplicativos da Web (ASP.NET Core 3)
Suporte das APIs do Google OAuth 2.0 para aplicativos de servidor da Web
O
Google.Apis.Auth.AspNetCore3 é a biblioteca recomendada para a maioria
Cenários de OAuth 2.0 em aplicativos ASP.NET Core 3. Ele implementa uma política do Google
Gerenciador de autenticação OpenIdConnect
. Ele dá suporte à autenticação incremental e define uma
IGoogleAuthProvider
para fornecer credenciais do Google que podem ser usadas com as APIs do Google.
Esta seção descreve como configurar e usar Google.Apis.Auth.AspNetCore3. O código mostrado aqui é baseada Google.Apis.Auth.AspNetCore3.IntegrationTests que é um ASP.NET padrão e totalmente funcional aplicativo Core 3.
Se você quiser acompanhar esta documentação como um tutorial, precisará do seu próprio arquivo ASP.NET. Core 3 e concluir essas etapas como pré-requisito.
Pré-requisitos
- Instale o Google.Apis.Auth.AspNetCore3.
- Estamos usando a API Google Drive para que você também precisam instalar Google.Apis.Drive.v3 .
- Crie um projeto do Google Cloud, caso ainda não tenha um. Seguir estas instruções para fazer isso. Esse será o projeto com o qual seu aplicativo será identificado.
- Ative a API Google Drive. Para ativar as APIs, siga estas instruções.
-
Crie credenciais de autorização que identificarão seu app para o Google. Seguir
estas instruções para criar credenciais de autorização e fazer o download do
arquivo
client_secrets.json
. Dois destaques:- Observe que o cabeçalho O tipo precisa ser aplicativo da Web.
- Para executar este app, o único URI de redirecionamento que você precisa adicionar é
https://localhost:5001/signin-oidc
:
Configurar seu aplicativo para usar Google.Apis.Auth.AspNetCore3
Google.Apis.Auth.AspNetCore3 está configurado na classe Startup
ou semelhante
alternativa que você esteja usando. Os seguintes snippets são extraídos
Startup.cs
no projeto Google.Apis.Auth.AspNetCore3.IntegrationTests.
-
Adicione o código a seguir usando a diretiva para o arquivo
Startup.cs
.using Google.Apis.Auth.AspNetCore3;
-
No método
Startup.ConfigureServices
, adicione o código a seguir e altere a Os marcadores de posição do ID e da chave secreta do cliente com os valores contidos nos arquivoclient_secrets.json
. É possível carregar esses valores diretamente do arquivo JSON ou pode armazená-los de outra maneira segura. Dê uma olhada noClientInfo.Load
no Google.Apis.Auth.AspNetCore3.IntegrationTests projeto para obter um exemplo de como carregar esses valores diretamente do arquivo 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}; }); }
-
No método
Startup.Configure
, adicione a autenticação do ASP.NET Core 3. e os componentes de middleware de autorização para o pipeline, bem como redirecionamentos HTTPS:public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { ... app.UseHttpsRedirection(); ... app.UseAuthentication(); app.UseAuthorization(); ... }
Usar a credencial do usuário para acessar as APIs do Google em nome dele
Agora está tudo pronto para adicionar métodos de ação aos controladores que exigem a credencial do usuário para acessar as APIs do Google em nome deles. O snippet a seguir mostra como listar os arquivos na da conta do Google Drive do usuário autenticado. Note duas coisas principalmente:
-
O usuário não só precisa ser autenticado, mas também ter concedido a permissão
escopo
https://www.googleapis.com/auth/drive.readonly
a seu aplicativo, que especificado pelo atributoGoogleScopedAuthorize
. -
Estamos usando o mecanismo de injeção de dependência padrão do ASP.NET Core 3 para receber uma
IGoogleAuthProvider
que usamos para receber as credenciais do usuário.
O código:
-
Primeiro, adicione o seguinte usando diretivas para seu controlador.
using Google.Apis.Auth.AspNetCore3; using Google.Apis.Auth.OAuth2; using Google.Apis.Drive.v3; using Google.Apis.Services;
-
Adicione a ação do controlador da seguinte maneira (e acompanhe-a com uma visualização simples
que recebe um modelo
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); }
E estes são os princípios básicos. Para saber mais,
HomeController.cs
do projeto Google.Apis.Auth.AspNetCore3.IntegrationTests
para descobrir como:
- Somente autenticação do usuário, sem escopos específicos
- Funcionalidade de saída
- Autorização incremental por código. O snippet acima mostra aumentos autorização por meio de atributos.
- Examinar escopos concedidos atualmente
- Examinar tokens de acesso e atualização
- Force a atualização do token de acesso. Observe que você não precisa fazer isso sozinho, Google.Apis.Auth.AspNetCore3 detecta se o token de acesso expirou ou está perto de expirar e o atualizará automaticamente.
Conta de serviço
As APIs do Google também dão suporte Contas de serviço. Diferentemente do cenário em que um aplicativo cliente solicita acesso aos dados de um usuário final, as contas de serviço oferecem acesso aos próprios dados do aplicativo cliente.
Seu aplicativo cliente assina a solicitação para um token de acesso usando uma chave privada baixada no Console de APIs do Google. Depois de criar um novo ID do cliente, escolha uma "Conta de serviço" tipo de aplicativo e, em seguida, poderá fazer o download da chave privada. Confira nossa amostra de conta de serviço usando a 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(); } } }
O exemplo de código acima cria uma
ServiceAccountCredential
Os escopos necessários estão definidos e há uma chamada para FromCertificate
,
que carrega a chave privada do X509Certificate2
fornecido.
Como em todos os outros exemplos de código, a credencial é definida como HttpClientInitializer
.