Migrer vers Google Identity Services

Présentation

Pour obtenir un jeton d'accès par utilisateur permettant d'appeler les API Google, Google propose plusieurs bibliothèques JavaScript:

Ce guide explique comment migrer de ces bibliothèques vers la bibliothèque Google Identity Services.

Grâce à ce guide, vous pourrez:

  • remplacer la bibliothèque Platform obsolète par la bibliothèque Identity Services ; et
  • si vous utilisez la bibliothèque cliente des API, supprimez le module obsolète gapi.auth2, ses méthodes et ses objets, en les remplaçant par des équivalents dans Identity Services.

Pour obtenir une description des modifications apportées à la bibliothèque JavaScript Identity Services, consultez la présentation et le fonctionnement de l'autorisation des utilisateurs. Vous pourrez ainsi passer en revue les termes et concepts clés.

Si vous recherchez l'authentification pour l'inscription et la connexion des utilisateurs, consultez plutôt Migrer depuis Google Sign-In.

Identifier votre flux d'autorisation

Il existe deux flux d'autorisation utilisateur: implicite et avec code d'autorisation.

Examinez votre application Web pour identifier le type de flux d'autorisation actuellement utilisé.

Indique que votre application Web utilise le flux implicite:

  • Votre application Web est entièrement basée sur un navigateur, sans plate-forme backend.
  • L'utilisateur doit être présent pour appeler les API Google. Votre application n'utilise que des jetons d'accès et ne nécessite pas de jetons d'actualisation.
  • Votre application Web charge apis.google.com/js/api.js.
  • Votre implémentation est basée sur le protocole OAuth 2.0 pour les applications Web côté client.
  • Votre application utilise les modules gapi.client ou gapi.auth2 disponibles dans la bibliothèque cliente des API Google pour JavaScript.

Indique que votre application Web utilise le flux de code d'autorisation:

  • Votre implémentation est basée sur les éléments suivants:

  • Votre application s'exécute à la fois dans le navigateur de l'utilisateur et sur votre plate-forme backend.

  • Votre plate-forme backend héberge un point de terminaison de code d'autorisation.

  • Votre plate-forme backend appelle les API Google pour le compte des utilisateurs sans exiger leur présence (mode hors connexion).

  • Les jetons d'actualisation sont gérés et stockés par votre plate-forme backend.

Dans certains cas, votre codebase peut être compatible avec les deux flux.

Choisir un flux d'autorisation

Avant de commencer la migration, vous devez déterminer si la poursuite de votre flux existant ou l'adoption d'un flux différent répond le mieux à vos besoins.

Consultez la section Choisir un flux d'autorisation pour comprendre les principales différences et les compromis entre les deux flux.

Dans la plupart des cas, le flux avec code d'autorisation est recommandé, car il offre le plus haut niveau de sécurité de l'utilisateur. L'implémentation de ce flux permet également à votre plate-forme d'ajouter plus facilement de nouvelles fonctionnalités hors connexion, telles que la récupération de mises à jour pour informer les utilisateurs de modifications importantes apportées à leur agenda, à leurs photos, à leurs abonnements, etc.

Choisissez un flux d'autorisation à l'aide des sélecteurs ci-dessous.

Flux implicite

Procurez-vous un jeton d'accès à utiliser dans le navigateur lorsque l'utilisateur est présent.

Les exemples de flux implicite présentent les applications Web avant et après la migration vers Identity Services.

Flux avec le code d'autorisation

Un code d'autorisation par utilisateur émis par Google est transmis à votre plate-forme de backend, où il est ensuite échangé contre un jeton d'accès et un jeton d'actualisation.

Les exemples de flux de code d'autorisation présentent les applications Web avant et après la migration vers Identity Services.

Tout au long de ce guide, suivez les instructions en gras pour Ajouter, Supprimer, Mettre à jour ou Remplacer.

Modifications apportées à votre application Web intégrée au navigateur

Cette section passe en revue les modifications que vous allez apporter à l'application Web de votre navigateur lors de la migration vers la bibliothèque JavaScript Google Identity Services.

Identifier le code affecté et les tests

Un cookie de débogage peut vous aider à localiser le code affecté et à tester le comportement après l'abandon.

Dans les applications volumineuses ou complexes, il peut être difficile de trouver tout le code affecté par l'abandon du module gapi.auth2. Pour consigner l'utilisation existante d'une fonctionnalité bientôt obsolète dans la console, définissez la valeur du cookie G_AUTH2_MIGRATION sur informational. Vous pouvez également ajouter un signe deux-points suivi d'une valeur de clé pour également vous connecter au stockage de session. Après la connexion et la réception des identifiants, examinez ou envoyez les journaux collectés à un backend pour une analyse ultérieure. Par exemple, informational:showauth2use enregistre l'origine et l'URL dans une clé de stockage de session nommée showauth2use.

Pour vérifier le comportement de l'application lorsque le module gapi.auth2 n'est plus chargé, définissez la valeur du cookie G_AUTH2_MIGRATION sur enforced. Cela permet de tester le comportement après l'abandon avant la date d'application.

Valeurs possibles pour le cookie G_AUTH2_MIGRATION:

  • enforced Ne chargez pas le module gapi.auth2.
  • informational Enregistrer l'utilisation d'une fonctionnalité obsolète dans la console JavaScript Consignez également le stockage de session lorsqu'un nom de clé facultatif est défini : informational:key-name.

Pour minimiser l'impact sur les utilisateurs, nous vous recommandons de définir ce cookie localement lors du développement et du test, avant de l'utiliser dans des environnements de production.

Bibliothèques et modules

Le module gapi.auth2 gère l'authentification des utilisateurs pour la connexion et le flux implicite d'autorisation. Il remplace ce module obsolète, ainsi que ses objets et méthodes par la bibliothèque Google Identity Services.

Ajoutez la bibliothèque Identity Services à votre application Web en l'incluant dans votre document:

<script src="https://accounts.google.com/gsi/client" async defer></script>

Supprimez toutes les instances de chargement du module auth2 à l'aide de gapi.load('auth2', function).

La bibliothèque Google Identity Services remplace l'utilisation du module gapi.auth2. Vous pouvez continuer à utiliser en toute sécurité le module gapi.client de la bibliothèque cliente des API Google pour JavaScript, et profiter de sa création automatique de méthodes JS appelables à partir d'un document de découverte, du traitement par lot de plusieurs appels d'API et de la fonctionnalité de gestion CORS.

Cookies

L'autorisation des utilisateurs ne nécessite pas l'utilisation de cookies.

Consultez Migrer depuis Google Sign-In pour en savoir plus sur l'utilisation des cookies par l'authentification des utilisateurs et la section Comment Google utilise les cookies à des fins d'utilisation par d'autres produits et services Google.

Identifiants

Google Identity Services distingue l'authentification et l'autorisation des utilisateurs en deux opérations distinctes. Les identifiants de l'utilisateur sont distincts: le jeton d'identification servant à identifier un utilisateur est renvoyé séparément du jeton d'accès utilisé pour l'autorisation.

