javascriptoauth-2.0google-oauthgoogle-api-js-client

Using Google Sheet API through the new "Sign in with Google" instead of the old "Google Sign-in"


I am threatened by Google to quit using the old (but very effective) "Google Sign-in" because it will be deprecated on 31 Mar 2023. It is fine, but when I go for the new "Sign in with Google", I find that there are no documents explaining how this new authorization flow can integrate with Google Sheet API.

Ironically, even in Google Sheet API's documentations, the demos there are all still based on the old "Google Sign-in". Can anyone provide demo cases of how to read and insert values into Google Sheet based on the new "Sign in with Google"?


Solution

  • The Google sheets api quickstart for javascript has been updated to use web authorization.

    You dont want to use signin unless you are working with Authencation, for google sheets you need authorization. The new library splits these two concepts.

    <!DOCTYPE html>
    <html>
    <head>
        <title>Sheets API Quickstart</title>
        <meta charset="utf-8" />
    </head>
    <body>
    <p>Sheets API Quickstart</p>
    
    <!--Add buttons to initiate auth sequence and sign out-->
    <button id="authorize_button" onclick="handleAuthClick()">Authorize</button>
    <button id="signout_button" onclick="handleSignoutClick()">Sign Out</button>
    
    <pre id="content" style="white-space: pre-wrap;"></pre>
    
    <script type="text/javascript">
        /* exported gapiLoaded */
        /* exported gisLoaded */
        /* exported handleAuthClick */
        /* exported handleSignoutClick */
    
        // TODO(developer): Set to client ID and API key from the Developer Console
        const CLIENT_ID = '<YOUR_CLIENT_ID>';
        const API_KEY = '<YOUR_API_KEY>';
    
        // Discovery doc URL for APIs used by the quickstart
        const DISCOVERY_DOC = 'https://sheets.googleapis.com/$discovery/rest?version=v4';
    
        // Authorization scopes required by the API; multiple scopes can be
        // included, separated by spaces.
        const SCOPES = 'https://www.googleapis.com/auth/spreadsheets.readonly';
    
        let tokenClient;
        let gapiInited = false;
        let gisInited = false;
    
        document.getElementById('authorize_button').style.visibility = 'hidden';
        document.getElementById('signout_button').style.visibility = 'hidden';
    
        /**
         * Callback after api.js is loaded.
         */
        function gapiLoaded() {
            gapi.load('client', intializeGapiClient);
        }
    
        /**
         * Callback after the API client is loaded. Loads the
         * discovery doc to initialize the API.
         */
        async function intializeGapiClient() {
            await gapi.client.init({
                apiKey: API_KEY,
                discoveryDocs: [DISCOVERY_DOC],
            });
            gapiInited = true;
            maybeEnableButtons();
        }
    
        /**
         * Callback after Google Identity Services are loaded.
         */
        function gisLoaded() {
            tokenClient = google.accounts.oauth2.initTokenClient({
                client_id: CLIENT_ID,
                scope: SCOPES,
                callback: '', // defined later
            });
            gisInited = true;
            maybeEnableButtons();
        }
    
        /**
         * Enables user interaction after all libraries are loaded.
         */
        function maybeEnableButtons() {
            if (gapiInited && gisInited) {
                document.getElementById('authorize_button').style.visibility = 'visible';
            }
        }
    
        /**
         *  Sign in the user upon button click.
         */
        function handleAuthClick() {
            tokenClient.callback = async (resp) => {
                if (resp.error !== undefined) {
                    throw (resp);
                }
                document.getElementById('signout_button').style.visibility = 'visible';
                document.getElementById('authorize_button').innerText = 'Refresh';
                await listMajors();
            };
    
            if (gapi.client.getToken() === null) {
                // Prompt the user to select a Google Account and ask 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: ''});
            }
        }
    
        /**
         *  Sign out the user upon button click.
         */
        function handleSignoutClick() {
            const token = gapi.client.getToken();
            if (token !== null) {
                google.accounts.oauth2.revoke(token.access_token);
                gapi.client.setToken('');
                document.getElementById('content').innerText = '';
                document.getElementById('authorize_button').innerText = 'Authorize';
                document.getElementById('signout_button').style.visibility = 'hidden';
            }
        }
    
        /**
         * Print the names and majors of students in a sample spreadsheet:
         * https://docs.google.com/spreadsheets/d/1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms/edit
         */
        async function listMajors() {
            let response;
            try {
                // Fetch first 10 files
                response = await gapi.client.sheets.spreadsheets.values.get({
                    spreadsheetId: '1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms',
                    range: 'Class Data!A2:E',
                });
            } catch (err) {
                document.getElementById('content').innerText = err.message;
                return;
            }
            const range = response.result;
            if (!range || !range.values || range.values.length == 0) {
                document.getElementById('content').innerText = 'No values found.';
                return;
            }
            // Flatten to string to display
            const output = range.values.reduce(
                (str, row) => `${str}${row[0]}, ${row[4]}\n`,
                'Name, Major:\n');
            document.getElementById('content').innerText = output;
        }
    </script>
    <script async defer src="https://apis.google.com/js/api.js" onload="gapiLoaded()"></script>
    <script async defer src="https://accounts.google.com/gsi/client" onload="gisLoaded()"></script>
    </body>
    </html>