Este documento explica como os aplicativos de servidor da Web usam as bibliotecas de cliente das APIs ou os endpoints OAuth 2.0 do Google para implementar a autorização OAuth 2.0 e acessar a API Data do YouTube.
O OAuth 2.0 permite que os usuários compartilhem dados específicos com um aplicativo, mantendo a privacidade de nomes de usuário, senhas e outras informações. Por exemplo, um aplicativo pode usar o OAuth 2.0 para receber permissão para enviar vídeos ao canal do YouTube de um usuário.
Este fluxo do OAuth 2.0 é específico para a autorização do usuário. Ele foi projetado para aplicativos que podem armazenar informações confidenciais e manter o estado. Um aplicativo de servidor da Web devidamente autorizado pode acessar uma API enquanto o usuário interage com o aplicativo ou depois que ele sai dele.
Os aplicativos do servidor da Web também costumam usar
contas de serviço para autorizar solicitações de API, principalmente ao chamar APIs do Cloud para acessar
dados baseados em projeto em vez de dados específicos do usuário. Os aplicativos do servidor da Web podem usar contas de serviço em conjunto com a autorização do usuário.
A API Data do YouTube oferece suporte ao fluxo de contas de serviço apenas para
proprietários de conteúdo do YouTube que possuem e gerenciam vários canais do YouTube.
Especificamente, os proprietários de conteúdo podem usar contas de serviço para chamar métodos de API que
ofereçam suporte ao parâmetro de solicitação onBehalfOfContentOwner
.
Bibliotecas de cliente
Os exemplos específicos de linguagem nesta página usam bibliotecas de cliente das APIs do Google para implementar a autorização do OAuth 2.0. Para executar os exemplos de código, instale primeiro a biblioteca de cliente para sua linguagem.
Quando você usa uma biblioteca de cliente de API do Google para processar o fluxo OAuth 2.0 do seu aplicativo, a biblioteca executa muitas ações que o aplicativo precisaria processar por conta própria. Por exemplo, ele determina quando o aplicativo pode usar ou atualizar tokens de acesso armazenados e quando o aplicativo precisa adquirir o consentimento novamente. A biblioteca de cliente também gera URLs de redirecionamento corretos e ajuda a implementar manipuladores de redirecionamento que trocam códigos de autorização por tokens de acesso.
As bibliotecas de cliente da API do Google para aplicativos do lado do servidor estão disponíveis para as seguintes linguagens:
Pré-requisitos
Ativar as APIs do projeto
Qualquer aplicativo que chame as APIs do Google precisa ativar essas APIs no API Console.
Para ativar uma API para um projeto, faça o seguinte:
- Open the API Library no Google API Console.
- If prompted, select a project, or create a new one.
- Use a página Biblioteca para encontrar e ativar a API YouTube Data. Encontre outras APIs que o aplicativo vai usar e ative-as também.
Criar credenciais de autorização
Qualquer aplicativo que use o OAuth 2.0 para acessar as APIs do Google precisa ter credenciais de autorização que identifiquem o aplicativo para o servidor OAuth 2.0 do Google. As etapas a seguir explicam como criar credenciais para seu projeto. Seus aplicativos podem usar as credenciais para acessar as APIs ativadas para o projeto.
- Go to the Credentials page.
- Clique em Criar credenciais > ID do cliente OAuth.
- Selecione o tipo de aplicativo Aplicativo da Web.
- Preencha o formulário e clique em Criar. Os aplicativos que usam linguagens e frameworks como PHP, Java, Python, Ruby e .NET precisam especificar URIs de redirecionamento autorizados. Os
URIs de redirecionamento são os endpoints para os quais o servidor OAuth 2.0 pode enviar respostas. Esses endpoints precisam obedecer às regras de validação do Google.
Para testes, especifique URIs que se refiram à máquina local, como
http://localhost:8080
. Com isso em mente, todos os exemplos neste documento usamhttp://localhost:8080
como o URI de redirecionamento.Recomendamos que você projete os endpoints de autenticação do app para que o aplicativo não exponha códigos de autorização a outros recursos na página.
Depois de criar suas credenciais, faça o download do arquivo client_secret.json em API Console. Armazene com segurança o arquivo em um local que somente seu aplicativo possa acessar.
Identificar escopos de acesso
Os escopos permitem que seu aplicativo solicite acesso apenas aos recursos necessários, além de permitir que os usuários controlem o nível de acesso que concedem ao seu aplicativo. Portanto, pode haver uma relação inversa entre o número de escopos solicitados e a probabilidade de conseguir o consentimento do usuário.
Antes de começar a implementar a autorização do OAuth 2.0, recomendamos que você identifique os escopos que o app precisará de permissão para acessar.
Também recomendamos que o aplicativo solicite acesso aos escopos de autorização por meio de um processo de autorização incremental, em que o aplicativo solicita acesso aos dados do usuário no contexto. Essa prática recomendada ajuda os usuários a entender melhor por que o app precisa do acesso que está solicitando.
A API YouTube Data v3 usa os seguintes escopos:
Escopos | |
---|---|
https://www.googleapis.com/auth/youtube | Gerenciar sua conta do YouTube |
https://www.googleapis.com/auth/youtube.channel-memberships.creator | Ver uma lista dos membros ativos atuais do canal, do nível deles e de quando se tornaram membros |
https://www.googleapis.com/auth/youtube.force-ssl | Ver, editar e excluir permanentemente vídeos, classificações, comentários e legendas do YouTube |
https://www.googleapis.com/auth/youtube.readonly | Visualize sua conta do YouTube |
https://www.googleapis.com/auth/youtube.upload | Gerenciar seus vídeos do YouTube |
https://www.googleapis.com/auth/youtubepartner | Ver e gerenciar seus ativos e conteúdos associados no YouTube |
https://www.googleapis.com/auth/youtubepartner-channel-audit | Visualiza as informações particulares do seu canal que são relevantes para o processo de auditoria com um parceiro do YouTube |
O documento Escopos da API OAuth 2.0 contém uma lista completa dos escopos que podem ser usados para acessar as APIs do Google.
Requisitos específicos do idioma
Para executar qualquer um dos exemplos de código deste documento, você precisa ter uma Conta do Google, acesso à Internet e um navegador da Web. Se você estiver usando uma das bibliotecas de cliente da API, consulte também os requisitos específicos da linguagem abaixo.
PHP
Para executar os exemplos de código PHP neste documento, você vai precisar de:
- PHP 5.6 ou mais recente com a interface de linha de comando (CLI) e a extensão JSON instaladas.
- A ferramenta de gerenciamento de dependências Composer.
-
Biblioteca de cliente de APIs do Google para PHP:
composer require google/apiclient:^2.10
Python
Para executar os exemplos de código Python neste documento, você vai precisar de:
- Python 2.6 ou superior
- A ferramenta de gerenciamento de pacotes pip.
- Biblioteca de cliente de APIs do Google para Python:
pip install --upgrade google-api-python-client
google-auth
,google-auth-oauthlib
egoogle-auth-httplib2
para autorização do usuário.pip install --upgrade google-auth google-auth-oauthlib google-auth-httplib2
- O framework de aplicativos da Web Flask Python.
pip install --upgrade flask
- A biblioteca HTTP
requests
.pip install --upgrade requests
Ruby
Para executar os exemplos de código Ruby neste documento, você vai precisar de:
- Ruby 2.6 ou superior
-
A biblioteca do Google Auth para Ruby:
gem install googleauth
-
O framework de aplicativos da Web Sinatra Ruby.
gem install sinatra
Node.js
Para executar os exemplos de código Node.js neste documento, você vai precisar de:
- A versão LTS de manutenção, LTS ativa ou atual do Node.js.
-
O cliente Node.js das APIs do Google:
npm install googleapis crypto express express-session
HTTP/REST
Não é necessário instalar nenhuma biblioteca para chamar diretamente os endpoints do OAuth 2.0.
Como conseguir tokens de acesso do OAuth 2.0
As etapas a seguir mostram como seu aplicativo interage com o servidor OAuth 2.0 do Google para receber o consentimento de um usuário e realizar uma solicitação de API em nome dele. Seu aplicativo precisa ter esse consentimento antes de executar uma solicitação da API Google que exija autorização do usuário.
A lista abaixo resume essas etapas:
- O aplicativo identifica as permissões necessárias.
- Seu aplicativo redireciona o usuário para o Google com a lista de permissões solicitadas.
- O usuário decide se concede as permissões ao seu app.
- O aplicativo descobre o que o usuário decidiu.
- Se o usuário conceder as permissões solicitadas, o aplicativo vai extrair os tokens necessários para fazer solicitações de API em nome do usuário.
Etapa 1: definir parâmetros de autorização
A primeira etapa é criar a solicitação de autorização. Essa solicitação define parâmetros que identificam seu aplicativo e definem as permissões que o usuário precisa conceder para ele.
- Se você usa uma biblioteca de cliente do Google para autenticação e autorização do OAuth 2.0, cria e configura um objeto que define esses parâmetros.
- Se você chamar o endpoint do OAuth 2.0 do Google diretamente, vai gerar um URL e definir os parâmetros nele.
As guias abaixo definem os parâmetros de autorização compatíveis para aplicativos de servidor da Web. Os exemplos específicos de linguagem também mostram como usar uma biblioteca de cliente ou de autorização para configurar um objeto que define esses parâmetros.
PHP
O snippet de código abaixo cria um objeto Google\Client()
, que define os
parâmetros na solicitação de autorização.
Esse objeto usa informações do arquivo client_secret.json para identificar seu
aplicativo. Consulte Como criar credenciais de autorização para saber mais sobre
esse arquivo. O objeto também identifica os escopos que o aplicativo está solicitando permissão
para acessar e o URL para o endpoint de autenticação do aplicativo, que processará a resposta do
servidor OAuth 2.0 do Google. Por fim, o código define os parâmetros opcionais access_type
e include_granted_scopes
.
Por exemplo, este código solicita acesso off-line para gerenciar a conta do YouTube de um usuário:
$client = new Google\Client(); // Required, call the setAuthConfig function to load authorization credentials from // client_secret.json file. $client->setAuthConfig('client_secret.json'); // Required, to set the scope value, call the addScope function $client->addScope(GOOGLE_SERVICE_YOUTUBE::YOUTUBE_FORCE_SSL); // Required, call the setRedirectUri function to specify a valid redirect URI for the // provided client_id $client->setRedirectUri('http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php'); // Recommended, offline access will give you both an access and refresh token so that // your app can refresh the access token without user interaction. $client->setAccessType('offline'); // Recommended, call the setState function. Using a state value can increase your assurance that // an incoming connection is the result of an authentication request. $client->setState($sample_passthrough_value); // Optional, if your application knows which user is trying to authenticate, it can use this // parameter to provide a hint to the Google Authentication Server. $client->setLoginHint('hint@example.com'); // Optional, call the setPrompt function to set "consent" will prompt the user for consent $client->setPrompt('consent'); // Optional, call the setIncludeGrantedScopes function with true to enable incremental // authorization $client->setIncludeGrantedScopes(true);
Python
O snippet de código a seguir usa o módulo google-auth-oauthlib.flow
para criar
a solicitação de autorização.
O código constrói um objeto Flow
, que identifica seu aplicativo usando
informações do arquivo client_secret.json que você fez o download depois de
criar credenciais de autorização. Esse objeto também identifica os escopos que seu aplicativo está solicitando permissão para acessar e o URL para o endpoint de autenticação do aplicativo, que manipulará a resposta do servidor OAuth 2.0 do Google. Por fim, o código
define os parâmetros opcionais access_type
e include_granted_scopes
.
Por exemplo, este código solicita acesso off-line para gerenciar a conta do YouTube de um usuário:
import google.oauth2.credentials import google_auth_oauthlib.flow # Required, call the from_client_secrets_file method to retrieve the client ID from a # client_secret.json file. The client ID (from that file) and access scopes are required. (You can # also use the from_client_config method, which passes the client configuration as it originally # appeared in a client secrets file but doesn't access the file itself.) flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file( 'client_secret.json', scopes=['https://www.googleapis.com/auth/youtube.force-ssl']) # Required, indicate where the API server will redirect the user after the user completes # the authorization flow. The redirect URI is required. The value must exactly # match one of the authorized redirect URIs for the OAuth 2.0 client, which you # configured in the API Console. If this value doesn't match an authorized URI, # you will get a 'redirect_uri_mismatch' error. flow.redirect_uri = 'https://www.example.com/oauth2callback' # Generate URL for request to Google's OAuth 2.0 server. # Use kwargs to set optional request parameters. authorization_url, state = flow.authorization_url( # Recommended, enable offline access so that you can refresh an access token without # re-prompting the user for permission. Recommended for web server apps. access_type='offline', # Optional, enable incremental authorization. Recommended as a best practice. include_granted_scopes='true', # Optional, if your application knows which user is trying to authenticate, it can use this # parameter to provide a hint to the Google Authentication Server. login_hint='hint@example.com', # Optional, set prompt to 'consent' will prompt the user for consent prompt='consent')
Ruby
Use o arquivo client_secrets.json que você criou para configurar um objeto cliente no seu aplicativo. Ao configurar um objeto de cliente, você especifica os escopos que seu aplicativo precisa acessar, junto com o URL do endpoint de autenticação do aplicativo, que processa a resposta do servidor OAuth 2.0.
Por exemplo, o código a seguir solicita acesso off-line para gerenciar a conta do YouTube de um usuário:
require 'google/apis/youtube_v3' require "googleauth" require 'googleauth/stores/redis_token_store' client_id = Google::Auth::ClientId.from_file('/path/to/client_secret.json') scope = 'https://www.googleapis.com/auth/youtube.force-ssl' token_store = Google::Auth::Stores::RedisTokenStore.new(redis: Redis.new) authorizer = Google::Auth::WebUserAuthorizer.new(client_id, scope, token_store, '/oauth2callback')
O aplicativo usa o objeto cliente para executar operações do OAuth 2.0, como gerar URLs de solicitação de autorização e aplicar tokens de acesso a solicitações HTTP.
Node.js
O snippet de código abaixo cria um objeto google.auth.OAuth2
, que define os
parâmetros na solicitação de autorização.
Esse objeto usa as informações de seu arquivo client_secret.json para identificar seu aplicativo. Para pedir permissões a um usuário para recuperar um token de acesso, redirecione-o para uma página de consentimento. Para criar um URL da página de consentimento:
const {google} = require('googleapis'); const crypto = require('crypto'); const express = require('express'); const session = require('express-session'); /** * To use OAuth2 authentication, we need access to a CLIENT_ID, CLIENT_SECRET, AND REDIRECT_URI * from the client_secret.json file. To get these credentials for your application, visit * https://console.cloud.google.com/apis/credentials. */ const oauth2Client = new google.auth.OAuth2( YOUR_CLIENT_ID, YOUR_CLIENT_SECRET, YOUR_REDIRECT_URL ); // Access scopes for read-only Drive activity. const scopes = [ 'https://www.googleapis.com/auth/drive.metadata.readonly' ]; // Generate a secure random state value. const state = crypto.randomBytes(32).toString('hex'); // Store state in the session req.session.state = state; // Generate a url that asks permissions for the Drive activity scope const authorizationUrl = oauth2Client.generateAuthUrl({ // 'online' (default) or 'offline' (gets refresh_token) access_type: 'offline', /** Pass in the scopes array defined above. * Alternatively, if only one scope is needed, you can pass a scope URL as a string */ scope: scopes, // Enable incremental authorization. Recommended as a best practice. include_granted_scopes: true, // Include the state parameter to reduce the risk of CSRF attacks. state: state });
Observação importante: o refresh_token
é retornado apenas na primeira
autorização. Confira mais detalhes
aqui.
HTTP/REST
O endpoint do OAuth 2.0 do Google está em https://accounts.google.com/o/oauth2/v2/auth
. Esse endpoint só pode ser acessado por HTTPS. Conexões HTTP simples são recusadas.
O servidor de autorização do Google aceita os seguintes parâmetros de string de consulta para aplicativos de servidor da Web:
Parâmetros | |||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
client_id |
Obrigatório
O ID do cliente do seu aplicativo. Esse valor está no API Console Credentials page. |
||||||||||||||||
redirect_uri |
Obrigatório
Determina para onde o servidor da API redireciona o usuário depois que ele conclui o
fluxo de autorização. O valor precisa corresponder exatamente a um dos URIs de redirecionamento autorizados do
cliente OAuth 2.0, que você configurou no
API Console
Credentials pagedo cliente. Se esse valor não corresponder a um
URI de redirecionamento autorizado para o O esquema, o caso e o caractere de barra inclinada final |
||||||||||||||||
response_type |
Obrigatório
Determina se o endpoint do Google OAuth 2.0 retorna um código de autorização. Defina o valor do parâmetro como |
||||||||||||||||
scope |
Obrigatório
Uma lista de escopos delimitada por espaços que identifica os recursos que o aplicativo pode acessar em nome do usuário. Esses valores informam a tela de consentimento que o Google mostra ao usuário. Os escopos permitem que seu aplicativo solicite acesso apenas aos recursos necessários, além de permitir que os usuários controlem o nível de acesso que concedem ao aplicativo. Portanto, há uma relação inversa entre o número de escopos solicitados e a probabilidade de conseguir o consentimento do usuário. A API YouTube Data v3 usa os seguintes escopos:
O documento Escopos da API OAuth 2.0 (em inglês) fornece uma lista completa de escopos que podem ser usados para acessar as APIs do Google. Recomendamos que o aplicativo solicite acesso aos escopos de autorização no contexto sempre que possível. Ao solicitar acesso aos dados do usuário no contexto, por meio da autorização incremental, você ajuda os usuários a entender melhor por que o app precisa do acesso que está sendo solicitado. |
||||||||||||||||
access_type |
Recomendado
Indica se o app pode atualizar tokens de acesso quando o usuário não está presente
no navegador. Os valores de parâmetro válidos são Defina o valor como |
||||||||||||||||
state |
Recomendado
Especifica qualquer valor de string que seu aplicativo usa para manter o estado entre a solicitação de autorização e a resposta do servidor de autorização.
O servidor retorna o valor exato que você envia como um par É possível usar esse parâmetro para várias finalidades, como direcionar o usuário ao recurso correto no aplicativo, enviar valores de uso único e reduzir a falsificação de solicitações entre sites. Como o |
||||||||||||||||
include_granted_scopes |
Opcional
Permite que os aplicativos usem a autorização incremental para solicitar acesso a outros
escopos no contexto. Se você definir o valor desse parâmetro como |
||||||||||||||||
enable_granular_consent |
Opcional
O valor padrão é Quando o Google ativar permissões granulares para um app, esse parâmetro não vai mais ter efeito. |
||||||||||||||||
login_hint |
Opcional
Se o aplicativo souber qual usuário está tentando fazer a autenticação, ele poderá usar esse parâmetro para fornecer uma dica ao servidor de autenticação do Google. O servidor usa a dica para simplificar o fluxo de login preenchendo o campo de e-mail no formulário de login ou selecionando a sessão de login múltiplo adequada. Defina o valor do parâmetro como um endereço de e-mail ou identificador |
||||||||||||||||
prompt |
Opcional
Uma lista de solicitações delimitada por espaço e que diferencia maiúsculas de minúsculas para apresentar ao usuário. Se você não especificar esse parâmetro, o usuário vai receber uma solicitação apenas na primeira vez que o projeto solicitar acesso. Consulte Solicitar novo consentimento para mais informações. Os valores possíveis são:
|
Etapa 2: redirecionar para o servidor OAuth 2.0 do Google
Redirecionar o usuário para o servidor OAuth 2.0 do Google para iniciar o processo de autenticação e autorização. Normalmente, isso ocorre quando seu aplicativo precisa acessar os dados do usuário pela primeira vez. No caso de autorização incremental, essa etapa também ocorre quando o aplicativo precisa acessar recursos adicionais que ainda não têm permissão para acesso.
PHP
- Gere um URL para solicitar acesso ao servidor OAuth 2.0 do Google:
$auth_url = $client->createAuthUrl();
- Redirecionar o usuário para
$auth_url
:header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
Python
Este exemplo mostra como redirecionar o usuário para o URL de autorização usando o framework de aplicativo da Web Flask:
return flask.redirect(authorization_url)
Ruby
- Gere um URL para solicitar acesso ao servidor OAuth 2.0 do Google:
auth_uri = authorizer.get_authorization_url(login_hint: user_id, request: request)
- Redirecionar o usuário para
auth_uri
.
Node.js
-
Use o URL
authorizationUrl
gerado na Etapa 1generateAuthUrl
para solicitar acesso ao servidor OAuth 2.0 do Google. -
Redirecionar o usuário para
authorizationUrl
.res.redirect(authorizationUrl);
HTTP/REST
Sample redirect to Google's authorization server
The sample URL below requests offline access
(access_type=offline
) to a scope that permits access to view
the user's YouTube account. It uses incremental authorization to ensure that
the new access token covers any scopes to which the user previously granted
the application access. The URL also sets values for the required
redirect_uri
, response_type
, and
client_id
parameters as well as for the state
parameter. The URL contains line breaks and spaces for readability.
https://accounts.google.com/o/oauth2/v2/auth?
scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fyoutube.readonly&
access_type=offline&
include_granted_scopes=true&
state=state_parameter_passthrough_value&
redirect_uri=http%3A%2F%2Flocalhost%2Foauth2callback&
response_type=code&
client_id=client_id
Depois de criar o URL da solicitação, redirecione o usuário para ele.
O servidor OAuth 2.0 do Google autentica o usuário e recebe o consentimento dele para que seu aplicativo acesse os escopos solicitados. A resposta é enviada de volta ao aplicativo usando o URL de redirecionamento especificado.
Etapa 3: o Google solicita consentimento ao usuário
Nesta etapa, o usuário decide se concede ou não o acesso solicitado ao seu app. Nessa etapa, o Google exibe uma janela de consentimento que mostra o nome do seu aplicativo e dos serviços das APIs do Google que ele está solicitando permissão para acessar com as credenciais de autorização do usuário e um resumo dos escopos de acesso a serem concedidos. O usuário pode, então, consentir com a concessão de acesso a um ou mais escopos solicitados pelo aplicativo ou recusar a solicitação.
Seu aplicativo não precisa fazer nada nesse estágio, já que aguarda a resposta do servidor OAuth 2.0 do Google indicando se algum acesso foi concedido. Essa resposta é explicada na etapa a seguir.
Erros
As solicitações para o endpoint de autorização do OAuth 2.0 do Google podem exibir mensagens de erro voltadas para o usuário, em vez dos fluxos de autenticação e autorização esperados. Confira abaixo os códigos de erro comuns e as soluções sugeridas.
admin_policy_enforced
A Conta do Google não consegue autorizar um ou mais escopos solicitados devido às políticas do administrador do Google Workspace. Consulte o artigo de ajuda do administrador do Google Workspace Controle quais apps internos e de terceiros acessam os dados do Google Workspace para saber mais sobre como um administrador pode restringir o acesso a todos os escopos ou escopos sensíveis e restritos até que o acesso seja concedido explicitamente ao seu ID de cliente OAuth.
disallowed_useragent
O endpoint de autorização é exibido dentro de um user-agent incorporado não permitido pelas Políticas do OAuth 2.0 do Google.
Android
Os desenvolvedores do Android podem encontrar essa mensagem de erro ao abrir solicitações de autorização no
android.webkit.WebView
.
Em vez disso, os desenvolvedores precisam usar bibliotecas do Android, como
Login do Google para Android ou
AppAuth para Android da OpenID Foundation.
Os desenvolvedores da Web podem encontrar esse erro quando um app Android abre um link da Web geral em um user-agent incorporado e um usuário navega até o endpoint de autorização do OAuth 2.0 do Google no seu site. Os desenvolvedores precisam permitir que links gerais sejam abertos no gerenciador de links padrão do sistema operacional, que inclui os gerenciadores Android App Links ou o app de navegador padrão. A biblioteca Android Custom Tabs também é uma opção compatível.
iOS
Os desenvolvedores de iOS e macOS podem encontrar esse erro ao abrir solicitações de autorização no
WKWebView
.
Os desenvolvedores devem usar bibliotecas do iOS, como
Login do Google para iOS ou a
AppAuth para iOS da OpenID Foundation.
Os desenvolvedores da Web podem encontrar esse erro quando um app para iOS ou macOS abre um link da Web geral em
um agente do usuário incorporado e um usuário navega até o endpoint de autorização do OAuth 2.0 do Google no
seu site. Os desenvolvedores precisam permitir que links gerais sejam abertos no gerenciador de links padrão do
sistema operacional, que inclui gerenciadores
Universal Links
ou o app de navegador padrão. A
biblioteca SFSafariViewController
também é uma opção aceita.
org_internal
O ID do cliente OAuth na solicitação faz parte de um projeto que limita o acesso a Contas do Google em uma organização do Google Cloud específica. Para mais informações sobre essa opção de configuração, consulte a seção Tipo de usuário no artigo de ajuda "Como configurar a tela de consentimento OAuth".
invalid_client
A chave secreta do cliente OAuth está incorreta. Revise a configuração do cliente OAuth, incluindo o ID e a chave secreta do cliente usados para essa solicitação.
invalid_grant
Ao atualizar um token de acesso ou usar autorização incremental, o token pode ter expirado ou ter sido invalidado. Autentique o usuário novamente e peça o consentimento dele para receber novos tokens. Se esse erro continuar a aparecer, verifique se o aplicativo foi configurado corretamente e se você está usando os tokens e parâmetros corretos na solicitação. Caso contrário, a conta de usuário pode ter sido excluída ou desativada.
redirect_uri_mismatch
O redirect_uri
transmitido na solicitação de autorização não corresponde a um URI de redirecionamento autorizado para o ID do cliente OAuth. Revise os URIs de redirecionamento autorizados no
Google API Console Credentials page.
O parâmetro redirect_uri
pode se referir ao fluxo fora de banda (OOB) do OAuth que foi
descontinuado e não tem mais suporte. Consulte o
guia de migração para atualizar a
integração.
invalid_request
Algo deu errado com a solicitação que você fez. Isso pode acontecer por vários motivos:
- A solicitação não foi formatada corretamente
- A solicitação não tinha parâmetros obrigatórios
- A solicitação usa um método de autorização não aceito pelo Google. Verifique se a integração OAuth usa um método recomendado
Etapa 4: processar a resposta do servidor OAuth 2.0
O servidor OAuth 2.0 responde à solicitação de acesso do aplicativo usando o URL especificado na solicitação.
Se o usuário aprovar a solicitação de acesso, a resposta conterá um código de autorização. Se o usuário não aprovar a solicitação, a resposta conterá uma mensagem de erro. O código de autorização ou a mensagem de erro retornada ao servidor da Web aparece na string de consulta, conforme mostrado abaixo:
Uma resposta de erro:
https://oauth2.example.com/auth?error=access_denied
Uma resposta do código de autorização:
https://oauth2.example.com/auth?code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7
Exemplo de resposta do servidor OAuth 2.0
Para testar esse fluxo, clique no seguinte URL de exemplo, que solicita acesso de leitura somente para visualizar os metadados dos arquivos no seu Google Drive:
https://accounts.google.com/o/oauth2/v2/auth? scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fyoutube.readonly& access_type=offline& include_granted_scopes=true& state=state_parameter_passthrough_value& redirect_uri=http%3A%2F%2Flocalhost%2Foauth2callback& response_type=code& client_id=client_id
Depois de concluir o fluxo do OAuth 2.0, você será redirecionado para http://localhost/oauth2callback
, que provavelmente produzirá um erro 404 NOT FOUND
, a menos que sua máquina local exiba um arquivo nesse endereço. A próxima etapa fornece mais detalhes sobre as informações retornadas no URI quando o usuário é redirecionado de volta para o aplicativo.
Etapa 5: trocar o código de autorização por tokens de atualização e acesso
Depois que o servidor da Web recebe o código de autorização, ele pode trocá-lo por um token de acesso.
PHP
Para trocar um código de autorização por um token de acesso, use o método authenticate
:
$client->authenticate($_GET['code']);
Recupere o token de acesso com o método getAccessToken
:
$access_token = $client->getAccessToken();
Python
Na página de callback, use a biblioteca google-auth
para verificar a resposta do servidor de autorização. Em seguida, use o método flow.fetch_token
para trocar o código de autorização
nessa resposta por um token de acesso:
state = flask.session['state'] flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file( 'client_secret.json', scopes=['https://www.googleapis.com/auth/youtube.force-ssl'], state=state) flow.redirect_uri = flask.url_for('oauth2callback', _external=True) authorization_response = flask.request.url flow.fetch_token(authorization_response=authorization_response) # Store the credentials in the session. # ACTION ITEM for developers: # Store user's access and refresh tokens in your data store if # incorporating this code into your real app. credentials = flow.credentials flask.session['credentials'] = { 'token': credentials.token, 'refresh_token': credentials.refresh_token, 'token_uri': credentials.token_uri, 'client_id': credentials.client_id, 'client_secret': credentials.client_secret, 'scopes': credentials.scopes}
Ruby
Na página de callback, use a biblioteca googleauth
para verificar a resposta do servidor de autorização. Use o método authorizer.handle_auth_callback_deferred
para salvar o
código de autorização e redirecionar para o URL que solicitou a autorização originalmente. Isso
adia a troca do código, armazenando temporariamente os resultados na sessão do usuário.
target_url = Google::Auth::WebUserAuthorizer.handle_auth_callback_deferred(request) redirect target_url
Node.js
Para trocar um código de autorização por um token de acesso, use o método getToken
:
const url = require('url'); // Receive the callback from Google's OAuth 2.0 server. app.get('/oauth2callback', async (req, res) => { let q = url.parse(req.url, true).query; if (q.error) { // An error response e.g. error=access_denied console.log('Error:' + q.error); } else if (q.state !== req.session.state) { //check state value console.log('State mismatch. Possible CSRF attack'); res.end('State mismatch. Possible CSRF attack'); } else { // Get access and refresh tokens (if access_type is offline) let { tokens } = await oauth2Client.getToken(q.code); oauth2Client.setCredentials(tokens); });
HTTP/REST
Para trocar um código de autorização por um token de acesso, chame o endpoint https://oauth2.googleapis.com/token
e defina os seguintes parâmetros:
Campos | |
---|---|
client_id |
O ID do cliente recebido do API Console Credentials page. |
client_secret |
A chave secreta do cliente recebida de API Console Credentials page. |
code |
O código de autorização retornado da solicitação inicial. |
grant_type |
Conforme definido na especificação OAuth 2.0, o valor desse campo precisa ser definido como authorization_code . |
redirect_uri |
Um dos URIs de redirecionamento listados para seu projeto no
API Console
Credentials page para o
client_id fornecido. |
O snippet a seguir mostra uma solicitação de exemplo:
POST /token HTTP/1.1 Host: oauth2.googleapis.com Content-Type: application/x-www-form-urlencoded code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7& client_id=your_client_id& client_secret=your_client_secret& redirect_uri=https%3A//oauth2.example.com/code& grant_type=authorization_code
O Google responde a essa solicitação retornando um objeto JSON que contém um token de acesso de curta duração
e um token de atualização.
O token de atualização só é retornado se o aplicativo definir o parâmetro access_type
como offline
na solicitação inicial ao servidor de autorização
do Google.
A resposta contém os seguintes campos:
Campos | |
---|---|
access_token |
O token que seu aplicativo envia para autorizar uma solicitação de API do Google. |
expires_in |
A vida útil restante do token de acesso em segundos. |
refresh_token |
Um token que pode ser usado para receber um novo token de acesso. Os tokens de atualização são válidos até que o
usuário revogue o acesso.
Novamente, esse campo só estará presente nessa resposta se você definir o parâmetro access_type como offline na solicitação inicial ao servidor de autorização do Google.
|
scope |
Os escopos de acesso concedidos pelo access_token são expressos como uma lista de
strings delimitadas por espaços e diferenciadas por maiúsculas e minúsculas. |
token_type |
O tipo de token retornado. No momento, o valor desse campo é sempre definido como
Bearer . |
O snippet a seguir mostra um exemplo de resposta:
{ "access_token": "1/fFAGRNJru1FTz70BzhT3Zg", "expires_in": 3920, "token_type": "Bearer", "scope": "https://www.googleapis.com/auth/youtube.force-ssl", "refresh_token": "1//xEoDL4iW3cxlI7yDbSRFYNG01kVKM2C-259HOF2aQbI" }
Erros
Ao trocar o código de autorização por um token de acesso, você pode encontrar o erro a seguir em vez da resposta esperada. Confira abaixo os códigos de erro comuns e as resoluções sugeridas.
invalid_grant
O código de autorização informado é inválido ou está em um formato incorreto. Peça um novo código reiniciando o processo OAuth para solicitar o consentimento do usuário novamente.
Como chamar APIs do Google
PHP
Para usar o token de acesso e chamar as APIs do Google, siga estas etapas:
- Se você precisar aplicar um token de acesso a um novo objeto
Google\Client
, por exemplo, se você armazenou o token de acesso em uma sessão do usuário, use o métodosetAccessToken
:$client->setAccessToken($access_token);
- Crie um objeto de serviço para a API que você quer chamar. Você cria um objeto de serviço
fornecendo um objeto
Google\Client
autorizado ao construtor da API que você quer chamar. Por exemplo, para chamar a API YouTube Data:$youtube = new Google_Service_YouTube($client);
- Faça solicitações ao serviço da API usando a interface fornecida pelo objeto de serviço.
Por exemplo, para extrair dados sobre o canal do YouTube do usuário autorizado:
$channel = $youtube->channels->listChannels('snippet', array('mine' => $mine));
Python
Depois de receber um token de acesso, o aplicativo poderá usá-lo para autorizar solicitações de API em nome de uma determinada conta de usuário ou de serviço. Use as credenciais de autorização específicas do usuário para criar um objeto de serviço para a API que você quer chamar e, em seguida, use esse objeto para fazer solicitações de API autorizadas.
- Crie um objeto de serviço para a API que você quer chamar. Você cria um objeto de serviço chamando o método
build
da bibliotecagoogleapiclient.discovery
com o nome e a versão da API e as credenciais do usuário: Por exemplo, para chamar a versão 3 da API YouTube Data:from googleapiclient.discovery import build youtube = build('youtube', 'v3', credentials=credentials)
- Faça solicitações ao serviço da API usando a
interface fornecida pelo objeto de serviço.
Por exemplo, para recuperar dados sobre o canal do YouTube do usuário autorizado:
channel = youtube.channels().list(mine=True, part='snippet').execute()
Ruby
Depois de receber um token de acesso, o aplicativo poderá usá-lo para fazer solicitações de API em nome de uma conta de usuário ou de serviço. Use as credenciais de autorização específicas do usuário para criar um objeto de serviço para a API que você quer chamar e, em seguida, use esse objeto para fazer solicitações de API autorizadas.
- Crie um objeto de serviço para a API que você quer chamar.
Por exemplo, para chamar a versão 3 da API YouTube Data:
youtube = Google::Apis::YoutubeV3::YouTubeService.new
- Defina as credenciais no serviço:
youtube.authorization = credentials
- Faça solicitações ao serviço da API usando a
interface
fornecida pelo objeto de serviço.
Por exemplo, para recuperar dados sobre o canal do YouTube do usuário autorizado:
channel = youtube.list_channels(part, :mine => mine)
Como alternativa, a autorização pode ser concedida para cada método, fornecendo o parâmetro options
a um método:
channel = youtube.list_channels(part, :mine => mine, options: { authorization: auth_client })
Node.js
Depois de receber um token de acesso e defini-lo como o objeto OAuth2
, use o objeto
para chamar as APIs do Google. Seu aplicativo pode usar esse token para autorizar solicitações de API em nome de uma determinada conta de usuário ou de serviço. Crie um objeto de serviço para a API que você quer chamar.
const { google } = require('googleapis'); // Example of using Google Drive API to list filenames in user's Drive. const drive = google.drive('v3'); drive.files.list({ auth: oauth2Client, pageSize: 10, fields: 'nextPageToken, files(id, name)', }, (err1, res1) => { if (err1) return console.log('The API returned an error: ' + err1); const files = res1.data.files; if (files.length) { console.log('Files:'); files.map((file) => { console.log(`${file.name} (${file.id})`); }); } else { console.log('No files found.'); } });
HTTP/REST
Depois que o aplicativo receber um token de acesso, ele poderá usá-lo para fazer chamadas para uma API
do Google em nome de uma determinada
conta de usuário, se os escopos de acesso exigidos pela API tiverem sido concedidos. Para isso, inclua o token de acesso em uma solicitação à API incluindo um parâmetro de consulta access_token
ou um valor Bearer
de cabeçalho HTTP Authorization
. Quando possível,
o cabeçalho HTTP é preferível, porque as strings de consulta tendem a ficar visíveis nos registros do servidor. Na maioria
dos casos, é possível usar uma biblioteca de cliente para configurar suas chamadas para as APIs do Google. Por exemplo, ao
chamar a API Data do YouTube.
A API YouTube Data é compatível apenas com contas de serviço de proprietários de conteúdo do YouTube que têm e gerenciam vários canais do YouTube, como gravadoras e estúdios de cinema.
Teste todas as APIs do Google e confira os escopos delas no OAuth 2.0 Playground.
Exemplos de GET HTTP
Uma chamada para o endpoint
youtube.channels
(a API YouTube Data) usando o cabeçalho HTTP Authorization: Bearer
pode ter a seguinte aparência: É necessário especificar seu próprio token de acesso:
GET /youtube/v3/channels?part=snippet&mine=true HTTP/1.1 Host: www.googleapis.com Authorization: Bearer access_token
Esta é uma chamada para a mesma API do usuário autenticado usando o parâmetro de string de consulta access_token
:
GET https://www.googleapis.com/youtube/v3/channels?access_token=access_token&part=snippet&mine=true
Exemplos de curl
É possível testar esses comandos com o aplicativo de linha de comando curl
. Veja um exemplo que usa a opção de cabeçalho HTTP (preferencial):
curl -H "Authorization: Bearer access_token" https://www.googleapis.com/youtube/v3/channels?part=snippet&mine=true
Ou, alternativamente, a opção do parâmetro da string de consulta:
curl https://www.googleapis.com/youtube/v3/channels?access_token=access_token&part=snippet&mine=true
Exemplo completo
O exemplo a seguir imprime um objeto formatado em JSON mostrando informações sobre o canal do YouTube de um usuário depois que ele autentica e autoriza o aplicativo a gerenciar a conta do YouTube.
PHP
Para executar esse exemplo:
- Em API Console, adicione o URL da máquina local à
lista de URLs de redirecionamento. Por exemplo, adicione
http://localhost:8080
. - Crie um novo diretório e mude para ele. Exemplo:
mkdir ~/php-oauth2-example cd ~/php-oauth2-example
- Instale a biblioteca de cliente de APIs do
Google para PHP usando o Composer:
composer require google/apiclient:^2.10
- Crie os arquivos
index.php
eoauth2callback.php
com o conteúdo abaixo. - Execute o exemplo com um servidor da Web configurado para veicular PHP. Se você usa o PHP 5.6 ou mais recente, pode
usar o servidor da Web de teste integrado do PHP:
php -S localhost:8080 ~/php-oauth2-example
index.php
<?php require_once __DIR__.'/vendor/autoload.php'; session_start(); $client = new Google\Client(); $client->setAuthConfig('client_secrets.json'); $client->addScope(GOOGLE_SERVICE_YOUTUBE::YOUTUBE_FORCE_SSL); if (isset($_SESSION['access_token']) && $_SESSION['access_token']) { $client->setAccessToken($_SESSION['access_token']); $youtube = new Google_Service_YouTube($client); $channel = $youtube->channels->listChannels('snippet', array('mine' => $mine)); echo json_encode($channel); } else { $redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php'; header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL)); }
oauth2callback.php
<?php require_once __DIR__.'/vendor/autoload.php'; session_start(); $client = new Google\Client(); $client->setAuthConfigFile('client_secrets.json'); $client->setRedirectUri('http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php'); $client->addScope(GOOGLE_SERVICE_YOUTUBE::YOUTUBE_FORCE_SSL); if (! isset($_GET['code'])) { // Generate and set state value $state = bin2hex(random_bytes(16)); $client->setState($state); $_SESSION['state'] = $state; $auth_url = $client->createAuthUrl(); header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL)); } else { // Check the state value if (!isset($_GET['state']) || $_GET['state'] !== $_SESSION['state']) { die('State mismatch. Possible CSRF attack.'); } $client->authenticate($_GET['code']); $_SESSION['access_token'] = $client->getAccessToken(); $redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . '/'; header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL)); }
Python
Este exemplo usa a estrutura Flask. Ele
executa um aplicativo da Web em http://localhost:8080
, que permite testar o fluxo do
OAuth 2.0. Ao acessar esse URL, você vai encontrar quatro links:
- Testar uma solicitação de API:este link aponta para uma página que tenta executar uma solicitação de API de exemplo. Se necessário, ele inicia o fluxo de autorização. Se for bem-sucedido, a página vai mostrar a resposta da API.
- Testar o fluxo de autenticação diretamente:este link aponta para uma página que tenta enviar o usuário pelo fluxo de autorização. O app solicita permissão para enviar solicitações de API autorizadas em nome do usuário.
- Revogar credenciais atuais:este link aponta para uma página que revoga as permissões que o usuário já concedeu ao aplicativo.
- Limpar credenciais da sessão do Flask:esse link limpa as credenciais de autorização que estão armazenadas na sessão do Flask. Isso permite que você veja o que aconteceria se um usuário que já concedeu permissão ao app tentasse executar uma solicitação de API em uma nova sessão. Ele também permite que você veja a resposta da API que seu app receberia se um usuário tivesse revogado as permissões concedidas a ele e o app ainda tentasse autorizar uma solicitação com um token de acesso revogado.
# -*- coding: utf-8 -*- import os import flask import requests import google.oauth2.credentials import google_auth_oauthlib.flow import googleapiclient.discovery # This variable specifies the name of a file that contains the OAuth 2.0 # information for this application, including its client_id and client_secret. CLIENT_SECRETS_FILE = "client_secret.json" # This OAuth 2.0 access scope allows for full read/write access to the # authenticated user's account and requires requests to use an SSL connection. SCOPES = ['https://www.googleapis.com/auth/youtube.force-ssl'] API_SERVICE_NAME = 'youtube' API_VERSION = 'v3' app = flask.Flask(__name__) # Note: A secret key is included in the sample so that it works. # If you use this code in your application, replace this with a truly secret # key. See https://flask.palletsprojects.com/quickstart/#sessions. app.secret_key = 'REPLACE ME - this value is here as a placeholder.' @app.route('/') def index(): return print_index_table() @app.route('/test') def test_api_request(): if 'credentials' not in flask.session: return flask.redirect('authorize') # Load credentials from the session. credentials = google.oauth2.credentials.Credentials( **flask.session['credentials']) youtube = googleapiclient.discovery.build( API_SERVICE_NAME, API_VERSION, credentials=credentials) channel = youtube.channels().list(mine=True, part='snippet').execute() # Save credentials back to session in case access token was refreshed. # ACTION ITEM: In a production app, you likely want to save these # credentials in a persistent database instead. flask.session['credentials'] = credentials_to_dict(credentials) return flask.jsonify(**channel) @app.route('/authorize') def authorize(): # Create flow instance to manage the OAuth 2.0 Authorization Grant Flow steps. flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file( CLIENT_SECRETS_FILE, scopes=SCOPES) # The URI created here must exactly match one of the authorized redirect URIs # for the OAuth 2.0 client, which you configured in the API Console. If this # value doesn't match an authorized URI, you will get a 'redirect_uri_mismatch' # error. flow.redirect_uri = flask.url_for('oauth2callback', _external=True) authorization_url, state = flow.authorization_url( # Enable offline access so that you can refresh an access token without # re-prompting the user for permission. Recommended for web server apps. access_type='offline', # Enable incremental authorization. Recommended as a best practice. include_granted_scopes='true') # Store the state so the callback can verify the auth server response. flask.session['state'] = state return flask.redirect(authorization_url) @app.route('/oauth2callback') def oauth2callback(): # Specify the state when creating the flow in the callback so that it can # verified in the authorization server response. state = flask.session['state'] flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file( CLIENT_SECRETS_FILE, scopes=SCOPES, state=state) flow.redirect_uri = flask.url_for('oauth2callback', _external=True) # Use the authorization server's response to fetch the OAuth 2.0 tokens. authorization_response = flask.request.url flow.fetch_token(authorization_response=authorization_response) # Store credentials in the session. # ACTION ITEM: In a production app, you likely want to save these # credentials in a persistent database instead. credentials = flow.credentials flask.session['credentials'] = credentials_to_dict(credentials) return flask.redirect(flask.url_for('test_api_request')) @app.route('/revoke') def revoke(): if 'credentials' not in flask.session: return ('You need to <a href="/authorize">authorize</a> before ' + 'testing the code to revoke credentials.') credentials = google.oauth2.credentials.Credentials( **flask.session['credentials']) revoke = requests.post('https://oauth2.googleapis.com/revoke', params={'token': credentials.token}, headers = {'content-type': 'application/x-www-form-urlencoded'}) status_code = getattr(revoke, 'status_code') if status_code == 200: return('Credentials successfully revoked.' + print_index_table()) else: return('An error occurred.' + print_index_table()) @app.route('/clear') def clear_credentials(): if 'credentials' in flask.session: del flask.session['credentials'] return ('Credentials have been cleared.<br><br>' + print_index_table()) def credentials_to_dict(credentials): return {'token': credentials.token, 'refresh_token': credentials.refresh_token, 'token_uri': credentials.token_uri, 'client_id': credentials.client_id, 'client_secret': credentials.client_secret, 'scopes': credentials.scopes} def print_index_table(): return ('<table>' + '<tr><td><a href="/test">Test an API request</a></td>' + '<td>Submit an API request and see a formatted JSON response. ' + ' Go through the authorization flow if there are no stored ' + ' credentials for the user.</td></tr>' + '<tr><td><a href="/authorize">Test the auth flow directly</a></td>' + '<td>Go directly to the authorization flow. If there are stored ' + ' credentials, you still might not be prompted to reauthorize ' + ' the application.</td></tr>' + '<tr><td><a href="/revoke">Revoke current credentials</a></td>' + '<td>Revoke the access token associated with the current user ' + ' session. After revoking credentials, if you go to the test ' + ' page, you should see an <code>invalid_grant</code> error.' + '</td></tr>' + '<tr><td><a href="/clear">Clear Flask session credentials</a></td>' + '<td>Clear the access token currently stored in the user session. ' + ' After clearing the token, if you <a href="/test">test the ' + ' API request</a> again, you should go back to the auth flow.' + '</td></tr></table>') if __name__ == '__main__': # When running locally, disable OAuthlib's HTTPs verification. # ACTION ITEM for developers: # When running in production *do not* leave this option enabled. os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1' # Specify a hostname and port that are set as a valid redirect URI # for your API project in the Google API Console. app.run('localhost', 8080, debug=True)
Ruby
Este exemplo usa o framework Sinatra.
require 'google/apis/youtube_v3' require 'sinatra' require 'googleauth' require 'googleauth/stores/redis_token_store' configure do enable :sessions set :client_id, Google::Auth::ClientId.from_file('/path/to/client_secret.json') set :scope, Google::Apis::DriveV3::AUTH_DRIVE_METADATA_READONLY set :token_store, Google::Auth::Stores::RedisTokenStore.new(redis: Redis.new) set :authorizer, Google::Auth::WebUserAuthorizer.new(settings.client_id, settings.scope, settings.token_store, '/oauth2callback') end get '/' do user_id = settings.client_id.id credentials = settings.authorizer.get_credentials(user_id, request) if credentials.nil? redirect settings.authorizer.get_authorization_url(login_hint: user_id, request: request) end youtube = Google::Apis::YoutubeV3::YouTubeService.new channel = youtube.list_channels(part, :mine => mine, options: { authorization: auth_client }) "<pre>#{JSON.pretty_generate(channel.to_h)}</pre>" end get '/oauth2callback' do target_url = Google::Auth::WebUserAuthorizer.handle_auth_callback_deferred(request) redirect target_url end
Node.js
Para executar esse exemplo:
-
No API Console, adicione o URL da máquina local à lista de URLs de redirecionamento. Por exemplo, adicione
http://localhost
. - Verifique se você tem a versão LTS de manutenção, LTS ativa ou atual do Node.js instalada.
-
Crie um novo diretório e mude para ele. Exemplo:
mkdir ~/nodejs-oauth2-example cd ~/nodejs-oauth2-example
-
Install the
Google API Client
Library
for Node.js using npm:
npm install googleapis
-
Crie os arquivos
main.js
com o conteúdo abaixo. -
Execute o exemplo:
node .\main.js
main.js
const http = require('http'); const https = require('https'); const url = require('url'); const { google } = require('googleapis'); const crypto = require('crypto'); const express = require('express'); const session = require('express-session'); /** * To use OAuth2 authentication, we need access to a CLIENT_ID, CLIENT_SECRET, AND REDIRECT_URI. * To get these credentials for your application, visit * https://console.cloud.google.com/apis/credentials. */ const oauth2Client = new google.auth.OAuth2( YOUR_CLIENT_ID, YOUR_CLIENT_SECRET, YOUR_REDIRECT_URL ); // Access scopes for read-only Drive activity. const scopes = [ 'https://www.googleapis.com/auth/drive.metadata.readonly' ]; /* Global variable that stores user credential in this code example. * ACTION ITEM for developers: * Store user's refresh token in your data store if * incorporating this code into your real app. * For more information on handling refresh tokens, * see https://github.com/googleapis/google-api-nodejs-client#handling-refresh-tokens */ let userCredential = null; async function main() { const app = express(); app.use(session({ secret: 'your_secure_secret_key', // Replace with a strong secret resave: false, saveUninitialized: false, })); // Example on redirecting user to Google's OAuth 2.0 server. app.get('/', async (req, res) => { // Generate a secure random state value. const state = crypto.randomBytes(32).toString('hex'); // Store state in the session req.session.state = state; // Generate a url that asks permissions for the Drive activity scope const authorizationUrl = oauth2Client.generateAuthUrl({ // 'online' (default) or 'offline' (gets refresh_token) access_type: 'offline', /** Pass in the scopes array defined above. * Alternatively, if only one scope is needed, you can pass a scope URL as a string */ scope: scopes, // Enable incremental authorization. Recommended as a best practice. include_granted_scopes: true, // Include the state parameter to reduce the risk of CSRF attacks. state: state }); res.redirect(authorizationUrl); }); // Receive the callback from Google's OAuth 2.0 server. app.get('/oauth2callback', async (req, res) => { // Handle the OAuth 2.0 server response let q = url.parse(req.url, true).query; if (q.error) { // An error response e.g. error=access_denied console.log('Error:' + q.error); } else if (q.state !== req.session.state) { //check state value console.log('State mismatch. Possible CSRF attack'); res.end('State mismatch. Possible CSRF attack'); } else { // Get access and refresh tokens (if access_type is offline) let { tokens } = await oauth2Client.getToken(q.code); oauth2Client.setCredentials(tokens); /** Save credential to the global variable in case access token was refreshed. * ACTION ITEM: In a production app, you likely want to save the refresh token * in a secure persistent database instead. */ userCredential = tokens; // Example of using Google Drive API to list filenames in user's Drive. const drive = google.drive('v3'); drive.files.list({ auth: oauth2Client, pageSize: 10, fields: 'nextPageToken, files(id, name)', }, (err1, res1) => { if (err1) return console.log('The API returned an error: ' + err1); const files = res1.data.files; if (files.length) { console.log('Files:'); files.map((file) => { console.log(`${file.name} (${file.id})`); }); } else { console.log('No files found.'); } }); } }); // Example on revoking a token app.get('/revoke', async (req, res) => { // Build the string for the POST request let postData = "token=" + userCredential.access_token; // Options for POST request to Google's OAuth 2.0 server to revoke a token let postOptions = { host: 'oauth2.googleapis.com', port: '443', path: '/revoke', method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Content-Length': Buffer.byteLength(postData) } }; // Set up the request const postReq = https.request(postOptions, function (res) { res.setEncoding('utf8'); res.on('data', d => { console.log('Response: ' + d); }); }); postReq.on('error', error => { console.log(error) }); // Post the request with data postReq.write(postData); postReq.end(); }); const server = http.createServer(app); server.listen(80); } main().catch(console.error);
HTTP/REST
Este exemplo em Python usa o framework Flask e a biblioteca Requests para demonstrar o fluxo da Web do OAuth 2.0. Recomendamos usar a biblioteca de cliente de APIs do Google para Python nesse fluxo. O exemplo na guia "Python" usa a biblioteca de cliente.
import json import flask import requests app = flask.Flask(__name__) CLIENT_ID = '123456789.apps.googleusercontent.com' CLIENT_SECRET = 'abc123' # Read from a file or environmental variable in a real app SCOPE = 'https://www.googleapis.com/auth/youtube.force-ssl' REDIRECT_URI = 'http://example.com/oauth2callback' @app.route('/') def index(): if 'credentials' not in flask.session: return flask.redirect(flask.url_for('oauth2callback')) credentials = json.loads(flask.session['credentials']) if credentials['expires_in'] <= 0: return flask.redirect(flask.url_for('oauth2callback')) else: headers = {'Authorization': 'Bearer {}'.format(credentials['access_token'])} req_uri = 'https://www.googleapis.com/youtube/v3/channels/list' r = requests.get(req_uri, headers=headers) return r.text @app.route('/oauth2callback') def oauth2callback(): if 'code' not in flask.request.args: state = str(uuid.uuid4()) flask.session['state'] = state auth_uri = ('https://accounts.google.com/o/oauth2/v2/auth?response_type=code' '&client_id={}&redirect_uri={}&scope={}&state={}').format(CLIENT_ID, REDIRECT_URI, SCOPE, state) return flask.redirect(auth_uri) else: if 'state' not in flask.request.args or flask.request.args['state'] != flask.session['state']: return 'State mismatch. Possible CSRF attack.', 400 auth_code = flask.request.args.get('code') data = {'code': auth_code, 'client_id': CLIENT_ID, 'client_secret': CLIENT_SECRET, 'redirect_uri': REDIRECT_URI, 'grant_type': 'authorization_code'} r = requests.post('https://oauth2.googleapis.com/token', data=data) flask.session['credentials'] = r.text return flask.redirect(flask.url_for('index')) if __name__ == '__main__': import uuid app.secret_key = str(uuid.uuid4()) app.debug = False app.run()
Regras de validação de URIs de redirecionamento
O Google aplica as regras de validação a seguir para redirecionar URIs e ajudar os desenvolvedores a manter os aplicativos seguros. Seus URIs de redirecionamento precisam aderir a essas regras. Consulte a seção 3 do RFC 3986 (em inglês) para ver a definição de domínio, host, caminho, consulta, esquema e userinfo mencionadas abaixo.
Regras de validação | |
---|---|
Esquema |
Os URIs de redirecionamento precisam usar o esquema HTTPS, não o HTTP simples. Os URIs de host local (incluindo URIs de endereço IP de host local) estão isentos dessa regra. |
Host |
Os hosts não podem ser endereços IP brutos. Os endereços IP do host local estão isentos dessa regra. |
Domínio |
“googleusercontent.com” .goo.gl ), a menos que
o app seja o proprietário do domínio. Além disso, se um app que é proprietário de um domínio de encurtador escolher redirecionar para esse domínio, esse URI de redirecionamento precisará conter “/google-callback/” no caminho ou terminar com “/google-callback” . |
Userinfo |
Os URIs de redirecionamento não podem conter o subcomponente "userinfo". |
Caminho |
Os URIs de redirecionamento não podem conter um acesso de travessia de caminho (também chamado de backtracking de diretório),
que é representado por um |
Consulta |
Os URIs de redirecionamento não podem conter redirecionamentos abertos. |
Fragmentos |
Os URIs de redirecionamento não podem conter o componente de fragmento. |
Personagens |
Os URIs de redirecionamento não podem conter determinados caracteres, incluindo:
|
Autorização incremental
No protocolo OAuth 2.0, o app solicita autorização para acessar recursos, que são identificados por escopos. É considerada uma prática recomendada de experiência do usuário solicitar a autorização de recursos quando você precisar deles. Para permitir essa prática, o servidor de autorização do Google oferece suporte à autorização incremental. Esse recurso permite solicitar escopos conforme necessário e, se o usuário conceder permissão para o novo escopo, ele retornará um código de autorização que pode ser trocado por um token contendo todos os escopos que o usuário concedeu ao projeto.
Por exemplo, suponha que um app ajuda os usuários a identificar eventos locais interessantes. O app permite que os usuários assistam vídeos sobre eventos, classifiquem e adicionem vídeos a playlists. Os usuários também podem usar o app para adicionar eventos ao Google Agenda.
Nesse caso, no momento do login, o app pode não precisar ou solicitar acesso a
nenhum escopo. No entanto, se o usuário tentar classificar um vídeo, adicionar um vídeo a uma
playlist ou realizar outra ação do YouTube, o app poderá solicitar acesso ao
escopo https://www.googleapis.com/auth/youtube.force-ssl
.
Da mesma forma, o app pode solicitar acesso ao
escopo https://www.googleapis.com/auth/calendar
se o usuário tentar
adicionar um evento de agenda.
Para implementar a autorização incremental, conclua o fluxo normal de solicitação de um token de acesso, mas verifique se a solicitação de autorização inclui escopos concedidos anteriormente. Essa abordagem permite que o app evite gerenciar vários tokens de acesso.
As regras a seguir se aplicam a um token de acesso recebido de uma autorização incremental:
- O token pode ser usado para acessar recursos correspondentes a qualquer um dos escopos incluídos na nova autorização combinada.
- Quando você usa o token de atualização para a autorização combinada para conseguir um token de acesso, o token de acesso representa a autorização combinada e pode ser usado para qualquer um dos valores de
scope
incluídos na resposta. - A autorização combinada inclui todos os escopos que o usuário concedeu ao projeto de API, mesmo que as concessões tenham sido solicitadas de clientes diferentes. Por exemplo, se um usuário conceder acesso a um escopo usando o cliente para computador de um aplicativo e, em seguida, conceder outro escopo ao mesmo aplicativo por um cliente para dispositivos móveis, a autorização combinada vai incluir os dois escopos.
- Se você revogar um token que representa uma autorização combinada, o acesso a todos os escopos dessa autorização em nome do usuário associado será revogado simultaneamente.
Os exemplos de código específicos da linguagem na Etapa 1: definir parâmetros de autorização e o URL de redirecionamento HTTP/REST de exemplo na Etapa 2: redirecionar para o servidor OAuth 2.0 do Google usam a autorização incremental. Os exemplos de código abaixo também mostram o código que você precisa adicionar para usar a autorização incremental.
PHP
$client->setIncludeGrantedScopes(true);
Python
No Python, defina o argumento de palavra-chave include_granted_scopes
como true
para
garantir que uma solicitação de autorização inclua escopos concedidos anteriormente. É muito possível que include_granted_scopes
não seja o único argumento de palavra-chave definido, como mostrado no exemplo abaixo.
authorization_url, state = flow.authorization_url( # Enable offline access so that you can refresh an access token without # re-prompting the user for permission. Recommended for web server apps. access_type='offline', # Enable incremental authorization. Recommended as a best practice. include_granted_scopes='true')
Ruby
auth_client.update!( :additional_parameters => {"include_granted_scopes" => "true"} )
Node.js
const authorizationUrl = oauth2Client.generateAuthUrl({ // 'online' (default) or 'offline' (gets refresh_token) access_type: 'offline', /** Pass in the scopes array defined above. * Alternatively, if only one scope is needed, you can pass a scope URL as a string */ scope: scopes, // Enable incremental authorization. Recommended as a best practice. include_granted_scopes: true });
HTTP/REST
Neste exemplo, o aplicativo de chamada solicita acesso para recuperar os dados do YouTube Analytics do usuário, além de qualquer outro acesso que ele já tenha concedido ao aplicativo.
GET https://accounts.google.com/o/oauth2/v2/auth? scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fyt-analytics.readonly& access_type=offline& state=security_token%3D138rk%3Btarget_url%3Dhttp...index& redirect_uri=http%3A%2F%2Flocalhost%2Foauth2callback& response_type=code& client_id=client_id& include_granted_scopes=true
Refreshing an access token (offline access)
Access tokens periodically expire and become invalid credentials for a related API request. You can refresh an access token without prompting the user for permission (including when the user is not present) if you requested offline access to the scopes associated with the token.
- If you use a Google API Client Library, the client object refreshes the access token as needed as long as you configure that object for offline access.
- If you are not using a client library, you need to set the
access_type
HTTP query parameter tooffline
when redirecting the user to Google's OAuth 2.0 server. In that case, Google's authorization server returns a refresh token when you exchange an authorization code for an access token. Then, if the access token expires (or at any other time), you can use a refresh token to obtain a new access token.
Requesting offline access is a requirement for any application that needs to access a Google
API when the user is not present. For example, an app that performs backup services or
executes actions at predetermined times needs to be able to refresh its access token when the
user is not present. The default style of access is called online
.
Server-side web applications, installed applications, and devices all obtain refresh tokens during the authorization process. Refresh tokens are not typically used in client-side (JavaScript) web applications.
PHP
If your application needs offline access to a Google API, set the API client's access type to
offline
:
$client->setAccessType("offline");
Depois que um usuário concede acesso off-line aos escopos solicitados, você pode continuar usando o cliente da API para acessar as APIs Google em nome do usuário quando ele estiver off-line. O objeto cliente vai atualizar o token de acesso conforme necessário.
Python
No Python, defina o argumento de palavra-chave access_type
como offline
para garantir
que você possa atualizar o token de acesso sem precisar pedir novamente a permissão
ao usuário. É muito provável que access_type
não seja o único argumento
de palavra-chave definido, conforme mostrado no exemplo abaixo.
authorization_url, state = flow.authorization_url( # Enable offline access so that you can refresh an access token without # re-prompting the user for permission. Recommended for web server apps. access_type='offline', # Enable incremental authorization. Recommended as a best practice. include_granted_scopes='true')
Depois que um usuário conceder acesso off-line aos escopos solicitados, será possível continuar utilizando o cliente de API para acessar as APIs do Google em nome do usuário quando ele estiver off-line. O objeto cliente vai atualizar o token de acesso conforme necessário.
Ruby
Se o aplicativo precisar de acesso off-line a uma API do Google, defina o tipo de acesso do cliente da API como
offline
:
auth_client.update!( :additional_parameters => {"access_type" => "offline"} )
Depois que um usuário conceder acesso off-line aos escopos solicitados, será possível continuar utilizando o cliente de API para acessar as APIs do Google em nome do usuário quando ele estiver off-line. O objeto cliente atualizará o token de acesso conforme necessário.
Node.js
Se o aplicativo precisar de acesso off-line a uma API do Google, defina o tipo de acesso do cliente da API como
offline
:
const authorizationUrl = oauth2Client.generateAuthUrl({ // 'online' (default) or 'offline' (gets refresh_token) access_type: 'offline', /** Pass in the scopes array defined above. * Alternatively, if only one scope is needed, you can pass a scope URL as a string */ scope: scopes, // Enable incremental authorization. Recommended as a best practice. include_granted_scopes: true });
Depois que um usuário concede acesso off-line aos escopos solicitados, você pode continuar usando o cliente da API para acessar as APIs Google em nome do usuário quando ele estiver off-line. O objeto cliente vai atualizar o token de acesso conforme necessário.
Os tokens de acesso expiram. Essa biblioteca vai usar automaticamente um token de atualização para receber um novo token de acesso se ele estiver prestes a expirar. Uma maneira fácil de armazenar sempre os tokens mais recentes é usar o evento de tokens:
oauth2Client.on('tokens', (tokens) => { if (tokens.refresh_token) { // store the refresh_token in your secure persistent database console.log(tokens.refresh_token); } console.log(tokens.access_token); });
Esse evento de tokens ocorre apenas na primeira autorização, e você precisa definir o
access_type
como offline
ao chamar o método generateAuthUrl
para receber o token de atualização. Se você já tiver concedido as permissões necessárias
ao app sem definir as restrições adequadas para receber um token de atualização, será necessário
autorizar novamente o aplicativo para receber um novo token de atualização.
Para definir o refresh_token
mais tarde, use o método setCredentials
:
oauth2Client.setCredentials({ refresh_token: `STORED_REFRESH_TOKEN` });
Quando o cliente tiver um token de atualização, os tokens de acesso serão adquiridos e atualizados automaticamente na próxima chamada à API.
HTTP/REST
Para atualizar um token de acesso, o aplicativo envia uma solicitação HTTPS POST
ao servidor de autorização do Google (https://oauth2.googleapis.com/token
) que inclui os seguintes parâmetros:
Campos | |
---|---|
client_id |
O ID do cliente recebido do API Console. |
client_secret |
A chave secreta do cliente recebida de API Console. |
grant_type |
Conforme
definido na
especificação OAuth 2.0,
o valor desse campo precisa ser definido como refresh_token . |
refresh_token |
O token de atualização retornado da troca de códigos de autorização. |
O snippet a seguir mostra uma solicitação de exemplo:
POST /token HTTP/1.1 Host: oauth2.googleapis.com Content-Type: application/x-www-form-urlencoded client_id=your_client_id& client_secret=your_client_secret& refresh_token=refresh_token& grant_type=refresh_token
Contanto que o usuário não tenha revogado o acesso concedido ao aplicativo, o servidor de token retornará um objeto JSON que contém um novo token de acesso. O snippet a seguir mostra um exemplo de resposta:
{ "access_token": "1/fFAGRNJru1FTz70BzhT3Zg", "expires_in": 3920, "scope": "https://www.googleapis.com/auth/drive.metadata.readonly", "token_type": "Bearer" }
Há limites para o número de tokens de atualização que serão emitidos: um limite por combinação de cliente/usuário e outro por usuário em todos os clientes. Salve os tokens de atualização no armazenamento de longo prazo e continue a usá-los enquanto eles permanecerem válidos. Se o aplicativo solicitar muitos tokens de atualização, ele poderá encontrar esses limites. Nesse caso, os tokens de atualização mais antigos vão deixar de funcionar.
Revogação de um token
Em alguns casos, o usuário pode querer revogar o acesso concedido a um app. Um usuário pode revogar o acesso acessando as Configurações da conta. Consulte a seção Remover acesso a sites ou apps do documento de suporte "Sites e apps de terceiros com acesso à sua conta" para mais informações.
Também é possível que um aplicativo revogue programaticamente o acesso concedido a ele. A revogação programática é importante em casos em que um usuário cancela a inscrição, remove um aplicativo ou os recursos da API exigidos por um app mudaram significativamente. Em outras palavras, parte do processo de remoção pode incluir uma solicitação de API para garantir que as permissões concedidas anteriormente ao aplicativo sejam removidas.
PHP
Para revogar um token de forma programática, chame revokeToken()
:
$client->revokeToken();
Python
Para revogar um token de forma programática, faça uma solicitação para
https://oauth2.googleapis.com/revoke
que inclua o token como um parâmetro e defina o
cabeçalho Content-Type
:
requests.post('https://oauth2.googleapis.com/revoke', params={'token': credentials.token}, headers = {'content-type': 'application/x-www-form-urlencoded'})
Ruby
Para revogar um token de forma programática, faça uma solicitação HTTP para o endpoint oauth2.revoke
:
uri = URI('https://oauth2.googleapis.com/revoke') response = Net::HTTP.post_form(uri, 'token' => auth_client.access_token)
O token pode ser de acesso ou de atualização. Se o token for de acesso e tiver um token de atualização correspondente, ele também será revogado.
Se a revogação for processada, o código de status da resposta será
200
. Em condições de erro, um código de status 400
é retornado com um
código de erro.
Node.js
Para revogar um token de forma programática, faça uma solicitação POST HTTPS para o endpoint /revoke
:
const https = require('https'); // Build the string for the POST request let postData = "token=" + userCredential.access_token; // Options for POST request to Google's OAuth 2.0 server to revoke a token let postOptions = { host: 'oauth2.googleapis.com', port: '443', path: '/revoke', method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Content-Length': Buffer.byteLength(postData) } }; // Set up the request const postReq = https.request(postOptions, function (res) { res.setEncoding('utf8'); res.on('data', d => { console.log('Response: ' + d); }); }); postReq.on('error', error => { console.log(error) }); // Post the request with data postReq.write(postData); postReq.end();
O parâmetro do token pode ser um token de acesso ou de atualização. Se o token for de acesso e tiver um token de atualização correspondente, ele também será revogado.
Se a revogação for processada, o código de status da resposta será
200
. Para condições de erro, um código de status 400
é retornado com um código de erro.
HTTP/REST
Para revogar um token de forma programática, seu app faz uma solicitação para
https://oauth2.googleapis.com/revoke
e inclui o token como um parâmetro:
curl -d -X -POST --header "Content-type:application/x-www-form-urlencoded" \ https://oauth2.googleapis.com/revoke?token={token}
O token pode ser de acesso ou de atualização. Se o token for de acesso e tiver um token de atualização correspondente, ele também será revogado.
Se a revogação for processada, o código de status HTTP da resposta será
200
. Para condições de erro, um código de status HTTP 400
é retornado com um código de erro.
Como implementar a Proteção entre contas
Outra medida que você pode tomar para proteger as contas dos usuários é implementar a proteção entre contas usando o serviço de proteção entre contas do Google. Esse serviço permite que você se inscreva em notificações de eventos de segurança que fornecem informações ao seu app sobre mudanças importantes na conta do usuário. Você pode usar as informações para agir, dependendo de como decidir responder aos eventos.
Alguns exemplos dos tipos de evento enviados ao seu app pelo Serviço de Proteção entre contas do Google são:
-
https://schemas.openid.net/secevent/risc/event-type/sessions-revoked
-
https://schemas.openid.net/secevent/oauth/event-type/token-revoked
-
https://schemas.openid.net/secevent/risc/event-type/account-disabled
Consulte a página Proteger contas de usuários com a Proteção entre contas para mais informações sobre como implementar a Proteção entre contas e a lista completa de eventos disponíveis.