Pour afficher ces modifications, consultez Exemples d'identifiants.

Flux implicite

Séparez l'authentification et l'autorisation des utilisateurs en supprimant la gestion des profils utilisateur des flux d'autorisation.

Supprimez ces références client JavaScript Google Sign-In:

Méthodes

  • GoogleUser.getBasicProfile()
  • GoogleUser.getId()

Flux avec le code d'autorisation

Identity Services sépare les identifiants intégrés au navigateur en jeton d'ID et jeton d'accès. Cette modification ne s'applique pas aux identifiants obtenus via des appels directs aux points de terminaison Google OAuth 2.0 depuis votre plate-forme backend ou via les bibliothèques exécutées sur un serveur sécurisé de votre plate-forme, comme le client Node.js des API Google.

État de la session

Auparavant, Google Sign-In vous permettait de gérer l'état de connexion des utilisateurs avec:

Vous êtes responsable de la gestion de l'état de connexion et des sessions utilisateur à votre application Web.

Supprimez ces références client JavaScript Google Sign-In:

Objets:

  • gapi.auth2.SignInOptions

Méthodes :

  • GoogleAuth.attachClickHandler()
  • GoogleAuth.isSignedIn()
  • GoogleAuth.isSignedIn.get()
  • GoogleAuth.isSignedIn.listen()
  • GoogleAuth.signIn()
  • GoogleAuth.signOut()
  • GoogleAuth.currentUser.get()
  • GoogleAuth.currentUser.listen()
  • GoogleUser.isSignedIn()

Configuration du client

Mettez à jour votre application Web pour initialiser un client de jeton pour le flux de code implicite ou d'autorisation.

Supprimez ces références client JavaScript Google Sign-In:

Objets:

  • gapi.auth2.ClientConfig
  • gapi.auth2.OfflineAccessOptions

Méthodes :

  • gapi.auth2.getAuthInstance()
  • GoogleUser.grant()

Flux implicite

Ajoutez un objet TokenClientConfig et un appel initTokenClient() pour configurer votre application Web, en suivant l'exemple de la section Initialiser un client de jeton.

Remplacez les références de client JavaScript Google Sign-In par les services d'identité Google:

Objets:

  • gapi.auth2.AuthorizeConfig avec TokenClientConfig

Méthodes :

  • gapi.auth2.init() avec google.accounts.oauth2.initTokenClient()

Paramètres :

  • gapi.auth2.AuthorizeConfig.login_hint avec TokenClientConfig.login_hint.
  • gapi.auth2.GoogleUser.getHostedDomain() correspond à TokenClientConfig.hd.

Flux avec le code d'autorisation

Ajoutez un objet CodeClientConfig et un appel initCodeClient() pour configurer votre application Web, en suivant l'exemple de la section Initialiser un client Code.

Lorsque vous passez du flux de code d'autorisation au flux implicite:

Supprimer les références client JavaScript Google Sign-In

Objets:

  • gapi.auth2.AuthorizeConfig

Méthodes :

  • gapi.auth2.init()

Paramètres :

  • gapi.auth2.AuthorizeConfig.login_hint
  • gapi.auth2.GoogleUser.getHostedDomain()

Demande de jeton

Un geste de l'utilisateur, tel qu'un clic sur un bouton, génère une requête qui renvoie un jeton d'accès directement au navigateur de l'utilisateur via le flux implicite ou à votre plate-forme backend après avoir échangé un code d'autorisation par utilisateur contre un jeton d'accès et un jeton d'actualisation.

Flux implicite

Les jetons d'accès peuvent être obtenus et utilisés dans le navigateur lorsque l'utilisateur est connecté et a une session active avec Google. Pour le mode implicite, un geste de l'utilisateur est nécessaire pour demander un jeton d'accès, même si une requête a déjà eu lieu.

Remplacez les références de client JavaScript Google Sign-In par Google Identity Services :

Méthodes :

  • gapi.auth2.authorize() avec TokenClient.requestAccessToken()
  • GoogleUser.reloadAuthResponse() avec TokenClient.requestAccessToken()

Ajoutez un lien ou un bouton pour appeler requestAccessToken() afin de lancer le flux d'expérience utilisateur pop-up afin de demander un jeton d'accès ou d'obtenir un nouveau jeton lorsque le jeton existant expire.

Mettez à jour votre codebase comme suit:

  • Déclenchez le flux de jetons OAuth 2.0 avec requestAccessToken().
  • Acceptez les autorisations incrémentielles en utilisant requestAccessToken et OverridableTokenClientConfig pour séparer une requête pour de nombreux champs d'application en plusieurs requêtes plus petites.
  • Demandez un nouveau jeton lorsque le jeton existant arrive à expiration ou est révoqué.

L'utilisation de plusieurs champs d'application peut nécessiter des modifications structurelles de votre codebase pour demander l'accès aux champs d'application uniquement lorsque c'est nécessaire, et non en une seule fois. C'est ce qu'on appelle une autorisation incrémentielle. Chaque requête doit contenir le moins de champs d'application possible et, idéalement, un seul champ d'application. Découvrez comment gérer le consentement de l'utilisateur pour savoir comment mettre à jour votre application pour les autorisations incrémentielles.

Lorsqu'un jeton d'accès expire, le module gapi.auth2 obtient automatiquement un nouveau jeton d'accès valide pour votre application Web. Pour améliorer la sécurité des utilisateurs, ce processus d'actualisation automatique des jetons n'est pas compatible avec la bibliothèque Google Identity Services. Votre application Web doit être mise à jour pour détecter un jeton d'accès expiré et en demander un nouveau. Pour en savoir plus, consultez la section "Gestion des jetons" ci-dessous.

Flux avec le code d'autorisation

Ajoutez un lien ou un bouton pour appeler requestCode() et demander un code d'autorisation à Google. Pour obtenir un exemple, consultez Déclencher un flux de code OAuth 2.0.

Consultez la section "Gestion des jetons" ci-dessous pour savoir comment répondre à un jeton d'accès expiré ou révoqué.

Gestion des jetons

Ajoutez la gestion des erreurs pour détecter l'échec des appels d'API Google en cas d'utilisation d'un jeton d'accès expiré ou révoqué, et pour demander un nouveau jeton d'accès valide.

Les API Google renvoient un code d'état HTTP 401 Unauthorized et un message d'erreur invalid_token lorsqu'un jeton d'accès arrivé à expiration ou révoqué est utilisé. Pour obtenir un exemple, consultez la section Réponse de jeton non valide.

Jetons expirés

Les jetons d'accès ont une courte durée de vie et ne sont souvent valides que pendant quelques minutes.

Révocation des jetons

Le titulaire d'un compte Google peut à tout moment révoquer un consentement précédemment accordé. Cela invalide les jetons d'accès et les jetons d'actualisation existants. La révocation peut être déclenchée depuis votre plate-forme à l'aide de revoke() ou d'un compte Google.

