'CORS issues with window.open() and OAuth2
I'm running a site that uses SharedArrayBuffer
(ffmpeg wasm) which strictly requires CORS (and/or site isolation), AND a Discord oauth2 workflow. After not looking at the site since earlier this year, I found out that it no longer works on the latest version of Chrome. Eventually I figured out that the problem with the Discord oauth flow was related to CORS.
When using window.open()
, (same-origin) CORS will prevent your site from interacting with said new window if it's on another domain (if I understand it right). Checking the window promise returns that the window has closed (window.closed == true
), even thought it hasn't.
I signed up for Origin Trials (hoping that same-origin-allow-popups
actually works soon). That did fix the Discord part of the flow. Checking the window promise returns normal. BUT, once I get redirected back to my own site, it once again claims the window is closed (before I can get the oauth code).
Why would CORS prevent me from reading my own site? Is it because the previous document.domain
was set to discord.com
?
Does anyone know of any good ways to troubleshoot this kind of problem? CORS errors are common, but there are no CORS errors, just window.closed == true
.
Solution 1:[1]
Short Answer: Check the Referer
(spelling error is intentional) header in your request and response. New Chromium based browsers (Chrome, Chromium and MS Edge) would return the URL to the origin due to its strict-origin new default policy.
There are multiple ways you can set the appropriate policies. I would not recommend using blanket "no-referrer" this could potentially be risky. "no-referrer-when-downgrade" could be a safer option. Once this policy is set either programmatically or via configuration of your app, the browser will examine and send the redirect appropriately.
Long Read: In a nutshell chromium has enhanced the security, policy so unless referrer policy is defined in the request header, chromium the redirect would go to the source of origin.
I ran into a similar issue where the redirection of oauth and back to the app would work as expected in IE but it would not work in the Chromium based browsers that is (Chrome, Chromium and MS Edge). Upon successful redirection from oauth provider, the redirection would go to the origin host.
Here was my scenario
www.hostA.com (Origin)
www.hostB.com/search/product/123 (CORS destination)
www.oauth-provider.com (OAuth Provider)
Both hostA and hostB are behind the oauth authentication. So when hostA is opening a request to hostB, the browser is setting the default policy "strict-origin" hence the referrer is added to the header which is "hostA" and redirects it to OAuth so user can supply credentials and Multi factor authentication etc.
When auth-provider receives the requests along with the policy header, it does the authentication and upon successful authentication it redirect it back to the browser along with original headers. Now browser looks at the referrer hence the URL becomes www.hostA.com/search/product/123
instead of www.hostB.com/search/product/123
, effectively falling back to the original request while keeping the rest of the URL intact.
Solution: Setting the correct referrer policy on the originating application would fix this issue. In my case it was a JavaScript Angular and specifying referrer policy in the window.open as a parameter worked. However the policy can be defined/modified variety of ways like security filters, interceptors proxies etc depending whatever option is the safest.
Examples:
- for JavaScript: https://developer.mozilla.org/en-US/docs/Web/API/Window/open#noreferrer
- Java Spring: https://docs.spring.io/spring-security/site/docs/5.2.0.RELEASE/reference/html/default-security-headers-2.html#Referrer%20Policy
Some additional reading that helped me find this tricky issue —
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | sideshowbarker |