Neste documento, explicamos 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 desse protocolo e acessar as APIs do Google.
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 conseguir permissão dos usuários para armazenar arquivos no Google Drive deles.
Esse fluxo do OAuth 2.0 é específico para 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 autorizado corretamente pode acessar uma API enquanto o usuário interage com o aplicativo ou depois que o usuário sai dele.
Aplicativos de servidor da Web geralmente também usam contas de serviço para autorizar solicitações de API, especialmente quando chamam APIs do Cloud para acessar dados baseados em projetos em vez de dados específicos do usuário. Os aplicativos de servidor da Web podem usar contas de serviço com a autorização do usuário.
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, primeiro instale a biblioteca de cliente da sua linguagem.
Quando você usa uma biblioteca de cliente das APIs do Google para processar o fluxo OAuth 2.0 do seu aplicativo, a biblioteca de cliente 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, bem como quando é necessário obter o consentimento. A biblioteca de cliente também gera URLs de redirecionamento corretos e ajuda a implementar gerenciadores de redirecionamento que trocam códigos de autorização por tokens de acesso.
As bibliotecas de cliente das APIs 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 APIs do Google precisa ativá-las no API Console.
Para ativar uma API para um projeto, faça o seguinte:
- Open the API Library no arquivo Google API Console.
- If prompted, select a project, or create a new one.
- API Library lista todas as APIs disponíveis agrupadas por família de produtos e popularidade. Se a API que você quer ativar não estiver visível na lista, use a pesquisa para encontrá-la ou clique em Ver tudo na família de produtos a que ela pertence.
- Selecione aquela que você quer habilitar e clique no botão Ativar.
- If prompted, enable billing.
- If prompted, read and accept the API's Terms of Service.
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. Os aplicativos podem usar as credenciais para acessar as APIs ativadas para esse 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 aos quais o servidor OAuth 2.0 pode enviar respostas. Esses
endpoints precisam aderir às regras de validação do Google.
Para testar, você pode especificar URIs que se referem à máquina local, por exemplo,
http://localhost:8080
. Com isso em mente, todos os exemplos neste documento usamhttp://localhost:8080
como URI de redirecionamento.Recomendamos que você projete os endpoints de autenticação do app para que ele 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 do API Console. Armazene o arquivo com segurança em um local que só seu aplicativo possa acessar.
Identificar escopos de acesso
Os escopos permitem que seu aplicativo solicite acesso apenas aos recursos necessários e, ao mesmo tempo, permitem que os usuários controlem o nível de acesso que concedem ao aplicativo. Assim, pode haver uma relação inversa entre o número de escopos solicitados e a probabilidade de obter 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 seu app vai precisar de permissão de acesso.
Também recomendamos que seu 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 mais facilmente por que seu aplicativo precisa do acesso que está solicitando.
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 neste documento, você precisará de 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ê precisará de:
- PHP 5.6 ou posterior com a interface de linha de comando (CLI) e a extensão JSON instalada.
- A ferramenta de gerenciamento de dependências do 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ê 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
- O
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 em Python.
pip install --upgrade flask
- A biblioteca HTTP
requests
pip install --upgrade requests
Raquel
Para executar os exemplos de código do Ruby neste documento, você precisará do seguinte:
- Ruby 2.6 ou superior
-
Biblioteca do Google Auth para Ruby:
gem install googleauth
-
O framework de aplicativos da Web Ruby Sinatra.
gem install sinatra
Node.js
Para executar os exemplos de código Node.js neste documento, você precisará de:
- O LTS de manutenção, o LTS ativo ou a versão atual do Node.js.
-
O cliente Node.js das APIs do Google:
npm install googleapis
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 conseguir o consentimento de um usuário para executar uma solicitação de API em nome dele. Seu aplicativo precisa ter esse consentimento antes de executar uma solicitação de API do Google que requer a autorização do usuário.
A lista abaixo resume rapidamente essas etapas:
- O aplicativo identifica as permissões necessárias.
- O aplicativo redireciona o usuário para o Google junto com a lista de permissões solicitadas.
- O usuário decide se quer conceder as permissões ao seu aplicativo.
- Seu aplicativo descobre o que o usuário decidiu.
- Se o usuário concedeu as permissões solicitadas, o aplicativo recupera 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 precisará conceder ao aplicativo.
- 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 Google OAuth 2.0 diretamente, você gerará um URL e definirá os parâmetros nesse URL.
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 seu 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
de acesso e o URL do endpoint de autenticação do aplicativo, que vai 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 somente leitura e off-line ao Google Drive de um usuário:
$client = new Google\Client(); $client->setAuthConfig('client_secret.json'); $client->addScope(Google\Service\Drive::DRIVE_METADATA_READONLY); $client->setRedirectUri('http://' . $_SERVER['HTTP_HOST'] . '/oauth2callback.php'); // 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'); // Using "consent" will prompt the user for consent $client->setPrompt('consent'); $client->setIncludeGrantedScopes(true); // incremental auth
A solicitação especifica as seguintes informações:
Parâmetros | |||||||
---|---|---|---|---|---|---|---|
client_id |
Obrigatório
ID do cliente do aplicativo. Esse valor pode ser encontrado no API Console Credentials page. No PHP, chame a função $client = new Google\Client(); $client->setAuthConfig('client_secret.json'); |
||||||
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 para
o cliente OAuth 2.0 configurado no
API Console
Credentials pagedo cliente. Se esse valor não corresponder a um URI de redirecionamento autorizado para o Observe que o esquema Para definir esse valor em PHP, chame a função $client->setRedirectUri('https://oauth2.example.com/code'); |
||||||
scope |
Obrigatório
Uma lista de escopos delimitada por espaços que identificam os recursos que seu 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 e, ao mesmo tempo, permitem que os usuários controlem o nível de acesso que concedem ao aplicativo. Assim, há uma relação inversa entre o número de escopos solicitados e a probabilidade de obter o consentimento do usuário. Para definir esse valor em PHP, chame a função $client->addScope(Google\Service\Drive::DRIVE_METADATA_READONLY); Recomendamos que seu aplicativo solicite acesso aos escopos de autorização em contexto sempre que possível. Ao solicitar acesso aos dados do usuário no contexto, por meio de autorização incremental, você ajuda os usuários a entender mais facilmente por que seu aplicativo precisa do acesso que está solicitando. |
||||||
access_type |
Recomendável
Indica se o aplicativo pode atualizar os 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 Para definir esse valor em PHP, chame a função $client->setAccessType('offline'); |
||||||
state |
Recomendável
Especifica qualquer valor de string que o 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 enviado como um par de Ele pode ser usado para várias finalidades, como direcionar o usuário para o
recurso correto no aplicativo, enviar valores de uso único e mitigar a falsificação de solicitações
entre sites. Como seu Para definir esse valor em PHP, chame a função $client->setState($sample_passthrough_value); |
||||||
include_granted_scopes |
Opcional
Permite que os aplicativos usem a autorização incremental para solicitar acesso a escopos adicionais no contexto. Se você definir o valor desse parâmetro como Para definir esse valor em PHP, chame a função $client->setIncludeGrantedScopes(true); |
||||||
enable_granular_consent |
Opcional
O valor padrão é |
||||||
login_hint |
Opcional
Se o aplicativo souber qual usuário está tentando se autenticar, 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 automaticamente o campo de e-mail no formulário de login ou selecionando a sessão de login múltiplo apropriada. Defina o valor do parâmetro como um endereço de e-mail ou um identificador Para definir esse valor em PHP, chame a função $client->setLoginHint('None'); |
||||||
prompt |
Opcional
Uma lista de comandos delimitados por espaço e que diferencia maiúsculas de minúsculas para apresentar o usuário. Se você não especificar esse parâmetro, o usuário só vai receber uma solicitação na primeira vez que o projeto solicitar acesso. Consulte Solicitação de novo consentimento para mais informações. Para definir esse valor em PHP, chame a função $client->setPrompt('consent'); Os valores possíveis são:
|
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 cria um objeto Flow
, que identifica seu aplicativo usando as informações do arquivo client_secret.json que você transferiu por download depois de criar credenciais de autorização. Esse objeto também identifica os escopos que o aplicativo está solicitando permissão de acesso 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 somente leitura e off-line ao Google Drive de um usuário:
import google.oauth2.credentials import google_auth_oauthlib.flow # Use the client_secret.json file to identify the application requesting # authorization. The client ID (from that file) and access scopes are required. flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file( 'client_secret.json', scopes=['https://www.googleapis.com/auth/drive.metadata.readonly']) # 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( # 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')
A solicitação especifica as seguintes informações:
Parâmetros | |||||||
---|---|---|---|---|---|---|---|
client_id |
Obrigatório
ID do cliente do aplicativo. Esse valor pode ser encontrado no API Console Credentials page. Em Python, chame o método flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file( 'client_secret.json', scopes=['https://www.googleapis.com/auth/drive.metadata.readonly']) |
||||||
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 para
o cliente OAuth 2.0 configurado no
API Console
Credentials pagedo cliente. Se esse valor não corresponder a um URI de redirecionamento autorizado para o Observe que o esquema Para definir esse valor em Python, defina a propriedade flow.redirect_uri = 'https://oauth2.example.com/code' |
||||||
scope |
Obrigatório
Uma lista de escopos que identificam os recursos que seu 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 e, ao mesmo tempo, permitem que os usuários controlem o nível de acesso que concedem ao aplicativo. Assim, há uma relação inversa entre o número de escopos solicitados e a probabilidade de obter o consentimento do usuário. Em Python, use o mesmo método usado para definir o flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file( 'client_secret.json', scopes=['https://www.googleapis.com/auth/drive.metadata.readonly']) Recomendamos que seu aplicativo solicite acesso aos escopos de autorização em contexto sempre que possível. Ao solicitar acesso aos dados do usuário no contexto, por meio de autorização incremental, você ajuda os usuários a entender mais facilmente por que seu aplicativo precisa do acesso que está solicitando. |
||||||
access_type |
Recomendável
Indica se o aplicativo pode atualizar os 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 Em Python, defina o parâmetro authorization_url, state = flow.authorization_url( access_type='offline', include_granted_scopes='true') |
||||||
state |
Recomendável
Especifica qualquer valor de string que o 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 enviado como um par de Ele pode ser usado para várias finalidades, como direcionar o usuário para o
recurso correto no aplicativo, enviar valores de uso único e mitigar a falsificação de solicitações
entre sites. Como seu Em Python, defina o parâmetro authorization_url, state = flow.authorization_url( access_type='offline', state=sample_passthrough_value, include_granted_scopes='true') |
||||||
include_granted_scopes |
Opcional
Permite que os aplicativos usem a autorização incremental para solicitar acesso a escopos adicionais no contexto. Se você definir o valor desse parâmetro como Em Python, defina o parâmetro authorization_url, state = flow.authorization_url( access_type='offline', include_granted_scopes='true') |
||||||
enable_granular_consent |
Opcional
O valor padrão é |
||||||
login_hint |
Opcional
Se o aplicativo souber qual usuário está tentando se autenticar, 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 automaticamente o campo de e-mail no formulário de login ou selecionando a sessão de login múltiplo apropriada. Defina o valor do parâmetro como um endereço de e-mail ou um identificador Em Python, defina o parâmetro authorization_url, state = flow.authorization_url( access_type='offline', login_hint='None', include_granted_scopes='true') |
||||||
prompt |
Opcional
Uma lista de comandos delimitados por espaço e que diferencia maiúsculas de minúsculas para apresentar o usuário. Se você não especificar esse parâmetro, o usuário só vai receber uma solicitação na primeira vez que o projeto solicitar acesso. Consulte Solicitação de novo consentimento para mais informações. Em Python, defina o parâmetro authorization_url, state = flow.authorization_url( access_type='offline', prompt='consent', include_granted_scopes='true') Os valores possíveis são:
|
Raquel
Use o arquivo client_secrets.json criado para configurar um objeto cliente no aplicativo. Ao configurar um objeto cliente, você especifica os escopos que seu aplicativo precisa acessar, além do URL para o endpoint de autenticação do aplicativo, que manipulará a resposta do servidor OAuth 2.0.
Por exemplo, este código solicita acesso somente leitura e off-line ao Google Drive de um usuário:
require 'google/apis/drive_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/drive.metadata.readonly' token_store = Google::Auth::Stores::RedisTokenStore.new(redis: Redis.new) authorizer = Google::Auth::WebUserAuthorizer.new(client_id, scope, token_store, '/oauth2callback')Your application uses the client object to perform OAuth 2.0 operations, such as generating authorization request URLs and applying access tokens to HTTP requests.
Node.js
The code snippet below creates a google.auth.OAuth2
object, which defines the
parameters in the authorization request.
That object uses information from your client_secret.json file to identify your application. To ask for permissions from a user to retrieve an access token, you redirect them to a consent page. To create a consent page URL:
const {google} = require('googleapis'); /** * 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 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 });
Observação importante: o refresh_token
só é retornado na primeira autorização. Veja mais detalhes
neste link.
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. As 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
ID do cliente do aplicativo. Esse valor pode ser encontrado 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 para
o cliente OAuth 2.0 configurado no
API Console
Credentials pagedo cliente. Se esse valor não corresponder a um URI de redirecionamento autorizado para o Observe que o esquema |
||||||
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 identificam os recursos que seu 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 e, ao mesmo tempo, permitem que os usuários controlem o nível de acesso que concedem ao aplicativo. Assim, há uma relação inversa entre o número de escopos solicitados e a probabilidade de obter o consentimento do usuário. Recomendamos que seu aplicativo solicite acesso aos escopos de autorização em contexto sempre que possível. Ao solicitar acesso aos dados do usuário no contexto, por meio de autorização incremental, você ajuda os usuários a entender mais facilmente por que seu aplicativo precisa do acesso que está solicitando. |
||||||
access_type |
Recomendável
Indica se o aplicativo pode atualizar os 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 |
Recomendável
Especifica qualquer valor de string que o 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 enviado como um par de Ele pode ser usado para várias finalidades, como direcionar o usuário para o
recurso correto no aplicativo, enviar valores de uso único e mitigar a falsificação de solicitações
entre sites. Como seu |
||||||
include_granted_scopes |
Opcional
Permite que os aplicativos usem a autorização incremental para solicitar acesso a escopos adicionais no contexto. Se você definir o valor desse parâmetro como |
||||||
enable_granular_consent |
Opcional
O valor padrão é |
||||||
login_hint |
Opcional
Se o aplicativo souber qual usuário está tentando se autenticar, 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 automaticamente o campo de e-mail no formulário de login ou selecionando a sessão de login múltiplo apropriada. Defina o valor do parâmetro como um endereço de e-mail ou um identificador |
||||||
prompt |
Opcional
Uma lista de comandos delimitados por espaço e que diferencia maiúsculas de minúsculas para apresentar o usuário. Se você não especificar esse parâmetro, o usuário só vai receber uma solicitação na primeira vez que o projeto solicitar acesso. Consulte Solicitação de 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 o 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 primeiro precisa acessar recursos adicionais que ainda não tem permissão.
PHP
- Gere um URL para solicitar acesso no 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
Neste exemplo, mostramos como redirecionar o usuário para o URL de autorização usando a biblioteca de aplicativos da Web do Flask:
return flask.redirect(authorization_url)
Raquel
- Gere um URL para solicitar acesso no servidor OAuth 2.0 do Google:
auth_uri = authorizer.get_authorization_url(login_hint: user_id, request: request)
- Redirecione o usuário para
auth_uri
.
Node.js
-
Use o URL gerado
authorizationUrl
do métodogenerateAuthUrl
da Etapa 1 para solicitar acesso do servidor OAuth 2.0 do Google. -
Redirecione o usuário para
authorizationUrl
.res.writeHead(301, { "Location": authorizationUrl });
HTTP/REST
Sample redirect to Google's authorization server
An example URL is shown below, with line breaks and spaces for readability.
https://accounts.google.com/o/oauth2/v2/auth? scope=https%3A//www.googleapis.com/auth/drive.metadata.readonly& access_type=offline& include_granted_scopes=true& response_type=code& state=state_parameter_passthrough_value& redirect_uri=https%3A//oauth2.example.com/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 seu aplicativo usando o URL de redirecionamento especificado.
Etapa 3: o Google solicita o consentimento do usuário
Nesta etapa, o usuário decide se quer conceder o acesso solicitado ao seu aplicativo. Nesse estágio, o Google exibe uma janela de consentimento que mostra o nome do aplicativo e os serviços da API do Google que estão solicitando permissão de acesso com as credenciais de autorização do usuário e um resumo dos escopos de acesso a serem concedidos. Assim, o usuário poderá conceder acesso a um ou mais escopos solicitados pelo seu aplicativo ou recusar a solicitação.
Seu aplicativo não precisa fazer nada nesta etapa, já que aguarda a resposta do servidor OAuth 2.0 do Google indicando se o 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 códigos de erro comuns e resoluções sugeridas.
admin_policy_enforced
A Conta do Google não pode 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 Controlar quais apps internos e de terceiros acessam os dados do Google Workspace para mais informações sobre como um administrador pode restringir o acesso a todos os escopos ou aos escopos confidenciais e restritos até que o acesso seja explicitamente concedido ao seu ID do 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 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 o
Login do Google para Android ou o
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 acessa 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 Links do app Android ou o app do navegador padrão. A biblioteca Guias personalizadas do Android também é uma opção compatível.
iOS
Os desenvolvedores iOS e macOS podem encontrar esse erro ao abrir solicitações de autorização em
WKWebView
.
Em vez disso, os desenvolvedores precisam usar bibliotecas do iOS, como o
Login do Google para iOS ou o
AppAuth para iOS da OpenID Foundation.
Os desenvolvedores da Web podem encontrar esse erro quando um app iOS ou macOS abre um link da Web geral em
um user agent incorporado e um usuário acessa o endpoint de autorização do OAuth 2.0 do Google
do seu site. Os desenvolvedores precisam permitir que links gerais sejam abertos no gerenciador de links padrão do
sistema operacional, que inclui os gerenciadores
Links universais
ou o app do navegador padrão. A biblioteca
SFSafariViewController
também é uma opção compatível.
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 específica do Google Cloud. 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 permissão OAuth".
invalid_client
A chave secreta do cliente OAuth está incorreta. Revise a configuração do cliente OAuth, incluindo o ID do cliente e a chave secreta usada na 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 você continuar vendo esse erro, verifique se o aplicativo foi configurado corretamente e se estão usando os tokens e parâmetros corretos na solicitação. Caso contrário, a conta do 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
é referente ao fluxo de OAuth fora de banda (OOB, na sigla em inglês) que foi descontinuado e não tem mais suporte. Consulte o guia de migração para atualizar sua integração.
invalid_request
Havia algo errado com o pedido que você fez. Isso pode ocorrer por vários motivos:
- A solicitação não foi formatada corretamente
- A solicitação não tinha os parâmetros obrigatórios
- A solicitação usa um método de autorização que não é compatível com o Google. Verificar se a integração do OAuth usa um método recomendado
Etapa 4: lidar com a resposta do servidor OAuth 2.0
O servidor OAuth 2.0 responde à solicitação de acesso do aplicativo usando o URL especificado nela.
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 vai conter uma mensagem de erro. O código de autorização ou a mensagem de erro retornado 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 URL de amostra a seguir, que solicita acesso somente leitura para visualizar metadados de arquivos no Google Drive:
https://accounts.google.com/o/oauth2/v2/auth? scope=https%3A//www.googleapis.com/auth/drive.metadata.readonly& access_type=offline& include_granted_scopes=true& response_type=code& state=state_parameter_passthrough_value& redirect_uri=https%3A//oauth2.example.com/code& client_id=client_id
Depois de concluir o fluxo do OAuth 2.0, você será redirecionado para http://localhost/oauth2callback
, o que provavelmente gerará um erro 404 NOT FOUND
, a menos que a máquina local exiba um arquivo nesse endereço. A
próxima etapa apresenta mais detalhes sobre as informações retornadas no URI quando o usuário é
redirecionado de volta ao aplicativo.
Etapa 5: trocar o código de autorização para 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/drive.metadata.readonly'], 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}
Raquel
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. if (req.url.startsWith('/oauth2callback')) { // Handle the OAuth 2.0 server response let q = url.parse(req.url, true).query; // 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 extraído de 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 do 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 um exemplo de solicitação:
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 para o 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 da 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 para o servidor de autorização do Google.
|
scope |
Os escopos de acesso concedidos pelo access_token expressos como uma lista de
strings delimitadas por espaço que diferenciam maiúsculas de 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/drive.metadata.readonly", "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. Códigos de erro comuns e resoluções sugeridas estão listados abaixo.
invalid_grant
O código de autorização fornecido é inválido ou está em um formato incorreto. Solicite um novo código reiniciando o processo OAuth para solicitar o consentimento do usuário novamente.
Chamada de APIs do Google
PHP
Use o token de acesso para chamar as APIs do Google concluindo as seguintes etapas:
- Se você precisar aplicar um token de acesso a um novo objeto
Google\Client
, por exemplo, se tiver armazenado o token de acesso em uma sessão de usuário, use o métodosetAccessToken
:$client->setAccessToken($access_token);
- Crie um objeto de serviço para a API que você quer chamar. Crie 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 Drive:$drive = new Google\Service\Drive($client);
- Faça solicitações ao serviço de API usando a interface fornecida pelo objeto de serviço.
Por exemplo, para listar os arquivos no Google Drive do usuário autenticado:
$files = $drive->files->listFiles(array())->getItems();
Python
Depois de receber um token de acesso, o aplicativo pode 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 use esse objeto para fazer solicitações de API autorizadas.
- Crie um objeto de serviço para a API que você quer chamar. Crie 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 Drive:from googleapiclient.discovery import build drive = build('drive', 'v2', credentials=credentials)
- Faça solicitações ao serviço de API usando a interface fornecida pelo objeto de serviço.
Por exemplo, para listar os arquivos no Google Drive do usuário autenticado:
files = drive.files().list().execute()
Raquel
Depois de receber um token de acesso, o aplicativo pode usá-lo para fazer solicitações de API em nome de uma determinada conta de usuário ou conta 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 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 Drive:
drive = Google::Apis::DriveV3::DriveService.new
- Defina as credenciais no serviço:
drive.authorization = credentials
- Faça solicitações ao serviço de API usando a interface fornecida pelo objeto de serviço.
Por exemplo, para listar os arquivos no Google Drive do usuário autenticado:
files = drive.list_files
Como alternativa, a autorização pode ser fornecida por método fornecendo o parâmetro options
a um método:
files = drive.list_files(options: { authorization: credentials })
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. O aplicativo pode usar esse token para autorizar solicitações de API em nome de
uma determinada conta de usuário ou conta 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 recebe um token de acesso, é possível usá-lo para fazer chamadas para uma API do Google em nome de uma determinada conta de usuário, se o escopo de acesso exigido pela API tiver sido concedido. Para fazer isso, inclua o token de acesso em uma solicitação para a API incluindo um parâmetro de consulta access_token
ou um valor Bearer
de cabeçalho HTTP Authorization
. Sempre que possível, recomendamos usar o cabeçalho HTTP, porque as strings de consulta tendem a ficar visíveis nos registros do servidor. Na maioria dos casos, você pode usar uma biblioteca de cliente para configurar suas chamadas para APIs do Google (por exemplo, ao chamar a API Drive Files).
É possível testar todas as APIs do Google e ver os escopos delas no OAuth 2.0 Playground.
Exemplos de HTTP GET
Uma chamada para o endpoint
drive.files
(API Drive Files) usando o cabeçalho HTTP Authorization: Bearer
pode ter a seguinte aparência. Observe que é necessário especificar seu próprio token de acesso:
GET /drive/v2/files HTTP/1.1 Host: www.googleapis.com Authorization: Bearer access_token
Veja a seguir uma chamada para a mesma API feita pelo usuário autenticado usando o parâmetro de string de consulta access_token
:
GET https://www.googleapis.com/drive/v2/files?access_token=access_token
Exemplos de curl
Teste 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/drive/v2/files
Ou, como alternativa, a opção de parâmetro da string de consulta:
curl https://www.googleapis.com/drive/v2/files?access_token=access_token
Exemplo completo
O exemplo a seguir imprime uma lista de arquivos formatados em JSON no Google Drive de um usuário depois que ele é autenticado e dá consentimento para que o aplicativo acesse os metadados do Drive do usuário.
PHP
Para executar esse exemplo:
- No 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. Por exemplo:
mkdir ~/php-oauth2-example cd ~/php-oauth2-example
- Instale a biblioteca de cliente das APIs do Google para PHP usando o Composer (em inglês):
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 disponibilizar PHP. Se você usar o PHP 5.6 ou uma versão mais recente, poderá 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\Drive::DRIVE_METADATA_READONLY); if (isset($_SESSION['access_token']) && $_SESSION['access_token']) { $client->setAccessToken($_SESSION['access_token']); $drive = new Google\Service\Drive($client); $files = $drive->files->listFiles(array())->getItems(); echo json_encode($files); } 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\Drive::DRIVE_METADATA_READONLY); if (! isset($_GET['code'])) { $auth_url = $client->createAuthUrl(); header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL)); } else { $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
Neste exemplo, usamos o framework Flask. Ele
executa um aplicativo da Web em http://localhost:8080
que permite testar o fluxo do
OAuth 2.0. Se você acessar esse URL, verá quatro links:
- Testar uma solicitação de API: este link leva a uma página que tenta executar uma solicitação de API de exemplo. Se necessário, ela inicia o fluxo de autorização. Se for bem-sucedida, a página exibirá a resposta da API.
- Testar o fluxo de autenticação diretamente:esse 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.
- Credenciais da sessão do Flask:esse link remove as credenciais de autorização armazenadas na sessão do Flask. Isso permite ver o que aconteceria se um usuário que já havia concedido 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, e seu 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/drive.metadata.readonly'] API_SERVICE_NAME = 'drive' API_VERSION = 'v2' 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']) drive = googleapiclient.discovery.build( API_SERVICE_NAME, API_VERSION, credentials=credentials) files = drive.files().list().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(**files) @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)
Raquel
Neste exemplo, usamos o framework Sinatra.
require 'google/apis/drive_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 drive = Google::Apis::DriveV3::DriveService.new files = drive.list_files(options: { authorization: credentials }) "<pre>#{JSON.pretty_generate(files.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 o LTS de manutenção, o LTS ativo ou se a versão atual do Node.js está instalada.
-
Crie um novo diretório e mude para ele. Por 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'); /** * 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' ]; // 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 }); /* 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 server = http.createServer(async function (req, res) { // Example on redirecting user to Google's OAuth 2.0 server. if (req.url == '/') { res.writeHead(301, { "Location": authorizationUrl }); } // Receive the callback from Google's OAuth 2.0 server. if (req.url.startsWith('/oauth2callback')) { // 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 { // 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 if (req.url == '/revoke') { // 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(); } res.end(); }).listen(80); } main().catch(console.error);
HTTP/REST
Este exemplo em Python usa os frameworks Flask e Solicitações para demonstrar o fluxo da Web do OAuth 2.0. Recomendamos usar a biblioteca de cliente da API do Google para Python neste 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/drive.metadata.readonly' 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/drive/v2/files' r = requests.get(req_uri, headers=headers) return r.text @app.route('/oauth2callback') def oauth2callback(): if 'code' not in flask.request.args: auth_uri = ('https://accounts.google.com/o/oauth2/v2/auth?response_type=code' '&client_id={}&redirect_uri={}&scope={}').format(CLIENT_ID, REDIRECT_URI, SCOPE) return flask.redirect(auth_uri) else: 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 do URI de redirecionamento
O Google aplica as regras de validação a seguir para redirecionar URIs com o objetivo de ajudar os desenvolvedores a manter os aplicativos seguros. Os URIs de redirecionamento precisam seguir essas regras. Consulte a seção 3 do RFC 3986 para ver a definição de domínio, host, caminho, consulta, esquema e informações do usuário, mencionadas abaixo.
Regras de validação | |
---|---|
Esquema |
Os URIs de redirecionamento precisam usar o esquema HTTPS, e não HTTP simples. Os URIs do host local (incluindo os URIs de endereço IP do localhost) 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 proprietário do domínio. Além disso, se um app proprietário de um domínio mais curto optar por
redirecionar para esse domínio, esse URI de redirecionamento vai precisar conter
“/google-callback/” no caminho ou terminar com
“/google-callback” . |
Informações do usuário |
Os URIs de redirecionamento não podem conter o subcomponente userinfo. |
Caminho |
Os URIs de redirecionamento não podem conter uma travessia de caminhos (também chamada de backtracking de diretório), que é representada por |
Consulta |
Os URIs de redirecionamento não podem conter redirecionamentos abertos. |
Fragmentos |
URIs de redirecionamento não podem conter o componente do fragmento. |
Personagens |
Os URIs de redirecionamento não podem conter determinados caracteres, incluindo:
|
Autorização incremental
No protocolo OAuth 2.0, seu app solicita autorização para acessar recursos, que são identificados por escopos. Solicitar autorização para recursos no momento em que você precisa é uma prática recomendada de experiência do usuário. Para isso, o servidor de autorização do Google é compatível com a autorização incremental. Esse recurso permite solicitar escopos conforme necessário e, se o usuário conceder permissão para o novo escopo, retorna um código de autorização que pode ser trocado por um token com todos os escopos que o usuário concedeu ao projeto.
Por exemplo, um app que permite usar músicas e criar mixes pode precisar de poucos recursos no momento do login, talvez apenas o nome da pessoa que está fazendo login. No entanto, para salvar uma combinação completa, é necessário ter acesso ao Google Drive. A maioria das pessoas acharia natural o acesso ao Google Drive apenas no momento em que o aplicativo realmente precisasse.
Nesse caso, no momento do login, o app pode solicitar que os escopos openid
e
profile
façam o login básico e, em seguida, solicitar o escopo
https://www.googleapis.com/auth/drive.file
no momento da primeira solicitação para salvar uma
combinação.
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 seu app evite a necessidade de 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 receber um token de acesso, ele
representa a autorização combinada e pode ser usado para qualquer um dos
valores
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 por clientes diferentes. Por exemplo, se um usuário concedeu acesso a um escopo usando o cliente de computador de um aplicativo e, em seguida, concedeu outro escopo ao mesmo aplicativo por meio de um cliente para dispositivos móveis, a autorização combinada 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 amostra na Etapa 2: redirecionar para o servidor OAuth 2.0 do Google usam autorização incremental. As amostras 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
Em 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 que você definiu, 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')
Raquel
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
GET https://accounts.google.com/o/oauth2/v2/auth? client_id=your_client_id& response_type=code& state=state_parameter_passthrough_value& scope=https%3A//www.googleapis.com/auth/drive.file& redirect_uri=https%3A//oauth2.example.com/code& prompt=consent& include_granted_scopes=true
Atualizar um token de acesso (acesso off-line)
Os tokens de acesso expiram periodicamente e se tornam credenciais inválidas para uma solicitação de API relacionada. É possível atualizar um token de acesso sem solicitar a permissão do usuário (inclusive quando ele não está presente) caso tenha solicitado acesso off-line aos escopos associados ao token.
- Se você usa uma biblioteca de cliente das APIs do Google, o objeto cliente atualiza o token de acesso conforme necessário, desde que você configure esse objeto para acesso off-line.
- Se você não estiver usando uma biblioteca de cliente, será necessário definir o parâmetro de consulta HTTP
access_type
comooffline
ao redirecionar o usuário para o servidor OAuth 2.0 do Google. Nesse caso, o servidor de autorização do Google retorna um token de atualização quando você troca um código de autorização por um token de acesso. Em seguida, se o token de acesso expirar (ou a qualquer momento), será possível usar um token de atualização para receber um novo token de acesso.
A solicitação de acesso off-line é um requisito para qualquer aplicativo que precise acessar uma API do Google quando o usuário não estiver presente. Por exemplo, um app que realiza serviços de backup ou
executa ações em momentos predeterminados precisa ser capaz de atualizar o token de acesso quando o
usuário não está presente. O estilo de acesso padrão é chamado de online
.
Os aplicativos da Web do lado do servidor, os aplicativos instalados e os dispositivos recebem tokens de atualização durante o processo de autorização. Os tokens de atualização normalmente não são usados em aplicativos da Web no lado do cliente (JavaScript).
PHP
Se o aplicativo precisar de acesso off-line a uma API do Google, defina o tipo de acesso do cliente da API como offline
:
$client->setAccessType("offline");
Depois que um usuário conceder acesso off-line aos escopos solicitados, você poderá continuar usando o cliente de API para acessar as APIs do Google em nome do usuário quando ele estiver off-line. O objeto do cliente atualizará o token de acesso conforme necessário.
Python
Em Python, defina o argumento de palavra-chave access_type
como offline
para garantir que você possa atualizar o token de acesso sem ter que solicitar a permissão do usuário novamente. É muito possível que access_type
não seja o único argumento de palavra-chave que você definiu, 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')
Depois que um usuário conceder acesso off-line aos escopos solicitados, você poderá continuar usando o cliente de API para acessar as APIs do Google em nome do usuário quando ele estiver off-line. O objeto do cliente atualizará o token de acesso conforme necessário.
Raquel
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, você poderá continuar usando o cliente de API para acessar as APIs do Google em nome do usuário quando ele estiver off-line. O objeto do 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 conceder acesso off-line aos escopos solicitados, você poderá continuar usando o cliente de API para acessar as APIs do Google em nome do usuário quando ele estiver off-line. O objeto do cliente atualizará o token de acesso conforme necessário.
Tokens de acesso expiram. Essa biblioteca usará um token de atualização automaticamente para receber um novo token de acesso se ele estiver prestes a expirar. Uma maneira fácil de garantir que você sempre armazene 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 é necessário definir access_type
como offline
ao chamar o método generateAuthUrl
para receber o token de atualização. Se você já tiver concedido ao app as permissões necessárias
sem definir as restrições apropriadas para receber um token de atualização, será necessário
autorizar novamente o aplicativo para receber um novo token.
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, seu aplicativo envia uma solicitação POST
HTTPS
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 extraído de API Console. |
client_secret |
A chave secreta do cliente recebida de API Console. |
grant_type |
Conforme definido na especificação do OAuth 2.0, o valor desse campo precisa ser definido como refresh_token . |
refresh_token |
O token de atualização retornado da troca do código de autorização. |
O snippet a seguir mostra um exemplo de solicitação:
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
Se o usuário não tiver revogado o acesso concedido ao aplicativo, o servidor de token retornará um objeto JSON com 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 cliente/usuário e outro por usuário em todos os clientes. Salve os tokens de atualização em um armazenamento de longo prazo e continue a usá-los enquanto permanecerem válidos. Se o aplicativo solicita muitos tokens de atualização, ele pode atingir esses limites. Nesse caso, os tokens de atualização mais antigos deixarão de funcionar.
Revogar um token
Em alguns casos, o usuário pode querer revogar o acesso dado a um aplicativo. Um usuário pode revogar o acesso acessando Configurações da conta. Para mais informações, consulte a seção Remover o acesso ao site ou app do documento de suporte de sites e apps de terceiros com acesso à sua conta.
Também é possível que um aplicativo revogue programaticamente o acesso concedido a ele. A revogação programática é importante nos casos em que um usuário cancela a inscrição, remove um aplicativo ou os recursos da API exigidos por um app são alterados de maneira significativa. 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 app 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 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'})
Raquel
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 for um token de acesso e tiver um token de atualização correspondente, ele também será revogado.
Se a revogação for processada com êxito, 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.
Node.js
Para revogar um token de forma programática, faça uma solicitação HTTPS POST 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 de token pode ser um token de acesso ou de atualização. Se for um token de acesso e tiver um token de atualização correspondente, ele também será revogado.
Se a revogação for processada com êxito, 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, o aplicativo faz uma solicitação a
https://oauth2.googleapis.com/revoke
e o inclui 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 for um token de acesso e tiver um token de atualização correspondente, ele também será revogado.
Se a revogação for processada com êxito, 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.