Remplacez les références de client JavaScript Google Sign-In par Google Identity Services :

Méthodes :

  • getAuthInstance().disconnect() avec google.accounts.oauth2.revoke()
  • GoogleUser.disconnect() avec google.accounts.oauth2.revoke()

Appelez revoke lorsqu'un utilisateur supprime son compte sur votre plate-forme ou souhaite retirer l'autorisation de partager des données avec votre application.

Google affiche une boîte de dialogue de consentement lorsque votre application Web ou votre plate-forme backend demande un jeton d'accès. Consultez les exemples de boîtes de dialogue de collecte du consentement affichées par Google auprès des utilisateurs.

Avant d'émettre un jeton d'accès pour votre application, vous devez disposer d'une session Google existante et active pour demander le consentement de l'utilisateur et enregistrer le résultat. L'utilisateur peut être invité à se connecter à un compte Google si aucune session existante n'a déjà été établie.

Connexion de l'utilisateur

Les utilisateurs peuvent être connectés à un compte Google dans un onglet de navigateur distinct, ou de manière native via un navigateur ou un système d'exploitation. Nous vous recommandons d'ajouter la fonctionnalité Se connecter avec Google à votre site pour établir une session active entre un compte Google et le navigateur lorsque l'utilisateur ouvre votre application pour la première fois. Vous bénéficierez ainsi des avantages suivants:

  • Minimise le nombre de fois où un utilisateur doit se connecter. La demande d'un jeton d'accès lance le processus de connexion au compte Google si aucune session active n'existe déjà.
  • Utilisez directement le champ d'identifiant email du jeton d'ID JWT comme valeur du paramètre login_hint dans les objets CodeClientConfig ou TokenClientConfig. Cela est particulièrement utile si votre plate-forme ne dispose pas d'un système de gestion de comptes utilisateur.
  • Recherchez un compte Google et associez-le à un compte utilisateur local existant sur votre plate-forme afin de réduire le nombre de comptes en double sur votre plate-forme.
  • Lorsqu'un compte local est créé, les boîtes de dialogue et le flux d'inscription peuvent être clairement séparés des boîtes de dialogue et des flux d'authentification des utilisateurs, ce qui réduit le nombre d'étapes requises et améliore le taux d'abandon.

Après la connexion et avant l'émission d'un jeton d'accès, les utilisateurs doivent donner leur autorisation pour votre application pour les champs d'application demandés.

Après le consentement, un jeton d'accès est renvoyé avec la liste des niveaux d'accès approuvés ou refusés par l'utilisateur.

Les autorisations précises permettent aux utilisateurs d'approuver ou de refuser des niveaux d'accès individuels. Lorsque vous demandez l'accès à plusieurs champs d'application, chaque champ d'application est accordé ou refusé indépendamment des autres champs d'application. En fonction du choix de l'utilisateur, votre application active de manière sélective des fonctionnalités qui dépendent d'un champ d'application individuel.

Flux implicite

Remplacez les références de client JavaScript Google Sign-In par les services d'identité Google:

Objets:

  • gapi.auth2.AuthorizeResponse avec TokenClient.TokenResponse
  • gapi.auth2.AuthResponse avec TokenClient.TokenResponse

Méthodes :

  • GoogleUser.hasGrantedScopes() avec google.accounts.oauth2.hasGrantedAllScopes()
  • GoogleUser.getGrantedScopes() avec google.accounts.oauth2.hasGrantedAllScopes()

Supprimez les références client JavaScript de Google Sign-In:

Méthodes :

  • GoogleUser.getAuthResponse()

Mettez à jour votre application Web avec hasGrantedAllScopes() et hasGrantedAnyScope() en suivant cet exemple d'autorisations précises.

Flux avec le code d'autorisation

Mettez à jour ou ajoutez un point de terminaison de code d'autorisation à votre plate-forme de backend en suivant les instructions de la section Gestion du code d'autorisation.

Mettez à jour votre plate-forme pour suivre les étapes décrites dans le guide Utiliser un modèle de code pour valider la requête et obtenir un jeton d'accès et un jeton d'actualisation.

Mettez à jour votre plate-forme pour activer ou désactiver de manière sélective des fonctionnalités et des fonctionnalités en fonction des niveaux d'accès individuels que l'utilisateur a approuvés. Pour ce faire, suivez les instructions sur l'autorisation incrémentielle et examinez les niveaux d'accès accordés par l'utilisateur.

Exemples de flux implicites

Ancienne méthode

Bibliothèque cliente GAPI

Exemple de bibliothèque cliente des API Google pour JavaScript s'exécutant dans un navigateur à l'aide d'une boîte de dialogue pop-up demandant le consentement de l'utilisateur.

Le module gapi.auth2 est automatiquement chargé et utilisé par gapi.client.init(). Il est donc masqué.

<!DOCTYPE html>
  <html>
    <head>
      <script src="https://apis.google.com/js/api.js"></script>
      <script>
        function start() {
          gapi.client.init({
            'apiKey': 'YOUR_API_KEY',
            'clientId': 'YOUR_CLIENT_ID',
            'scope': 'https://www.googleapis.com/auth/cloud-translation',
            'discoveryDocs': ['https://www.googleapis.com/discovery/v1/apis/translate/v2/rest'],
          }).then(function() {
            // Execute an API request which is returned as a Promise.
            // The method name language.translations.list comes from the API discovery.
            return gapi.client.language.translations.list({
              q: 'hello world',
              source: 'en',
              target: 'de',
            });
          }).then(function(response) {
            console.log(response.result.data.translations[0].translatedText);
          }, function(reason) {
            console.log('Error: ' + reason.result.error.message);
          });
        };

        // Load the JavaScript client library and invoke start afterwards.
        gapi.load('client', start);
      </script>
    </head>
    <body>
      <div id="results"></div>
    </body>
  </html>

Bibliothèque cliente JavaScript

OAuth 2.0 pour les applications Web côté client s'exécutant dans un navigateur à l'aide d'une boîte de dialogue contextuelle pour le consentement de l'utilisateur

Le module gapi.auth2 est chargé manuellement.

<!DOCTYPE html>
<html><head></head><body>
<script>
  var GoogleAuth;
  var SCOPE = 'https://www.googleapis.com/auth/drive.metadata.readonly';
  function handleClientLoad() {
    // Load the API's client and auth2 modules.
    // Call the initClient function after the modules load.
    gapi.load('client:auth2', initClient);
  }

  function initClient() {
    // In practice, your app can retrieve one or more discovery documents.
    var discoveryUrl = 'https://www.googleapis.com/discovery/v1/apis/drive/v3/rest';

    // Initialize the gapi.client object, which app uses to make API requests.
    // Get API key and client ID from API Console.
    // 'scope' field specifies space-delimited list of access scopes.
    gapi.client.init({
        'apiKey': 'YOUR_API_KEY',
        'clientId': 'YOUR_CLIENT_ID',
        'discoveryDocs': [discoveryUrl],
        'scope': SCOPE
    }).then(function () {
      GoogleAuth = gapi.auth2.getAuthInstance();

      // Listen for sign-in state changes.
      GoogleAuth.isSignedIn.listen(updateSigninStatus);

      // Handle initial sign-in state. (Determine if user is already signed in.)
      var user = GoogleAuth.currentUser.get();
      setSigninStatus();

      // Call handleAuthClick function when user clicks on
      //      "Sign In/Authorize" button.
      $('#sign-in-or-out-button').click(function() {
        handleAuthClick();
      });
      $('#revoke-access-button').click(function() {
        revokeAccess();
      });
    });
  }

  function handleAuthClick() {
    if (GoogleAuth.isSignedIn.get()) {
      // User is authorized and has clicked "Sign out" button.
      GoogleAuth.signOut();
    } else {
      // User is not signed in. Start Google auth flow.
      GoogleAuth.signIn();
    }
  }

  function revokeAccess() {
    GoogleAuth.disconnect();
  }

  function setSigninStatus() {
    var user = GoogleAuth.currentUser.get();
    var isAuthorized = user.hasGrantedScopes(SCOPE);
    if (isAuthorized) {
      $('#sign-in-or-out-button').html('Sign out');
      $('#revoke-access-button').css('display', 'inline-block');
      $('#auth-status').html('You are currently signed in and have granted ' +
          'access to this app.');
    } else {
      $('#sign-in-or-out-button').html('Sign In/Authorize');
      $('#revoke-access-button').css('display', 'none');
      $('#auth-status').html('You have not authorized this app or you are ' +
          'signed out.');
    }
  }

  function updateSigninStatus() {
    setSigninStatus();
  }
</script>

<button id="sign-in-or-out-button"
        style="margin-left: 25px">Sign In/Authorize</button>
<button id="revoke-access-button"
        style="display: none; margin-left: 25px">Revoke access</button>

<div id="auth-status" style="display: inline; padding-left: 25px"></div><hr>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script async defer src="https://apis.google.com/js/api.js"
        onload="this.onload=function(){};handleClientLoad()"
        onreadystatechange="if (this.readyState === 'complete') this.onload()">
</script>
</body></html>

Points de terminaison OAuth 2.0

OAuth 2.0 pour les applications Web côté client s'exécutant dans un navigateur via une redirection vers Google pour obtenir le consentement de l'utilisateur

Cet exemple présente des appels directs aux points de terminaison OAuth 2.0 de Google à partir du navigateur de l'utilisateur. Il n'utilise ni le module gapi.auth2, ni une bibliothèque JavaScript.

<!DOCTYPE html>
<html><head></head><body>
<script>
  var YOUR_CLIENT_ID = 'REPLACE_THIS_VALUE';
  var YOUR_REDIRECT_URI = 'REPLACE_THIS_VALUE';
  var fragmentString = location.hash.substring(1);

  // Parse query string to see if page request is coming from OAuth 2.0 server.
  var params = {};
  var regex = /([^&=]+)=([^&]*)/g, m;
  while (m = regex.exec(fragmentString)) {
    params[decodeURIComponent(m[1])] = decodeURIComponent(m[2]);
  }
  if (Object.keys(params).length > 0) {
    localStorage.setItem('oauth2-test-params', JSON.stringify(params) );
    if (params['state'] && params['state'] == 'try_sample_request') {
      trySampleRequest();
    }
  }

  // If there's an access token, try an API request.
  // Otherwise, start OAuth 2.0 flow.
  function trySampleRequest() {
    var params = JSON.parse(localStorage.getItem('oauth2-test-params'));
    if (params && params['access_token']) {
      var xhr = new XMLHttpRequest();
      xhr.open('GET',
          'https://www.googleapis.com/drive/v3/about?fields=user&' +
          'access_token=' + params['access_token']);
      xhr.onreadystatechange = function (e) {
        if (xhr.readyState === 4 && xhr.status === 200) {
          console.log(xhr.response);
        } else if (xhr.readyState === 4 && xhr.status === 401) {
          // Token invalid, so prompt for user permission.
          oauth2SignIn();
        }
      };
      xhr.send(null);
    } else {
      oauth2SignIn();
    }
  }

  /*

    *   Create form to request access token from Google's OAuth 2.0 server.
 */
function oauth2SignIn() {
  // Google's OAuth 2.0 endpoint for requesting an access token
  var oauth2Endpoint = 'https://accounts.google.com/o/oauth2/v2/auth';

    // Create element to open OAuth 2.0 endpoint in new window.
    var form = document.createElement('form');
    form.setAttribute('method', 'GET'); // Send as a GET request.
    form.setAttribute('action', oauth2Endpoint);

    // Parameters to pass to OAuth 2.0 endpoint.
    var params = {'client_id': YOUR_CLIENT_ID,
                  'redirect_uri': YOUR_REDIRECT_URI,
                  'scope': 'https://www.googleapis.com/auth/drive.metadata.readonly',
                  'state': 'try_sample_request',
                  'include_granted_scopes': 'true',
                  'response_type': 'token'};

    // Add form parameters as hidden input values.
    for (var p in params) {
      var input = document.createElement('input');
      input.setAttribute('type', 'hidden');
      input.setAttribute('name', p);
      input.setAttribute('value', params[p]);
      form.appendChild(input);
    }

    // Add form to page and submit it to open the OAuth 2.0 endpoint.
    document.body.appendChild(form);
    form.submit();
  }
</script>

<button onclick="trySampleRequest();">Try sample request</button>
</body></html>

Nouvelle méthode

SIG uniquement

Cet exemple ne montre que la bibliothèque JavaScript de Google Identity Service utilisant le modèle de jeton et la boîte de dialogue pop-up pour le consentement de l'utilisateur. Il est fourni pour illustrer le nombre minimal d'étapes requises pour configurer un client, demander et obtenir un jeton d'accès, et appeler une API Google.

<!DOCTYPE html>
<html>
  <head>
    <script src="https://accounts.google.com/gsi/client" onload="initClient()" async defer></script>
  </head>
  <body>
    <script>
      var client;
      var access_token;

      function initClient() {
        client = google.accounts.oauth2.initTokenClient({
          client_id: 'YOUR_CLIENT_ID',
          scope: 'https://www.googleapis.com/auth/calendar.readonly \
                  https://www.googleapis.com/auth/contacts.readonly',
          callback: (tokenResponse) => {
            access_token = tokenResponse.access_token;
          },
        });
      }
      function getToken() {
        client.requestAccessToken();
      }
      function revokeToken() {
        google.accounts.oauth2.revoke(access_token, () => {console.log('access token revoked')});
      }
      function loadCalendar() {
        var xhr = new XMLHttpRequest();
        xhr.open('GET', 'https://www.googleapis.com/calendar/v3/calendars/primary/events');
        xhr.setRequestHeader('Authorization', 'Bearer ' + access_token);
        xhr.send();
      }
    </script>
    <h1>Google Identity Services Authorization Token model</h1>
    <button onclick="getToken();">Get access token</button><br><br>
    <button onclick="loadCalendar();">Load Calendar</button><br><br>
    <button onclick="revokeToken();">Revoke token</button>
  </body>
</html>

GAPI async/await

Cet exemple montre comment ajouter la bibliothèque Google Identity Service à l'aide du modèle de jeton, supprimer le module gapi.auth2 et appeler une API à l'aide de la bibliothèque cliente des API Google pour JavaScript.

Les promesses, les méthodes async et await sont utilisées pour appliquer l'ordre de chargement de la bibliothèque, ainsi que pour détecter et relancer les erreurs d'autorisation. Un appel d'API n'est effectué qu'une fois qu'un jeton d'accès valide est disponible.

Les utilisateurs doivent appuyer sur le bouton "Afficher le calendrier" lorsque le jeton d'accès est manquant lors du premier chargement de la page, ou plus tard après l'expiration du jeton d'accès.

<!DOCTYPE html>
<html>
<head></head>
<body>
  <h1>GAPI with GIS async/await</h1>
  <button id="showEventsBtn" onclick="showEvents();">Show Calendar</button><br><br>
  <button id="revokeBtn" onclick="revokeToken();">Revoke access token</button>

  <script>

    const gapiLoadPromise = new Promise((resolve, reject) => {
      gapiLoadOkay = resolve;
      gapiLoadFail = reject;
    });
    const gisLoadPromise = new Promise((resolve, reject) => {
      gisLoadOkay = resolve;
      gisLoadFail = reject;
    });

    var tokenClient;

    (async () => {
      document.getElementById("showEventsBtn").style.visibility="hidden";
      document.getElementById("revokeBtn").style.visibility="hidden";

      // First, load and initialize the gapi.client
      await gapiLoadPromise;
      await new Promise((resolve, reject) => {
        // NOTE: the 'auth2' module is no longer loaded.
        gapi.load('client', {callback: resolve, onerror: reject});
      });
      await gapi.client.init({
        // NOTE: OAuth2 'scope' and 'client_id' parameters have moved to initTokenClient().
      })
      .then(function() {  // Load the Calendar API discovery document.
        gapi.client.load('https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest');
      });

      // Now load the GIS client
      await gisLoadPromise;
      await new Promise((resolve, reject) => {
        try {
          tokenClient = google.accounts.oauth2.initTokenClient({
              client_id: 'YOUR_CLIENT_ID',
              scope: 'https://www.googleapis.com/auth/calendar.readonly',
              prompt: 'consent',
              callback: '',  // defined at request time in await/promise scope.
          });
          resolve();
        } catch (err) {
          reject(err);
        }
      });

      document.getElementById("showEventsBtn").style.visibility="visible";
      document.getElementById("revokeBtn").style.visibility="visible";
    })();

    async function getToken(err) {

      if (err.result.error.code == 401 || (err.result.error.code == 403) &&
          (err.result.error.status == "PERMISSION_DENIED")) {

        // The access token is missing, invalid, or expired, prompt for user consent to obtain one.
        await new Promise((resolve, reject) => {
          try {
            // Settle this promise in the response callback for requestAccessToken()
            tokenClient.callback = (resp) => {
              if (resp.error !== undefined) {
                reject(resp);
              }
              // GIS has automatically updated gapi.client with the newly issued access token.
              console.log('gapi.client access token: ' + JSON.stringify(gapi.client.getToken()));
              resolve(resp);
            };
            tokenClient.requestAccessToken();
          } catch (err) {
            console.log(err)
          }
        });
      } else {
        // Errors unrelated to authorization: server errors, exceeding quota, bad requests, and so on.
        throw new Error(err);
      }
    }

    function showEvents() {

      // Try to fetch a list of Calendar events. If a valid access token is needed,
      // prompt to obtain one and then retry the original request.
      gapi.client.calendar.events.list({ 'calendarId': 'primary' })
      .then(calendarAPIResponse => console.log(JSON.stringify(calendarAPIResponse)))
      .catch(err  => getToken(err))  // for authorization errors obtain an access token
      .then(retry => gapi.client.calendar.events.list({ 'calendarId': 'primary' }))
      .then(calendarAPIResponse => console.log(JSON.stringify(calendarAPIResponse)))
      .catch(err  => console.log(err)); // cancelled by user, timeout, etc.
    }

    function revokeToken() {
      let cred = gapi.client.getToken();
      if (cred !== null) {
        google.accounts.oauth2.revoke(cred.access_token, () => {console.log('Revoked: ' + cred.access_token)});
        gapi.client.setToken('');
      }
    }

  </script>

  <script async defer src="https://apis.google.com/js/api.js" onload="gapiLoadOkay()" onerror="gapiLoadFail(event)"></script>
  <script async defer src="https://accounts.google.com/gsi/client" onload="gisLoadOkay()" onerror="gisLoadFail(event)"></script>

</body>
</html>

Rappel GAPI

Cet exemple montre comment ajouter la bibliothèque Google Identity Service à l'aide du modèle de jeton, supprimer le module gapi.auth2 et appeler une API à l'aide de la bibliothèque cliente des API Google pour JavaScript.

Les variables permettent d'appliquer l'ordre de chargement de la bibliothèque. Les appels GAPI sont effectués à partir du rappel après le renvoi d'un jeton d'accès valide.

Les utilisateurs doivent appuyer sur le bouton "Afficher l'agenda" lors du premier chargement de la page, puis de nouveau lorsqu'ils souhaitent actualiser les informations de leur agenda.

<!DOCTYPE html>
<html>
<head>
  <script async defer src="https://apis.google.com/js/api.js" onload="gapiLoad()"></script>
  <script async defer src="https://accounts.google.com/gsi/client" onload="gisInit()"></script>
