0

I have a simple app script that searches drive for a folder named 'something' and lists the names of files inside if the folder doesn't exist it creates it.

function doGet() {
 var folders = DriveApp.getFoldersByName('something');
 if (folders.hasNext()) {
  var files = folders.next().getFiles();
    var fileNames  = [];
    while (files.hasNext()) {
      var file = files.next();
      fileNames.push(file.getName())
    };
    return ContentService.createTextOutput(JSON.stringify({
        'status': 'success',
        'output': fileNames
    }))

  } else {
    DriveApp.createFolder('something');
    return ContentService.createTextOutput(JSON.stringify({
        'status': 'success',
        'output': 'folder created'
    }))
  }
}

I deploy the script as a web app, execute the app as myself, test it out using a fetch call from a react app in a browser and everything work as expected.

Then I republish as a web app, executing as the user accessing the web app. This time nothing works. I get the following error in the browser

Access to fetch at 'https://script.google.com/macros/s/AKfycbx4eQ60DziUy4hSjnJidW9WVwBsT_qruQHa_BrK508T4oD9ILY/exec' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

I expected an error since there is no authentication. I set up google OAuth2 on the react app, added scripts and drive scopes, register the app in google developer console and set everything up so that I get an accessToken that I can send in the header with the fetch call to the google script.

But I still get the same error as above.

How am I supposed to authorize an app script app so that anyone can run it?

I am trying to create a web app with a google sign in button, when the user signins in it calls the appscript I deployed and searches their drive for a folder names 'something' so that I can display the names of files in my web app.

This is not a cors issue, if I execute the web app as myself there is no cors problems and zero changes to the code. My question is regarding how I authorise an app script? I only mention the cors error because I was showing what I have tried so far.

7
  • 1. Try setting X-frame options to Allow-all with htmlservice OR 2. use doPost() OR 3. Use a backend to fetch Commented Apr 3, 2019 at 12:15
  • So you are saying this is just a cors issue, what I am trying to do makes sense and is possible using appscript? Commented Apr 3, 2019 at 12:24
  • Isn't that what your error states? I don't see why not... But I'm doubtful whether you can bypass cors. Commented Apr 3, 2019 at 12:25
  • 3
    @tehhowch reopened Commented Apr 3, 2019 at 13:29
  • 1
    I can't guarantee anything, but I believe what you're trying to do is entirely possible and that this still is a cors issue or as the answer states Google's error page does not include any CORS headers.-> So, you have a error somewhere. You have to provide error logs(view>Stackdriver logging) Commented Apr 3, 2019 at 14:18

1 Answer 1

1

You will receive a CORS error if any function in your call throws an exception, since you have no try...catch handler. When a deployed webapp fails to return a valid response (i.e. either an HtmlOutput or TextOutput), Google's error page does not include any CORS headers.

To prevent these "masking" CORS errors, wrap your web app entry points with try...catch so that the actual error can be reported.

Even without wrapping your webapp's entry points with try...catch, it is very likely that you are able to access the underlying error by viewing your project's Stackdriver logs / Stackdriver Error Reporting.

This is a simple example, demonstrating some event object validation to ensure that the request is from somewhere you care about & is well-formed, and then calls a function that may throw an exception for invalid / unauthorized operations. In either case, it returns an opaque user-facing response ("Sorry!") and for errors will generate a Stackdriver log. It cannot catch the exception that occurs for an execution time quota breach, since your script is simply killed.

function doGet(e) {
  if (!e || !validate_(e)) {
    return fail_();
  }
  try {
    return walkDriveContent(...);
  }
  catch (err) {
    console.error({message: "Drive walk failed: " + err.message, stack: err.stack, error: err});
    return fail_();
  }
}

function fail_() {
  return ContentService.createTextOutput("Sorry!");
}

function validate_(eventObj) {
 /** your code here that ensures this is a valid event object you can work with */
 // return true;
 //     or
 // return false;
}

function walkDriveContent(folderName) {
  /**
   * Your code that may throw exceptions here, but otherwise
   * returns TextOutput or HtmlOutput
   */
}
Sign up to request clarification or add additional context in comments.

5 Comments

Thanks, I'll try this. But does this means you are saying that my general approach is correct and I shoudl be able to authentcate a script by passing in teh access token in the header. there is nothing else I have to do?
@josh Off the top of my head, yes, if you've obtained an OAuth2 access token that contains the required scopes, then you can execute your web app as that user. You may or may not be able to access the web app as that user. I suggest updating your question to be about resolving the masking CORS error, and then when you have the underlying error pinned down, ask a new question about that. Probably you should review github.com/tanaikech/…
I'm not too worried about cors, I'll figure that out or ask another question, this question is titled 'How do I authorize an app script in a web interface?'.
@josh Yes, that's the title, but then your question body is almost entirely about a CORS error. This answer of mine demonstrates how you can prevent getting that CORS error (and instead access the underlying error that created the CORS error).
Thank you. I appreciate your help. I did my best to explicitly state that this is not a cors issue at the bottom of the question, and that I only mention the cors error because I was showing what I have tried so far. My concern is that I don;t want to spend ages fixing teh cors error if what I am trying to do in fundamentally not possible. Have you ever granted access to an app script app via a web app by passing in a token?

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.