12

Today Google Picker stopped working in my Google Sheets add-on without any changes to the code. The error in the modal dialogue reads:

Invalid origin value.

The errors in console are:

Failed to execute 'postMessage' on 'DOMWindow': The target origin provided ('https://docs.google.com') does not match the recipient window's origin ('https://n-a6p4dqsl***d6wq-0lu-script.googleusercontent.com')

dropping postMessage.. was from unexpected window

dropping postMessage.. was from unexpected window

Invalid 'X-Frame-Options' header encountered when loading 'https://docs.google.com/picker?protocol=gadgets&origin=https%3A%2F%2Fdocs.google.com%2F&sdr=true&title&oauth_token=<oathToken>&developerKey=<developerKey>&hostId=n-a6p4dq***d6wq-0lu-script.googleusercontent.com&relayUrl=https%3A%2F%2Fn-a6p4dq***d6wq-0lu-script.googleusercontent.com%2Ffavicon.ico&nav=((%22documents%22%2Cnull%2C%7B%22selectFolder%22%3Atrue%2C%22parent%22%3A%22root%22%7D)%2C(%22documents%22%2Cnull%2C%7B%22dr%22%3Atrue%2C%22includeFolders%22%3Atrue%7D))&rpcService=qhurmoc5w4l7&rpctoken=xssf8g42xc2&thirdParty=true#rpctoken=xssf8g42xc2': 'ALLOW-FROM https://docs.google.com/' is not a recognized directive. The header will be ignored.

It maybe that the error is linked to this line of code where I do setOrigin():

        var picker = new google.picker.PickerBuilder()
            .addView(driveView)
            .addView(drivesView)
            .hideTitleBar()
            .setOAuthToken(token)
            .setDeveloperKey(DEVELOPER_KEY)
            .setCallback(pickerCallback)
        --> .setOrigin(google.script.host.origin)
            .setSize(DIALOG_DIMENSIONS.width - 2,
                DIALOG_DIMENSIONS.height - 2)
            .build();

But this line is directly from the documentation of the Google Picker API and worked properly before. If I change google.script.host.origin, that returns https://docs.google.com as url to https://n-a6p4dqsl***6wcd6wq-0lu-script.googleusercontent.com, I get the same error and a new one, so that is not it.

I also cannot add this as as an authorized javascript origin in the GCP project as it returns the following error:

Invalid Origin: uses a forbidden domain

(This has been the case of a while)

This seems like a new error and I wasn't able to find an answer neither on Google's issues tracker nor on StackOverflow.

Anyone facing this as well or have an idea how it can be handled?

Dmitry Kostyuk
  • 1,354
  • 1
  • 5
  • 21
  • 1
    Same issue for us with an add-on as well. I believe that setOrigin line is converted into the X-Frame-Options directive using a header ALLOW-FROM that is now ignored, so causing the Invalid origin value error message as the response. I just found out in the X-Frame-Options documentation that ALLOW-FROM is an obsolete directive that no longer works in modern browsers. Don't use it ... Maybe they just started to drop it yesterday. I am guessing that might the actual reason – Fausto R. Jan 09 '21 at 01:35

2 Answers2

13

Putting an end, the only way to solve this is to remove the trailing slash after

From

docs.google.com/

To

docs.google.com

Contrary,

The google.script.host.orgin gives the "https://docs.google.com/" which causes the error. Hence you need to hard code as

"https://docs.google.com"

Google has made some changes recently which might have bubbled this issue.

UPDATE

You can use this function - and call - ...... setOrigin(getOrigin())

function getOrigin() {
    var url = google.script.host.origin;
    return url.substr(url.length - 1) === "/" ? url.substr(0, url.length - 1) : url;
}
Code Guy
  • 3,059
  • 2
  • 30
  • 74
  • 3
    This worked for me.. To make it extra clear, this new hardcoded value goes in the `setOrigin()` call on the `PickerBuilder()` instead of the `google.script.host.origin` value that is there in the docs. – Seb Barre Jan 09 '21 at 17:09
  • Thanks a million, this worked! For those who don't want to hardcode the url, you can use the following function to strip the trailing slash: ` function stripSlash(url) { return url.substr(url.length - 1) === "/" ? url.substr(0, url.length - 1) : url; } ` – Dmitry Kostyuk Jan 09 '21 at 18:24
0

Solution for use in a iframe

https://developers.google.com/apps-script/guides/dialogs#code.gs_2

code.gs

         function showPicker() {
          var html = HtmlService.createHtmlOutputFromFile('dialog.html')
              .setWidth(600)
              .setHeight(425)
              .setSandboxMode(HtmlService.SandboxMode.IFRAME);
          SpreadsheetApp.getUi().showModalDialog(html, 'Select a file');
    }


.setSandboxMode(HtmlService.SandboxMode.IFRAME); 
//can be removed or replaced with
.setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);

dialog.html

function getOrigin() {
        var url = "https://mydomain.name/";
        return url.substr(url.length - 1) === "/" ? url.substr(0, url.length - 1) : url;
    }

Update

Now it works without any changes in the code.

Sergey.K
  • 11
  • 1