</head>
<body>
  <h1>GAPI with GIS callbacks</h1>
  <button id="showEventsBtn" onclick="showEvents();">Show Calendar</button><br><br>
  <button id="revokeBtn" onclick="revokeToken();">Revoke access token</button>
  <script>
    let tokenClient;
    let gapiInited;
    let gisInited;

    document.getElementById("showEventsBtn").style.visibility="hidden";
    document.getElementById("revokeBtn").style.visibility="hidden";

    function checkBeforeStart() {
       if (gapiInited && gisInited){
          // Start only when both gapi and gis are initialized.
          document.getElementById("showEventsBtn").style.visibility="visible";
          document.getElementById("revokeBtn").style.visibility="visible";
       }
    }

    function gapiInit() {
      gapi.client.init({
        // NOTE: OAuth2 'scope' and 'client_id' parameters have moved to initTokenClient().
      })
      .then(function() {  // Load the Calendar API discovery document.
        gapi.client.load('https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest');
        gapiInited = true;
        checkBeforeStart();
      });
    }

    function gapiLoad() {
        gapi.load('client', gapiInit)
    }

    function gisInit() {
     tokenClient = google.accounts.oauth2.initTokenClient({
                client_id: 'YOUR_CLIENT_ID',
                scope: 'https://www.googleapis.com/auth/calendar.readonly',
                callback: '',  // defined at request time
            });
      gisInited = true;
      checkBeforeStart();
    }

    function showEvents() {

      tokenClient.callback = (resp) => {
        if (resp.error !== undefined) {
          throw(resp);
        }
        // GIS has automatically updated gapi.client with the newly issued access token.
        console.log('gapi.client access token: ' + JSON.stringify(gapi.client.getToken()));

        gapi.client.calendar.events.list({ 'calendarId': 'primary' })
        .then(calendarAPIResponse => console.log(JSON.stringify(calendarAPIResponse)))
        .catch(err => console.log(err));

        document.getElementById("showEventsBtn").innerText = "Refresh Calendar";
      }

      // Conditionally ask users to select the Google Account they'd like to use,
      // and explicitly obtain their consent to fetch their Calendar.
      // NOTE: To request an access token a user gesture is necessary.
      if (gapi.client.getToken() === null) {
        // Prompt the user to select a Google Account and asked for consent to share their data
        // when establishing a new session.
        tokenClient.requestAccessToken({prompt: 'consent'});
      } else {
        // Skip display of account chooser and consent dialog for an existing session.
        tokenClient.requestAccessToken({prompt: ''});
      }
    }

    function revokeToken() {
      let cred = gapi.client.getToken();
      if (cred !== null) {
        google.accounts.oauth2.revoke(cred.access_token, () => {console.log('Revoked: ' + cred.access_token)});
        gapi.client.setToken('');
        document.getElementById("showEventsBtn").innerText = "Show Calendar";
      }
    }
  </script>
</body>
</html>

Exemples de flux de code d'autorisation

L'expérience utilisateur pop-up de la bibliothèque Google Identity Service peut soit utiliser une redirection d'URL pour renvoyer un code d'autorisation directement au point de terminaison de votre jeton de backend, soit utiliser un gestionnaire de rappel JavaScript exécuté dans le navigateur de l'utilisateur qui transmet la réponse à votre plate-forme en tant que proxy. Dans les deux cas, votre plate-forme backend termine le flux OAuth 2.0 pour obtenir un jeton d'actualisation et d'accès valide.

Ancienne méthode

Applications Web côté serveur

Google Sign-In pour les applications côté serveur s'exécutant sur une plate-forme backend via une redirection vers Google pour le consentement de l'utilisateur.

<!DOCTYPE html>
<html>
  <head>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
    <script src="https://apis.google.com/js/client:platform.js?onload=start" async defer></script>
    <script>
      function start() {
        gapi.load('auth2', function() {
          auth2 = gapi.auth2.init({
            client_id: 'YOUR_CLIENT_ID',
            api_key: 'YOUR_API_KEY',
            discovery_docs: ['https://www.googleapis.com/discovery/v1/apis/translate/v2/rest'],
            // Scopes to request in addition to 'profile' and 'email'
            scope: 'https://www.googleapis.com/auth/cloud-translation',
          });
        });
      }
      function signInCallback(authResult) {
        if (authResult['code']) {
          console.log("sending AJAX request");
          // Send authorization code obtained from Google to backend platform
          $.ajax({
            type: 'POST',
            url: 'YOUR_AUTHORIZATION_CODE_ENDPOINT_URL',
            // Always include an X-Requested-With header to protect against CSRF attacks.
            headers: {
              'X-Requested-With': 'XMLHttpRequest'
            },
            contentType: 'application/octet-stream; charset=utf-8',
            success: function(result) {
              console.log(result);
            },
            processData: false,
            data: authResult['code']
          });
        } else {
          console.log('error: failed to obtain authorization code')
        }
      }
    </script>
  </head>
  <body>
    <button id="signinButton">Sign In With Google</button>
    <script>
      $('#signinButton').click(function() {
        // Obtain an authorization code from Google
        auth2.grantOfflineAccess().then(signInCallback);
      });
    </script>
  </body>
</html>

HTTP/REST avec redirection

Utiliser OAuth 2.0 pour les applications de serveur Web pour envoyer le code d'autorisation du navigateur de l'utilisateur à votre plate-forme backend. Consentement de l'utilisateur géré en redirigeant le navigateur de l'utilisateur vers Google.

/\*
 \* Create form to request access token from Google's OAuth 2.0 server.
 \*/
function oauthSignIn() {
  // Google's OAuth 2.0 endpoint for requesting an access token
  var oauth2Endpoint = 'https://accounts.google.com/o/oauth2/v2/auth';
  // Create &lt;form> element to submit parameters to OAuth 2.0 endpoint.
  var form = document.createElement('form');
  form.setAttribute('method', 'GET'); // Send as a GET request.
  form.setAttribute('action', oauth2Endpoint);
  // Parameters to pass to OAuth 2.0 endpoint.
  var params = {'client\_id': 'YOUR_CLIENT_ID',
                'redirect\_uri': 'YOUR_AUTHORIZATION_CODE_ENDPOINT_URL',
                'response\_type': 'token',
                'scope': 'https://www.googleapis.com/auth/drive.metadata.readonly',
                'include\_granted\_scopes': 'true',
                'state': 'pass-through value'};
  // Add form parameters as hidden input values.
  for (var p in params) {
    var input = document.createElement('input');
    input.setAttribute('type', 'hidden');
    input.setAttribute('name', p);
    input.setAttribute('value', params[p]);
    form.appendChild(input);
  }

  // Add form to page and submit it to open the OAuth 2.0 endpoint.
  document.body.appendChild(form);
  form.submit();
}

Nouvelle méthode

Expérience utilisateur du pop-up SIG

Cet exemple montre uniquement la bibliothèque JavaScript Google Identity Service utilisant le modèle de code d'autorisation. Une boîte de dialogue pop-up s'affiche pour permettre au gestionnaire de consentement et de rappel de recevoir le code d'autorisation de Google. Il est fourni pour illustrer le nombre minimal d'étapes requises pour configurer un client, obtenir le consentement des utilisateurs et envoyer un code d'autorisation à votre plate-forme backend.

<!DOCTYPE html>
<html>
  <head>
    <script src="https://accounts.google.com/gsi/client" onload="initClient()" async defer></script>
  </head>
  <body>
    <script>
      var client;
      function initClient() {
        client = google.accounts.oauth2.initCodeClient({
          client_id: 'YOUR_CLIENT_ID',
          scope: 'https://www.googleapis.com/auth/calendar.readonly',
          ux_mode: 'popup',
          callback: (response) => {
            var code_receiver_uri = 'YOUR_AUTHORIZATION_CODE_ENDPOINT_URI',
            // Send auth code to your backend platform
            const xhr = new XMLHttpRequest();
            xhr.open('POST', code_receiver_uri, true);
            xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
            xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
            xhr.onload = function() {
              console.log('Signed in as: ' + xhr.responseText);
            };
            xhr.send('code=' + response.code);
            // After receipt, the code is exchanged for an access token and
            // refresh token, and the platform then updates this web app
            // running in user's browser with the requested calendar info.
          },
        });
      }
      function getAuthCode() {
        // Request authorization code and obtain user consent
        client.requestCode();
      }
    </script>
    <button onclick="getAuthCode();">Load Your Calendar</button>
  </body>
