0
votes

The task I need to solve is to get "gapi.auth2" access for Google Sheets and Google Drive through JS in WebBrowser and than to use this permissions granted from user directly and byitself for a long time (untill user gets back this permissions).

I need to have possibility to change (add some info) to Google Sheet of the user. User had to configure what info will be added. That's why I need to save and use access info (access & refresh tokens) offline.

Code I tried:

<div>
    <p>Google Sheets API Quickstart</p>

    <!--Add buttons to initiate auth sequence and sign out-->
    <button id="authorize_button" style="display: none;">Authorize</button>
    <button id="signout_button" style="display: none;">Sign Out</button>

    <pre id="content" style="white-space: pre-wrap;"></pre>

    <script type="text/javascript">
  // Client ID and API key from the Developer Console
  var CLIENT_ID = 'MyID.apps.googleusercontent.com';
  var API_KEY = 'MyKey';

  // Array of API discovery doc URLs for APIs used by the quickstart
  var DISCOVERY_DOCS = ["https://sheets.googleapis.com/$discovery/rest?version=v4"];

  // Authorization scopes required by the API; multiple scopes can be
  // included, separated by spaces.
  var SCOPES = "https://www.googleapis.com/auth/spreadsheets https://www.googleapis.com/auth/drive";

  var authorizeButton = document.getElementById('authorize_button');
  var signoutButton = document.getElementById('signout_button');

  /**
   *  On load, called to load the auth2 library and API client library.
   */
  function handleClientLoad() {
    gapi.load('client:auth2', initClient);
  }

  /**
   *  Initializes the API client library and sets up sign-in state
   *  listeners.
   */
  function initClient() {
    gapi.client.init({
      apiKey: API_KEY,
      clientId: CLIENT_ID,
      discoveryDocs: DISCOVERY_DOCS,
      scope: SCOPES
    }).then(function () {
      // Listen for sign-in state changes.
      gapi.auth2.getAuthInstance().isSignedIn.listen(updateSigninStatus);

      // Handle the initial sign-in state.
      updateSigninStatus(gapi.auth2.getAuthInstance().isSignedIn.get());
      authorizeButton.onclick = handleAuthClick;
      signoutButton.onclick = handleSignoutClick;
    }, function(error) {
      appendPre(JSON.stringify(error, null, 2));
    });
  }

  /**
   *  Called when the signed in status changes, to update the UI
   *  appropriately. After a sign-in, the API is called.
   */
  function updateSigninStatus(isSignedIn) {
    if (isSignedIn) {
      authorizeButton.style.display = 'none';
      signoutButton.style.display = 'block';
      listMajors();
    } else {
      authorizeButton.style.display = 'block';
      signoutButton.style.display = 'none';
    }
  }

  /**
   *  Sign in the user upon button click.
   */
        function handleAuthClick(event) {
            let instance = gapi.auth2.getAuthInstance();
            console.log(instance);
            let promise = instance.signIn();
            console.log(gapi.auth2.getAuthInstance());
            console.log(promise);
            console.log(gapi.client);
            console.log(gapi.client.getToken());
            console.log(gapi.auth2);

            console.log(gapi.auth2.getAuthInstance().currentUser.get().getAuthResponse());
            console.log(gapi.auth2.getAuthInstance().currentUser.get());
            console.log(gapi.auth2.getAuthInstance().currentUser);

            console.log(instance.currentUser);
            console.log(instance.currentUser.ie);
            console.log(instance.currentUser.ie.uc);
            console.log(instance.currentUser.ie.uc.access_token);
            console.log(auth);
            let auth = instance.currentUser.ie.uc.access_token;

            let a = document.getElementById('my');
            a.href += auth;

            let xhr = new XMLHttpRequest();
            xhr.setRequestHeader('Authorization', 'Bearer ' + "ya29.a0Adw1xeXfLePcaSdeluMmvtDrnrgbDibLToC22Vw5yOfIhOpQ1TqxFlROBozsBPbXL1GRYHumMltcLuJWNygtZ1m8IRpfx9n7I-oLQi4BpgaU98nx7InjquPqJ8Yc2aGvN9ac6HI9rqlDPJFTbhxKP37SzG_31x_u6vs");
            xhr.
            xhr.send();


  }

  /**
   *  Sign out the user upon button click.
   */
  function handleSignoutClick(event) {
    gapi.auth2.getAuthInstance().signOut();
  }

  /**
   * Append a pre element to the body containing the given message
   * as its text node. Used to display the results of the API call.
   *
   * param {string} message Text to be placed in pre element.
   */
  function appendPre(message) {
    var pre = document.getElementById('content');
    var textContent = document.createTextNode(message + '\n');
    pre.appendChild(textContent);
  }

  /**
   * Print the names and majors of students in a sample spreadsheet:
   * https://docs.google.com/spreadsheets/d/1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms/edit
   */
  function listMajors() {
    gapi.client.sheets.spreadsheets.values.get({
      spreadsheetId: '1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms',
      range: 'Class Data!A2:E',
    }).then(function(response) {
      var range = response.result;
      if (range.values.length > 0) {
        appendPre('Name, Major:');
        for (i = 0; i < range.values.length; i++) {
          var row = range.values[i];
          // Print columns A and E, which correspond to indices 0 and 4.
          appendPre(row[0] + ', ' + row[4]);
        }
      } else {
        appendPre('No data found.');
      }
    }, function(response) {
      appendPre('Error: ' + response.result.error.message);
    });
        }
    </script>
</div>

<script async defer src="https://apis.google.com/js/api.js"
        onload="this.onload=function(){};handleClientLoad()"
        onreadystatechange="if (this.readyState === 'complete') this.onload()">
</script>

Also I tried to type this into browser: "https://accounts.google.com/o/oauth2/auth?access_type=offline&prompt=consent&redirect_uri=https://localhost:44325/&client_id=MyID.apps.googleusercontent.com&scope=https://www.googleapis.com/auth/spreadsheets+https://www.googleapis.com/auth/drive&response_type=code&state=/profile"

redirect_uri is wrong, and adding it in console do not help.

When I try to use Quichstart .NET App it works fine, but I get only my tokens, not my clients.

How to get offline access to my clients Google Data using JS? Where can I get refresh token if my client gives me access through JS in WebBrowser?

1

1 Answers

0
votes

The correct link was - https://accounts.google.com/o/oauth2/auth?access_type=offline&prompt=consent&redirect_uri=https://localhost:44325&client_id=MyID.apps.googleusercontent.com&scope=https://www.googleapis.com/auth/spreadsheets+https://www.googleapis.com/auth/drive&response_type=code&state=/profile

"redirect_uri=https://localhost:44325" not "redirect_uri=https://localhost:44325/"

Then when I was redirected to "https://localhost:44325/" the link was next "https://localhost:44325/?state=/profile&code=4/xwFM---SOME SYMBOLS---&scope=https://www.googleapis.com/auth/drive%20https://www.googleapis.com/auth/spreadsheets"

Where "4/xwFM---SOME SYMBOLS---" is my refresh token as I gues. I'll check it tomorrow.

UPD. This code I use then in POST request to "https://accounts.google.com/o/oauth2/token" with the following fields set:

grant_type=authorization_code
code='the code from the previous step'
client_id='the client ID token created in the APIs Console'
client_secret='the client secret corresponding to the client ID'
redirect_uri='the URI registered with the client ID'

Details: https://developers.google.com/android-publisher/authorization