1

This is Yet another error 403 on Google Sheets API. Um trying to read the data from a Spreadsheet and expose it on a website, using some custom HTML filters.

So, there is this question: Error 403 on Google Sheets API

Still, I cannot figure out what to do. I have setup my service account in the google cloud platform, granted it permissions to access my Spreadsheet - I have even made my SpreadSheet accessible via link (but that is restricted to emails from my organization, so it seems useless anyway). I've also activated domain-wide delegation for my service account - didn't make any difference at all. I'm pretty sure the issue is not related to a wrong key or some typo because, when I remove the access to the service email from the sheet, I steel get a 403 error, but it comes with a message saying the caller doesn't have access to that spreadsheet.

People keep mentioning OAuth, but I don't want to use that, since I'm intending to use a simple API access, as in this Google GitHub example. I'm using my business account, so there might be some issue related to that.

Here is the HTML (which I'm running from a simple HTTP server on python, not directly, given the fact the GAPI doesn't handle localhost/ sources very well):

<!DOCTYPE html>
<html>
  <head>
    <title>Google Sheets API Quickstart</title>
    <meta charset="utf-8" />
  </head>
  <body>
    <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 API_KEY = 'My-API-KEY';
      var DISCOVERY_DOCS = ["https://sheets.googleapis.com/$discovery/rest?version=v4"];
      var SCOPES = "https://www.googleapis.com/auth/spreadsheets.readonly";

      function handleClientLoad() {
        gapi.load('client', initClient);
      }

      function initClient() {
        gapi.client.init({
          apiKey: API_KEY,
          discoveryDocs: DISCOVERY_DOCS
        }).then(function(){listMajors();})
      }

      function appendPre(message) {
        var pre = document.getElementById('content');
        var textContent = document.createTextNode(message + '\n');
        pre.appendChild(textContent);
      }

      function listMajors() {
        gapi.client.sheets.spreadsheets.values.get({
          spreadsheetId: 'my-spreadsheet-id',
          range: 'Sheet1!A1:A10',
        }).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>

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


Does anyone have anyclue on what I'm missing, or what else can I try?

Edit: sharing the spreadsheet publicly is not an option. The is a business email, and, therefore, the only option I've got here is sharing it domain wide, as I've already stated above. Also, this is a business spreadsheet, and therefofe contains sentitive data. Doesn't really make sense to expose it publicly. Besides that, I've already shared the spreadsheet with the service email. What I'm trying to achieve, after all, is to read the data from the spreadsheet without using oauth, and emdding it on a website (I know there is a built-in embed tool, but that doesn't suit me because I need to add a html filter).

14
  • You are trying to access to Google Spreadsheet using the service account with the script in your question. If my understanding is correct, can I ask you about where the service account is used in your script? If I misunderstood your question, I apologize. Commented Feb 13, 2020 at 0:14
  • You understood it properly. I don't declare it directly. I didn't even see in the docs some guidance to use it. I don't know how shoould it be done. Commented Feb 13, 2020 at 1:14
  • Thank you for replying. When the service account is used, the users are not required to log in to Google. In this case, I think that you can create HTML including Javascript without the python server. But I'm not sure about your goal. So can I ask you about your goal? Commented Feb 13, 2020 at 1:33
  • Yeah, the python server was used only for local testing purposes. My goal is to read the data from a Spreadsheet and show it on a site - but I need to have a filter, so the default Google Spreadsheet embedding options doont suit me. Commented Feb 13, 2020 at 1:41
  • Thank you for replying. For example, in your actual situation, the Spreadsheet can shared publicly as the readonly? If you can do, how about retrieving the values from the shared Spreadsheet? In this case, the values can be retrieved with the API key, and the script is simpler than that using the service account. Commented Feb 13, 2020 at 1:55

1 Answer 1

0

If you try to access a Spreadsheet that is not public, you will have to use OAuth 2.0. Since it is not a public resource, you have to use the credentials of an account that has access to this resource.

In the example you provided, they are accessing a public resource, so the API key is enough. That's not your case.

Reference:

Sign up to request clarification or add additional context in comments.

6 Comments

Just to clarify - if I want to embed a given Spreadsheet on my HTML page, the user accessing the page will be prompted to grant my page access, from his Google user, to the Spreadsheet?
@LucasLima how are you embedding the spreadsheet to your page? Is that via an iframe?
I'm not actually trying to embed it. I'm trying to read the data from the spreadsheet, and then present it on a HTML table - the reason for that is I want the user to be able to filter the values, and, AFAIK, standard embedding doesn't allow that. So, although I have not got that far, I don't think that will be a thing in my process. Advice is most welcome, btw
@LucasLima What you could do in this situation is to make a request to your server, in which you could use your Service Account to complete the authorization flow and request the desired data from the spreadsheet, and finally, send this data back to the client. I don't know what technologies (if any) you're using server-side though, so I'm afraid I can't be more precise. I'd suggest you to create another question regarding this, while providing more details about your case.
Thank you for your suggestion. I didn't know of the existence of such a thing. That said, considering they don't show an option to do it using JS on a browser (I intend to embed it on a Google Site, BTW), I will access the spreadsheet using a Google Script, and expose it as a webapp, which will just be accessible when logged in a business account from our domain.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.