</html>

Expérience utilisateur de redirection SIG

Le modèle de code d'autorisation accepte les modes pop-up et de redirection pour envoyer un code d'autorisation par utilisateur au point de terminaison hébergé par votre plate-forme. Le mode de redirection de l'expérience utilisateur est illustré ici:

<!DOCTYPE html>
<html>
  <head>
    <script src="https://accounts.google.com/gsi/client" onload="initClient()" async defer></script>
  </head>
  <body>
    <script>
      var client;
      function initClient() {
        client = google.accounts.oauth2.initCodeClient({
          client_id: 'YOUR_CLIENT_ID',
          scope: 'https://www.googleapis.com/auth/calendar.readonly \
                  https://www.googleapis.com/auth/photoslibrary.readonly',
          ux_mode: 'redirect',
          redirect_uri: 'YOUR_AUTHORIZATION_CODE_ENDPOINT_URI'
        });
      }
      // Request an access token
      function getAuthCode() {
        // Request authorization code and obtain user consent
        client.requestCode();
      }
    </script>
    <button onclick="getAuthCode();">Load Your Calendar</button>
  </body>
</html>

Bibliothèques JavaScript

Google Identity Services est une bibliothèque JavaScript unique utilisée pour l'authentification et l'autorisation des utilisateurs. Elle regroupe et remplace les fonctionnalités disponibles dans plusieurs bibliothèques et modules:

Actions à effectuer lors de la migration vers Identity Services:

Bibliothèque JS existante Nouvelle bibliothèque JS Remarques
apis.google.com/js/api.js accounts.google.com/gsi/client Ajoutez une bibliothèque et suivez le flux implicite.
apis.google.com/js/client.js accounts.google.com/gsi/client Ajoutez une bibliothèque et le flux de code d'autorisation.

Guide de référence rapide de la bibliothèque

Comparaison des objets et des méthodes entre l'ancienne bibliothèque cliente JavaScript Google Sign-In et la nouvelle bibliothèque Google Identity Services, ainsi que des notes, avec des informations supplémentaires et les mesures à prendre lors de la migration.

Ancienne version Nouvelle version Remarques
Objet GoogleAuth et méthodes associées:
GoogleAuth.attachClickHandler() Supprimer
GoogleAuth.currentUser.get() Supprimer
GoogleAuth.currentUser.listen() Supprimer
GoogleAuth.disconnect() google.accounts.oauth2.revoke Remplacez l'ancien par le neuf. La révocation peut aussi se produire sur https://myaccount.google.com/permissions
GoogleAuth.grantOfflineAccess() Supprimez-le, puis suivez le flux avec code d'autorisation.
GoogleAuth.isSignedIn.get() Supprimer
GoogleAuth.isSignedIn.listen() Supprimer
GoogleAuth.signIn() Supprimer
GoogleAuth.signOut() Supprimer
GoogleAuth.then() Supprimer
Objet GoogleUser et méthodes associées:
GoogleUser.disconnect() google.accounts.id.revoke Remplacez l'ancien par le neuf. La révocation peut aussi se produire sur https://myaccount.google.com/permissions
GoogleUser.getAuthResponse() requestCode() or requestAccessToken() Remplacer l'ancien par le neuf
GoogleUser.getBasicProfile() Supprimer. Utilisez plutôt un jeton d'ID. Consultez Migrer depuis Google Sign-In.
GoogleUser.getGrantedScopes() hasGrantedAnyScope() Remplacer l'ancien par le neuf
GoogleUser.getHostedDomain() Supprimer
GoogleUser.getId() Supprimer
GoogleUser.grantOfflineAccess() Supprimez-le, puis suivez le flux avec code d'autorisation.
GoogleUser.grant() Supprimer
GoogleUser.hasGrantedScopes() hasGrantedAnyScope() Remplacer l'ancien par le neuf
GoogleUser.isSignedIn() Supprimer
GoogleUser.reloadAuthResponse() requestAccessToken() Supprimez l'ancien, appelez le nouveau pour remplacer le jeton d'accès arrivé à expiration ou révoqué.
Objet gapi.auth2 et méthodes associées:
Objet gapi.auth2.AuthorizeConfig TokenClientConfig ou CodeClientConfig Remplacer l'ancien par le neuf
Objet gapi.auth2.AuthorizeResponse Supprimer
Objet gapi.auth2.AuthResponse Supprimer
gapi.auth2.authorize() requestCode() or requestAccessToken() Remplacer l'ancien par le neuf
gapi.auth2.ClientConfig() TokenClientConfig ou CodeClientConfig Remplacer l'ancien par le neuf
gapi.auth2.getAuthInstance() Supprimer
gapi.auth2.init() initTokenClient() or initCodeClient() Remplacer l'ancien par le neuf
Objet gapi.auth2.offlineAccessOptions Supprimer
Objet gapi.auth2.SignInOptions Supprimer
Objet gapi.signin2 et les méthodes associées:
gapi.signin2.render() Supprimer. Le chargement HTML du DOM de l'élément g_id_signin ou de l'appel JS à google.accounts.id.renderButton déclenche la connexion de l'utilisateur à un compte Google.

Exemples d'identifiants

Identifiants existants

La bibliothèque de la plate-forme Google Sign-In, la bibliothèque cliente des API Google pour JavaScript ou les appels directs aux points de terminaison Google Auth 2.0 renvoient un jeton d'accès OAuth 2.0 et un jeton d'ID OpenID Connect dans une seule réponse.

