javascriptgoogle-sheetsgoogle-api-js-clientgoogle-identity

How do I use new google identity JS library to work with sheets?


Google introduced new Sign In JS library(gsi) a long time ago but Google Sheets documentation still shows examples using gapi. What would be the best approach to combine/replace gapi with gsi? May I have an example?


Solution

  • Update 2022/02/04:

    Documentation regarding Google Identity Services JavaScript SDK just became available.

    In contrast with Sign In With Google, which only handles authentication (see Authentication and authorization), this library handles OAuth tokens (see Using the token model) to access Google APIs, and so can be used as a complete replacement to gapi.

    Please notice though that GIS doesn't handle calling the API, and so Google suggests to keep using gapi.client for that (ref):

    You can safely continue using the gapi.client module from the Google API Client Library for JavaScript, and take advantage of its automatic creation of callable JS methods from a discovery document, batching multiple API calls, and CORS management functionality.

    So, after getting the access token via GIS, you can either use gapi to call the API, or call the API without any of these libraries (in the example below and in the official docs, XMLHttpRequest is used for that).

    Sample 1: Use Google Identity Services:

    <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: 'CLIENT_ID',
              scope: 'https://www.googleapis.com/auth/spreadsheets.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 listMajors() {
            var spreadsheetId = '1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms';
            var range = 'Class Data!A2:E';
            var xhr = new XMLHttpRequest();
            xhr.onreadystatechange = function() {
              if (this.readyState == 4 && this.status == 200) {
                console.log(this.responseText);
              }
            };
            xhr.open('GET', `https://sheets.googleapis.com/v4/spreadsheets/${spreadsheetId}/values/${range}`);
            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="listMajors();">Call Sheets API</button> <br><br>
        <button onclick="revokeToken();">Revoke token</button>
      </body>
    </html>
    

    Sample 2. Use GIS in combination with GAPI:

    <html>
    <head>
      <script src="https://accounts.google.com/gsi/client" onload="gisInit()" async defer></script>
      <script src="https://apis.google.com/js/api.js" onload="gapiLoad()" async defer></script>
    </head>
    <body>
      <script>
    
        var tokenClient;
        var access_token;
    
        function gapiStart() {
            gapi.client.init({
          }).then(function() {
            gapi.client.load('sheets', 'v4');
          }).then(function(response) {
            console.log('discovery document loaded');
          }, function(reason) {
            console.log('Error: ' + reason.result.error.message);
          });
        }
    
        function gapiLoad() {
          gapi.load('client', gapiStart)
        }
    
        function gisInit() {
          tokenClient = google.accounts.oauth2.initTokenClient({
            client_id: 'CLIENT_ID',
            scope: 'https://www.googleapis.com/auth/spreadsheets.readonly',
            callback: (tokenResponse) => {
              access_token = tokenResponse.access_token;
            },
          });
        }
    
        function getToken() {
          tokenClient.requestAccessToken();
        }
    
        function listMajors() {
          gapi.client.sheets.spreadsheets.values.get({
            spreadsheetId: '1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms',
            range: 'Class Data!A2:E',
          }).then(function(response) {
            var range = response.result;
            console.log(range);
          });
        }
    
    
        function revokeToken() {
          google.accounts.oauth2.revoke(access_token, () => {console.log('access token revoked')});
        }
    
      </script>
    
      <h1>Google Identity Services Authorization and GAPI</h1>
      <button onclick="getToken();">Get access token</button> <br><br>
      <button onclick="listMajors();">Call Sheets API</button> <br><br>
      <button onclick="revokeToken();">Revoke token</button>
    </body>
    </html>
    

    Note:

    Both these samples are based on the examples found in the official docs, in which Calendar API is called (see Implicit flow examples).

    Reference: