-2

I'm implementing login with Spotify. Basically, I open a new window to allow user to log in.

As soon as the window is opened, I get this error in console:

DOMException: Blocked a frame with origin "http://localhost:3000" from accessing a cross-origin frame. at http://localhost:3000/static/js/main.chunk.js:2522:30

This is the handler to open the window, where spotifyLoginUrl has the following pattern:

https://accounts.spotify.com/en/authorize?scope=user-follow-read%20user-read-email&response_type=code&redirect_uri=http:%2F%2Flocalhost:3000%2F&client_id=x&show_dialog=true&state=y
const handleSpotifyLogin = (event) => {
  popupWindow
    .open(
      spotifyLoginUrl,
      'spotify-authorization',
      530,
      840,
      getSpotifyCode,
      getSpotifyState
    )
    .then(({ loginCode, loginState }) => {
      ...
    })
    .catch((err) => {
      console.error(err);
    });
};

And the popup window handler:

export const openWindow = (url, windowName, w, h) => {
  const y = window.top.outerHeight / 2 + window.top.screenY - h / 2;
  const x = window.top.outerWidth / 2 + window.top.screenX - w / 2;
  return window.open(
    url,
    windowName,
    `toolbar=no, location=no, directories=no, status=no, menubar=no,
    scrollbars=no, resizable=no, copyhistory=no,
    width=${w}, height=${h}, top=${y}, left=${x}`
  );
};

class popupWindow {
  constructor(url, id, w, h, getLoginCode, getLoginState) {
    this.url = url;
    this.id = id;
    this.w = w;
    this.h = h;
    this.getLoginCode = getLoginCode;
    this.getLoginState = getLoginState;
  }

  open() {
    const { url, id, w, h } = this;
    this.window = openWindow(url, id, w, h);
  }

  close() {
    this.cancel();
    this.window.close();
  }

  poll() {
    this.promise = new Promise((resolve, reject) => {
      this.interval = window.setInterval(() => {
        try {
          const popup = this.window;

          if (!popup || popup.closed) {
            this.close();
            reject();
            return;
          }

          if (
            popup.location.href === this.url ||
            popup.location.pathname === 'blank'
          ) {
            return;
          }

          resolve({
            loginCode: this.getLoginCode(popup),
            loginState: this.getLoginState(popup),
          });
          this.close();
        } catch (err) {
          console.error(err);
        }
      }, 300);
    });
  }

  cancel() {
    if (this.interval) {
      window.clearInterval(this.interval);
      this.interval = null;
    }
  }

  then(...args) {
    return this.promise.then(...args);
  }

  catch(...args) {
    return this.promise.then(...args);
  }

  static open(...args) {
    const popup = new this(...args);

    popup.open();
    popup.poll();

    return popup;
  }
}

I use Express in server side, and have enabled CORS and Helmet there:

app.use(cors());
app.use(helmet());

I tried to add accounts.spotify.com to CSP but still getting the same error:

app.use(
  helmet.contentSecurityPolicy({
    useDefaults: true,
    directives: {
      'script-src': ["'self'", 'https://accounts.spotify.com'],
    },
  })
);

What should I do to fix the error?

user3132457
  • 789
  • 2
  • 11
  • 29
  • CORS won't help here, instead, you need to avoid trying to access any information from the window, such as it's url. – Kevin B Jun 22 '21 at 19:45

1 Answers1

-1

For security reasons, Javascript in one frame can't access a different frame if it's of a different origin. Check the docs on the same-origin policy.

You probably want to use XHR requests instead to solve your problem.

Joundill
  • 6,828
  • 12
  • 36
  • 50