Exemple de réponse contenant à la fois access_token et id_token:

  {
    "token_type": "Bearer",
    "access_token": "ya29.A0ARrdaM-SmArZaCIh68qXsZSzyeU-8mxhQERHrP2EXtxpUuZ-3oW8IW7a6D2J6lRnZrRj8S6-ZcIl5XVEqnqxq5fuMeDDH_6MZgQ5dgP7moY-yTiKR5kdPm-LkuPM-mOtUsylWPd1wpRmvw_AGOZ1UUCa6UD5Hg",
    "scope": "https://www.googleapis.com/auth/calendar.readonly",
    "login_hint": "AJDLj6I2d1RH77cgpe__DdEree1zxHjZJr4Q7yOisoumTZUmo5W2ZmVFHyAomUYzLkrluG-hqt4RnNxrPhArd5y6p8kzO0t8xIfMAe6yhztt6v2E-_Bb4Ec3GLFKikHSXNh5bI-gPrsI",
    "expires_in": 3599,
    "id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjkzNDFhYmM0MDkyYjZmYzAzOGU0MDNjOTEwMjJkZDNlNDQ1MzliNTYiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJhY2NvdW50cy5nb29nbGUuY29tIiwiYXpwIjoiNTM4MzQ0NjUzMjU1LTc1OGM1aDVpc2M0NXZnazI3ZDhoOGRlYWJvdnBnNnRvLmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tIiwiYXVkIjoiNTM4MzQ0NjUzMjU1LTc1OGM1aDVpc2M0NXZnazI3ZDhoOGRlYWJvdnBnNnRvLmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tIiwic3ViIjoiMTE3NzI2NDMxNjUxOTQzNjk4NjAwIiwiaGQiOiJnb29nbGUuY29tIiwiZW1haWwiOiJkYWJyaWFuQGdvb2dsZS5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiYXRfaGFzaCI6IkJBSW55TjN2MS1ZejNLQnJUMVo0ckEiLCJuYW1lIjoiQnJpYW4gRGF1Z2hlcnR5IiwicGljdHVyZSI6Imh0dHBzOi8vbGgzLmdvb2dsZXVzZXJjb250ZW50LmNvbS9hLS9BT2gxNEdnenAyTXNGRGZvbVdMX3VDemRYUWNzeVM3ZGtxTE5ybk90S0QzVXNRPXM5Ni1jIiwiZ2l2ZW5fbmFtZSI6IkJyaWFuIiwiZmFtaWx5X25hbWUiOiJEYXVnaGVydHkiLCJsb2NhbGUiOiJlbiIsImlhdCI6MTYzODk5MTYzOCwiZXhwIjoxNjM4OTk1MjM4LCJqdGkiOiI5YmRkZjE1YWFiNzE2ZDhjYmJmNDYwMmM1YWM3YzViN2VhMDQ5OTA5In0.K3EA-3Adw5HA7O8nJVCsX1HmGWxWzYk3P7ViVBb4H4BoT2-HIgxKlx1mi6jSxIUJGEekjw9MC-nL1B9Asgv1vXTMgoGaNna0UoEHYitySI23E5jaMkExkTSLtxI-ih2tJrA2ggfA9Ekj-JFiMc6MuJnwcfBTlsYWRcZOYVw3QpdTZ_VYfhUu-yERAElZCjaAyEXLtVQegRe-ymScra3r9S92TA33ylMb3WDTlfmDpWL0CDdDzby2asXYpl6GQ7SdSj64s49Yw6mdGELZn5WoJqG7Zr2KwIGXJuSxEo-wGbzxNK-mKAiABcFpYP4KHPEUgYyz3n9Vqn2Tfrgp-g65BQ",
    "session_state": {
      "extraQueryParams": {
        "authuser": "0"
      }
    },
    "first_issued_at": 1638991637982,
    "expires_at": 1638995236982,
    "idpId": "google"
  }

Identifiants Google Identity Services

La bibliothèque Google Identity Services renvoie les éléments suivants:

  • un jeton d'accès en cas d'utilisation pour l'autorisation:

    {
      "access_token": "ya29.A0ARrdaM_LWSO-uckLj7IJVNSfnUityT0Xj-UCCrGxFQdxmLiWuAosnAKMVQ2Z0LLqeZdeJii3TgULp6hR_PJxnInBOl8UoUwWoqsrGQ7-swxgy97E8_hnzfhrOWyQBmH6zs0_sUCzwzhEr_FAVqf92sZZHphr0g",
      "token_type": "Bearer",
      "expires_in": 3599,
      "scope": "https://www.googleapis.com/auth/calendar.readonly"
    }
    
  • ou un jeton d'identification pour l'authentification:

    {
      "clientId": "538344653255-758c5h5isc45vgk27d8h8deabovpg6to.apps.googleusercontent.com",
      "credential": "eyJhbGciOiJSUzI1NiIsImtpZCI6ImMxODkyZWI0OWQ3ZWY5YWRmOGIyZTE0YzA1Y2EwZDAzMjcxNGEyMzciLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJuYmYiOjE2MzkxNTcyNjQsImF1ZCI6IjUzODM0NDY1MzI1NS03NThjNWg1aXNjNDV2Z2syN2Q4aDhkZWFib3ZwZzZ0by5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbSIsInN1YiI6IjExNzcyNjQzMTY1MTk0MzY5ODYwMCIsIm5vbmNlIjoiZm9vYmFyIiwiaGQiOiJnb29nbGUuY29tIiwiZW1haWwiOiJkYWJyaWFuQGdvb2dsZS5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiYXpwIjoiNTM4MzQ0NjUzMjU1LTc1OGM1aDVpc2M0NXZnazI3ZDhoOGRlYWJvdnBnNnRvLmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tIiwibmFtZSI6IkJyaWFuIERhdWdoZXJ0eSIsInBpY3R1cmUiOiJodHRwczovL2xoMy5nb29nbGV1c2VyY29udGVudC5jb20vYS0vQU9oMTRHZ3pwMk1zRkRmb21XTF91Q3pkWFFjc3lTN2RrcUxOcm5PdEtEM1VzUT1zOTYtYyIsImdpdmVuX25hbWUiOiJCcmlhbiIsImZhbWlseV9uYW1lIjoiRGF1Z2hlcnR5IiwiaWF0IjoxNjM5MTU3NTY0LCJleHAiOjE2MzkxNjExNjQsImp0aSI6IjRiOTVkYjAyZjU4NDczMmUxZGJkOTY2NWJiMWYzY2VhYzgyMmI0NjUifQ.Cr-AgMsLFeLurnqyGpw0hSomjOCU4S3cU669Hyi4VsbqnAV11zc_z73o6ahe9Nqc26kPVCNRGSqYrDZPfRyTnV6g1PIgc4Zvl-JBuy6O9HhClAK1HhMwh1FpgeYwXqrng1tifmuotuLQnZAiQJM73Gl-J_6s86Buo_1AIx5YAKCucYDUYYdXBIHLxrbALsA5W6pZCqqkMbqpTWteix-G5Q5T8LNsfqIu_uMBUGceqZWFJALhS9ieaDqoxhIqpx_89QAr1YlGu_UO6R6FYl0wDT-nzjyeF5tonSs3FHN0iNIiR3AMOHZu7KUwZaUdHg4eYkU-sQ01QNY_11keHROCRQ",
      "select_by": "user"
    }
    

Réponse de jeton non valide

Exemple de réponse de Google lors d'une tentative d'envoi d'une requête API à l'aide d'un jeton d'accès expiré, révoqué ou non valide:

En-têtes de réponse HTTP

  www-authenticate: Bearer realm="https://accounts.google.com/", error="invalid_token"

Corps de la réponse

  {
    "error": {
      "code": 401,
      "message": "Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.",
      "errors": [
        {
          "message": "Invalid Credentials",
          "domain": "global",
          "reason": "authError",
          "location": "Authorization",
          "locationType": "header"
        }
      ],
      "status": "UNAUTHENTICATED"
    }
  }