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.
En suivant ce guide, vous allez :
- remplacer la bibliothèque de plate-forme obsolète par la bibliothèque Identity Services ;
- Si vous utilisez la bibliothèque cliente des API, supprimez le module
gapi.auth2
obsolète, ainsi que ses méthodes et objets, et remplacez-les par les équivalents des services d'identité.
Pour obtenir une description des modifications apportées à la bibliothèque JavaScript des services d'identité, consultez la présentation et le fonctionnement de l'autorisation des utilisateurs pour passer en revue les principaux termes et concepts.
Si vous recherchez une 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 possibles : le flux implicite et le flux avec code d'autorisation.
Examinez votre application Web pour identifier le type de flux d'autorisation utilisé.
Voici quelques indications que votre application Web utilise le flux implicite :
- Votre application Web est purement basée sur le navigateur, sans plate-forme de 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 se charge
apis.google.com/js/api.js
. - Votre implémentation est basée sur OAuth 2.0 pour les applications Web côté client.
- Votre application utilise les modules
gapi.client
ougapi.auth2
de la bibliothèque cliente des API Google pour JavaScript.
Voici quelques indications que votre application Web utilise le flux avec code d'autorisation :
Votre implémentation est basée sur :
Votre application s'exécute à la fois dans le navigateur de l'utilisateur et sur votre plate-forme backend.
Votre plate-forme de backend héberge un point de terminaison de code d'autorisation.
Votre plate-forme de backend appelle les API Google au nom des utilisateurs sans qu'ils aient besoin d'être présents (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 prendre en charge les deux flux.
Choisir un flux d'autorisation
Avant de commencer votre migration, vous devez déterminer si vous devez continuer avec votre flux existant ou en adopter un autre.
Consultez 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é pour les utilisateurs. L'implémentation de ce flux permet également à votre plate-forme d'ajouter de nouvelles fonctionnalités hors connexion, telles que la récupération des mises à jour pour informer les utilisateurs des modifications importantes apportées à leur agenda, à leurs photos et à leurs abonnements.
Choisissez un flux d'autorisation à l'aide des sélecteurs.
Flux implicite
Obtenez un jeton d'accès pour une utilisation dans le navigateur lorsque l'utilisateur est présent.
La section Exemples de flux implicites montre des applications Web avant et après la migration vers les services d'identité.
Flux de code d'autorisation
Un code d'autorisation par utilisateur émis par Google est envoyé à votre plate-forme de backend, où il est ensuite échangé contre un jeton d'accès et un jeton d'actualisation.
La section Exemples de flux de code d'autorisation montre des applications Web avant et après la migration vers les services d'identité.
Tout au long de ce guide, suivez les instructions en gras pour ajouter, supprimer, mettre à jour ou remplacer des fonctionnalités existantes.
Modifications apportées à votre application Web dans le navigateur
Cette section passe en revue les modifications que vous apporterez à votre application Web dans le navigateur lors de la migration vers la bibliothèque JavaScript Google Identity Services.
Identifier le code et le test concernés
Un cookie de débogage peut vous aider à localiser le code concerné 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 deux-points suivi d'une valeur clé pour consigner les données dans le 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 du cookie G_AUTH2_MIGRATION
:
- Ne chargez pas le module
gapi.auth2
deenforced
. informational
Consignez l'utilisation des fonctionnalités obsolètes dans la console JS. Enregistrez également dans 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 d'abord ce cookie localement pendant le développement et le test, avant de l'utiliser dans les environnements de production.
Bibliothèques et modules
Le module gapi.auth2
gère l'authentification des utilisateurs pour la connexion et le flux implicite pour l'autorisation. Remplacez 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 le module gapi.client
de la bibliothèque cliente d'API Google pour JavaScript en toute sécurité. Vous bénéficierez ainsi de la création automatique de méthodes JS appelables à partir d'un document de découverte, du regroupement de plusieurs appels d'API et de la fonctionnalité de gestion CORS.
Cookies
L'autorisation de l'utilisateur ne nécessite pas l'utilisation de cookies.
Consultez Migrer depuis Google Sign-In pour en savoir plus sur l'utilisation des cookies pour l'authentification des utilisateurs, et Comment Google utilise les cookies pour en savoir plus sur l'utilisation des cookies par d'autres produits et services Google.
Identifiants
Les services d'identité Google séparent l'authentification et l'autorisation des utilisateurs en deux opérations distinctes, et les identifiants des utilisateurs sont distincts : le jeton d'identité utilisé pour identifier un utilisateur est renvoyé séparément du jeton d'accès utilisé pour l'autorisation.
Pour afficher ces modifications, consultez les 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 les références au client JavaScript Google Sign-In suivantes :
Méthodes
GoogleUser.getBasicProfile()
GoogleUser.getId()
Flux de code d'autorisation
Les services d'identité séparent les identifiants dans le navigateur en jeton d'identité et jeton d'accès. Cette modification ne s'applique pas aux identifiants obtenus par le biais d'appels directs aux points de terminaison Google OAuth 2.0 depuis votre plate-forme de backend, ni par le biais de bibliothèques s'exécutant sur un serveur sécurisé de votre plate-forme, comme la bibliothèque cliente Node.js des API Google.
État de la session
Auparavant, la connexion avec Google vous aidait à gérer l'état de connexion des utilisateurs à l'aide des éléments suivants :
- Gestionnaires de rappel pour surveiller l'état de la session de l'utilisateur.
- Listeners pour les événements et les modifications de l'état de connexion d'un compte Google.
Vous êtes responsable de la gestion de l'état de connexion et des sessions utilisateur de votre application Web.
Supprimez les références au client JavaScript Google Sign-In suivantes :
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 d'autorisation ou implicite.
Supprimez les références au client JavaScript Google Sign-In suivantes :
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 jetons.
Remplacez les références du client JavaScript Google Sign-In par Google Identity Services :
Objets :
gapi.auth2.AuthorizeConfig
avecTokenClientConfig
Méthodes :
gapi.auth2.init()
avecgoogle.accounts.oauth2.initTokenClient()
Paramètres :
gapi.auth2.AuthorizeConfig.login_hint
avecTokenClientConfig.login_hint
.gapi.auth2.GoogleUser.getHostedDomain()
correspond àTokenClientConfig.hd
.
Flux de 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 implicite au flux avec code d'autorisation :
Supprimer les références du 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 entraîne le renvoi d'un jeton d'accès directement au navigateur de l'utilisateur avec le flux implicite, ou à votre plate-forme de backend après l'échange d'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 qu'une session active est établie avec Google. En mode implicite, un geste de l'utilisateur est requis pour demander un jeton d'accès, même s'il y a eu une demande antérieure.
Remplacer Documentation de référence du client JavaScript Google Sign-In par Google Identity Services :
Méthodes :
gapi.auth2.authorize()
avecTokenClient.requestAccessToken()
GoogleUser.reloadAuthResponse()
avecTokenClient.requestAccessToken()
Ajoutez un lien ou un bouton pour appeler requestAccessToken()
afin de lancer le flux d'expérience utilisateur pop-up pour demander un jeton d'accès ou pour obtenir un nouveau jeton lorsque le jeton existant expire.
Mettez à jour votre codebase pour :
- Déclenchez le flux de jetons OAuth 2.0 avec
requestAccessToken()
. - Prenez en charge l'autorisation incrémentielle en utilisant
requestAccessToken
etOverridableTokenClientConfig
pour diviser une requête pour plusieurs niveaux d'accès en plusieurs requêtes plus petites. - Demandez un nouveau jeton lorsque le jeton existant expire ou est révoqué.
L'utilisation de plusieurs niveaux d'accès peut nécessiter des modifications structurelles de votre code pour demander l'accès aux niveaux d'accès uniquement lorsqu'ils sont nécessaires, plutôt que tous en même temps. C'est ce qu'on appelle l'autorisation incrémentielle. Chaque requête doit contenir le moins de champs d'application possible, idéalement un seul. Pour savoir comment mettre à jour votre application pour l'autorisation incrémentielle, consultez Gérer le consentement de l'utilisateur.
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 pris en charge par 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 sur la gestion des jetons.
Flux de 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 le flux de code OAuth 2.0.
Pour savoir comment réagir en cas d'expiration ou de révocation d'un jeton d'accès, consultez la section "Gestion des jetons".
Gestion des jetons
Ajoutez la gestion des erreurs pour détecter les appels d'API Google ayant échoué lorsqu'un jeton d'accès expiré ou révoqué est utilisé, et pour demander un nouveau jeton d'accès valide.
Un code d'état HTTP 401 Unauthorized
et un message d'erreur invalid_token
sont renvoyés par les API Google lorsqu'un jeton d'accès expiré ou révoqué est utilisé. Pour consulter un exemple, reportez-vous à la section Réponse de jeton non valide.
Jetons expirés
Les jetons d'accès sont de courte durée et ne sont souvent valides que pendant quelques minutes.
Révocation de jeton
À tout moment, le propriétaire d'un compte Google peut révoquer l'autorisation précédemment accordée. Cela invalide les jetons d'accès et d'actualisation existants. La révocation peut être déclenchée depuis votre plate-forme à l'aide de revoke()
ou d'un compte Google.
Remplacer Documentation de référence du client JavaScript Google Sign-In par Google Identity Services :
Méthodes :
getAuthInstance().disconnect()
avecgoogle.accounts.oauth2.revoke()
GoogleUser.disconnect()
avecgoogle.accounts.oauth2.revoke()
Appelez revoke
lorsqu'un utilisateur supprime son compte sur votre plate-forme ou souhaite retirer son consentement au partage de données avec votre application.
Invite de consentement de l'utilisateur
Google affiche une boîte de dialogue de consentement à l'utilisateur lorsque votre application Web ou votre plate-forme de backend demande un jeton d'accès. Consultez des exemples de boîtes de dialogue de consentement affichées par Google aux utilisateurs.
Avant d'émettre un jeton d'accès pour votre application, une session Google existante et active est requise 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 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. Cela présente les avantages suivants :
- Réduit au minimum 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 credential
email
du jeton d'identité JWT comme valeur du paramètrelogin_hint
dans les objetsCodeClientConfig
ouTokenClientConfig
. Cela est particulièrement utile si votre plate-forme ne dispose pas d'un système de gestion des comptes utilisateur. - Recherchez et associez un compte Google à un compte utilisateur local existant sur votre plate-forme pour minimiser les comptes en double.
- Lorsqu'un nouveau compte local est créé, vos boîtes de dialogue et flux d'inscription peuvent être clairement séparés des boîtes de dialogue et 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 autoriser votre application pour les niveaux d'accès demandés.
Réponse du jeton et de l'autorisation
Une fois le consentement obtenu, un jeton d'accès est renvoyé avec une liste des autorisations approuvées ou refusées par l'utilisateur.
Les autorisations détaillées permettent aux utilisateurs d'approuver ou de refuser des habilitations individuelles. Lorsque vous demandez l'accès à plusieurs niveaux d'accès, chacun d'eux est accordé ou refusé indépendamment des autres. En fonction du choix de l'utilisateur, votre application active de manière sélective les fonctionnalités qui dépendent d'un champ d'application individuel.
Flux implicite
Remplacez les références du client JavaScript Google Sign-In par Google Identity Services :
Objets :
gapi.auth2.AuthorizeResponse
avecTokenClient.TokenResponse
gapi.auth2.AuthResponse
avecTokenClient.TokenResponse
Méthodes :
GoogleUser.hasGrantedScopes()
avecgoogle.accounts.oauth2.hasGrantedAllScopes()
GoogleUser.getGrantedScopes()
avecgoogle.accounts.oauth2.hasGrantedAllScopes()
Supprimez les références au client JavaScript 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 de code d'autorisation
Mettez à jour ou ajoutez un point de terminaison de code d'autorisation à votre plate-forme backend en suivant les instructions de la section Gestion du code d'autorisation.
Mettez à jour votre plate-forme en suivant les étapes décrites dans le guide Utiliser le 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 sélectivement des fonctionnalités en fonction des différents niveaux d'accès approuvés par l'utilisateur en suivant les instructions pour l'autorisation incrémentielle et examiner les niveaux d'accès accordés par l'utilisateur.
Exemples de flux implicites
L'ancienne méthode
Bibliothèque cliente GAPI
Exemple de la bibliothèque cliente des API Google pour JavaScript s'exécutant dans le navigateur à l'aide d'une boîte de dialogue pop-up pour 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 JS
OAuth 2.0 pour les applications Web côté client s'exécutant dans le navigateur à l'aide d'une boîte de dialogue pop-up 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 Google Cloud 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 le navigateur à l'aide de redirections vers Google pour obtenir le consentement de l'utilisateur.
Cet exemple montre des appels directs aux points de terminaison OAuth 2.0 de Google à partir du navigateur de l'utilisateur. Il n'utilise pas le module gapi.auth2
ni de 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>
La nouvelle méthode
GIS uniquement
Cet exemple ne montre que la bibliothèque JavaScript 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 nécessaires 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, async et await sont utilisés pour appliquer l'ordre de chargement des bibliothèques, et pour détecter et réessayer 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 sont censés 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>
<title>GAPI and GIS Example</title>
<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="gisLoad()"></script>
</head>
<body>
<h1>GAPI Client with GIS Authorization</h1>
<button id="authorizeBtn" style="visibility:hidden;">Authorize and Load Events</button>
<button id="revokeBtn" style="visibility:hidden;">Revoke Access</button>
<div id="content"></div>
<script>
const YOUR_CLIENT_ID = "YOUR_CLIENT_ID";
const YOUR_API_KEY = 'YOUR_API_KEY';
const CALENDAR_SCOPE = 'https://www.googleapis.com/auth/calendar.readonly';
let tokenClient;
let libsLoaded = 0;
function gapiLoad() {
gapi.load('client', initGapiClient);
}
async function initGapiClient() {
try {
await gapi.client.init({ apiKey: YOUR_API_KEY });
await gapi.client.load('https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest');
console.log('GAPI client initialized.');
checkAllLoaded();
} catch (err) {
handleError('GAPI initialization failed:', err);
}
}
function gisLoad() {
try {
tokenClient = google.accounts.oauth2.initTokenClient({
client_id: YOUR_CLIENT_ID,
scope: CALENDAR_SCOPE,
callback: '', // Will be set dynamically
error_callback: handleGisError,
});
console.log('GIS TokenClient initialized.');
checkAllLoaded();
} catch (err) {
handleError('GIS initialization failed:', err);
}
}
function checkAllLoaded() {
libsLoaded++;
if (libsLoaded === 2) {
document.getElementById('authorizeBtn').style.visibility = 'visible';
document.getElementById('revokeBtn').style.visibility = 'visible';
document.getElementById('authorizeBtn').onclick = makeApiCall;
document.getElementById('revokeBtn').onclick = revokeAccess;
console.log('Ready to authorize.');
}
}
function handleGisError(err) {
console.error('GIS Error:', err);
let message = 'An error occurred during authorization.';
if (err && err.type === 'popup_failed_to_open') {
message = 'Failed to open popup. Please disable popup blockers.';
} else if (err && err.type === 'popup_closed') {
message = 'Authorization popup was closed.';
}
document.getElementById('content').textContent = message;
}
function handleError(message, error) {
console.error(message, error);
document.getElementById('content').textContent = `${message} ${error.message || JSON.stringify(error)}`;
}
async function makeApiCall() {
document.getElementById('content').textContent = 'Processing...';
try {
let token = gapi.client.getToken();
if (!token || !token.access_token) {
console.log('No token, fetching one...');
await getToken();
}
console.log('Calling Calendar API...');
const response = await gapi.client.calendar.events.list({ 'calendarId': 'primary' });
displayEvents(response.result);
} catch (err) {
console.error('API call failed:', err);
const errorInfo = err.result && err.result.error;
if (errorInfo && (errorInfo.code === 401 || (errorInfo.code === 403 && errorInfo.status === "PERMISSION_DENIED"))) {
console.log('Auth error on API call, refreshing token...');
try {
await getToken({ prompt: 'consent' }); // Force refresh
const retryResponse = await gapi.client.calendar.events.list({ 'calendarId': 'primary' });
displayEvents(retryResponse.result);
} catch (refreshErr) {
handleError('Failed to refresh token or retry API call:', refreshErr);
}
} else {
handleError('Error loading events:', err.result ? err.result.error : err);
}
}
}
async function getToken(options = { prompt: '' }) {
return new Promise((resolve, reject) => {
if (!tokenClient) return reject(new Error("GIS TokenClient not initialized."));
tokenClient.callback = (tokenResponse) => {
if (tokenResponse.error) {
reject(new Error(`Token Error: ${tokenResponse.error} - ${tokenResponse.error_description}`));
} else {
console.log('Token acquired.');
resolve(tokenResponse);
}
};
tokenClient.requestAccessToken(options);
});
}
function displayEvents(result) {
const events = result.items;
if (events && events.length > 0) {
let eventList = '<h3>Upcoming Events:</h3><ul>' + events.map(event =>
`<li>${event.summary} (${event.start.dateTime || event.start.date})</li>`
).join('') + '</ul>';
document.getElementById('content').innerHTML = eventList;
} else {
document.getElementById('content').textContent = 'No upcoming events found.';
}
}
function revokeAccess() {
const token = gapi.client.getToken();
if (token && token.access_token) {
google.accounts.oauth2.revoke(token.access_token, () => {
console.log('Access revoked.');
document.getElementById('content').textContent = 'Access has been revoked.';
gapi.client.setToken(null);
});
} else {
document.getElementById('content').textContent = 'No token to revoke.';
}
}
</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 sont utilisées pour appliquer l'ordre de chargement des bibliothèques. Les appels GAPI sont effectués à partir du rappel une fois qu'un jeton d'accès valide est renvoyé.
Les utilisateurs doivent appuyer sur le bouton "Afficher l'agenda" lorsque la page est chargée pour la première fois, 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'interface utilisateur pop-up de la bibliothèque Google Identity Service peut utiliser une redirection d'URL pour renvoyer un code d'autorisation directement à votre point de terminaison de jeton de backend, ou un gestionnaire de rappel JavaScript s'exécutant dans le navigateur de l'utilisateur qui sert de proxy pour la réponse à votre plate-forme. Dans les deux cas, votre plate-forme de backend terminera le flux OAuth 2.0 pour obtenir un jeton d'actualisation et un jeton d'accès valides.
L'ancienne méthode
Applications Web côté serveur
Google Sign-In pour les applications côté serveur s'exécutant sur une plate-forme de backend à l'aide d'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 utilisant une redirection
Utilisez OAuth 2.0 pour les applications de serveur Web afin d'envoyer le code d'autorisation du navigateur de l'utilisateur à votre plate-forme de backend. Le consentement de l'utilisateur est 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 <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();
}
La nouvelle méthode
Expérience utilisateur des pop-ups GIS
Cet exemple montre uniquement la bibliothèque JavaScript Google Identity Services utilisant le modèle de code d'autorisation, une boîte de dialogue pop-up pour le consentement de l'utilisateur et un gestionnaire de rappel pour 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 et envoyer un code d'autorisation à votre plate-forme de 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 GIS
Le modèle de code d'autorisation est compatible avec les modes UX pop-up et redirection pour envoyer un code d'autorisation par utilisateur au point de terminaison hébergé par votre plate-forme. Le mode UX de redirection est illustré ci-dessous :
<!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 et les fonctions disponibles dans plusieurs bibliothèques et modules différents :
Actions à effectuer lors de la migration vers les services d'identité :
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 nouvelle bibliothèque et le flux de code d'autorisation. |
Référence rapide sur 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 remarques contenant des informations supplémentaires et les actions à effectuer lors de la migration.
Ancienne version | Nouveau | 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 nouveau. La révocation peut également avoir lieu sur https://myaccount.google.com/permissions. |
GoogleAuth.grantOfflineAccess() | Supprimez-le en suivant le flux du 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 nouveau. La révocation peut également avoir lieu sur https://myaccount.google.com/permissions. |
GoogleUser.getAuthResponse() | requestCode() or requestAccessToken() | Remplacer l'ancien par le nouveau |
GoogleUser.getBasicProfile() | Supprimer. Utilisez plutôt un jeton d'identité. Pour en savoir plus, consultez Migrer depuis Google Sign-In. | |
GoogleUser.getGrantedScopes() | hasGrantedAnyScope() | Remplacer l'ancien par le nouveau |
GoogleUser.getHostedDomain() | Supprimer | |
GoogleUser.getId() | Supprimer | |
GoogleUser.grantOfflineAccess() | Supprimez-le en suivant le flux du code d'autorisation. | |
GoogleUser.grant() | Supprimer | |
GoogleUser.hasGrantedScopes() | hasGrantedAnyScope() | Remplacer l'ancien par le nouveau |
GoogleUser.isSignedIn() | Supprimer | |
GoogleUser.reloadAuthResponse() | requestAccessToken() | Supprimez l'ancien jeton d'accès et appelez le nouveau pour remplacer celui qui a expiré ou a été révoqué. |
Objet gapi.auth2 et méthodes associées : | ||
Objet gapi.auth2.AuthorizeConfig | TokenClientConfig ou CodeClientConfig | Remplacer l'ancien par le nouveau |
Objet gapi.auth2.AuthorizeResponse | Supprimer | |
Objet gapi.auth2.AuthResponse | Supprimer | |
gapi.auth2.authorize() | requestCode() or requestAccessToken() | Remplacer l'ancien par le nouveau |
gapi.auth2.ClientConfig() | TokenClientConfig ou CodeClientConfig | Remplacer l'ancien par le nouveau |
gapi.auth2.getAuthInstance() | Supprimer | |
gapi.auth2.init() | initTokenClient() or initCodeClient() | Remplacer l'ancien par le nouveau |
Objet gapi.auth2.OfflineAccessOptions | Supprimer | |
Objet gapi.auth2.SignInOptions | Supprimer | |
Objet gapi.signin2 et méthodes associées : | ||
gapi.signin2.render() | Supprimer. Le chargement du DOM HTML de l'élément g_id_signin ou l'appel JS à google.accounts.id.renderButton déclenchent la connexion de l'utilisateur à un compte Google. |
Exemple d'identifiants
Identifiants existants
La bibliothèque de plate-forme Google Sign-In, la bibliothèque cliente des API Google pour JavaScript ou les appels directs aux points de terminaison Google OAuth 2.0 renvoient à la fois un jeton d'accès OAuth 2.0 et un jeton d'identité OpenID Connect dans une même 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"
}
Identifiant Google Identity Services
La bibliothèque Google Identity Services renvoie :
soit un jeton d'accès lorsqu'il est utilisé 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'identité lorsqu'il est utilisé 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 lorsque vous tentez d'envoyer 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"
}
}