Using `signInWithRedirect` with an `authDomain` different than the domain of the app does not complete the sign in (and reports no errors)
Operating System
Ubuntu 20.04 LTS
Browser Version
Chrome 119.0.6045.123 / Firefox 119
Firebase SDK Version
10.7.0
Firebase SDK Product:
AppCheck, Auth
Describe your project's tooling
Next.js (React app), using pages router. Deployed on Vercel.
Describe the problem
I'm migrating Firebase signInWithPopup to signInWithRedirect.
If I don't implement the best practices listed here, the login works fine on Chrome (but not on Firefox and Safari as the documentation states). Implementing the Option # 3 of the documentation (which changes the authDomain of Firebase's configuration to point to our servers, and adds a proxy to rewrite the URLs to Firebase's domain), makes this work on all browsers on my dev environment (where I use a real Firebase project, not an emulation).
The issue happens on the staging environment, where I have different deployments (that are deployed on each PR, with unique URLs), that all point to the main staging URL as the authDomain (let's call it "www.staging.com" ). As they are all unique URLs I cannot allow them all in Google's OAuth list, which is the reason they all point to "www.staging.com", instead of "www.randomUrl123.com" (as an example of one of the PR deployments).
Unfortunately, in the PR deployments, the sign in does not succeed on "www.randomUrl123.com". It first redirects to "www.staging.com" as expected, then to Google (to perform auth), and then redirects back to "www.randomUrl123.com", but no sign in happens, and getRedirectResult returns null instead of throwing an error. The browser console is also empty, so I'm not really sure how to debug this.
The reason I'm filing this as a bug is that the console does not report any issues, the browser tab only has requests with statuses 200 or 302, and getRedirectResult returns null instead of an error. I think we should get some kind of error here to help us debug where this sign in attempt failed.
There is no way for me to allow all the possible URLs like "www.randomUrl123.com" on Google's OAuth, so I must find a way to ensure this works through "www.staging.com"
Steps and code to reproduce issue
On signIn button:
const auth = getAuth();
signInWithRedirect(auth, provider); // The provider I'm testing is Google's OAuth
On _app.tsx:
useEffect(() => {
;(async () => {
const auth = getAuth();
try {
const res = await getRedirectResult(auth)
console.log(res)
} catch (err) {
console.log(err)
}
})()
}, [])
On the dev environement, this resolves to the UserCredentialImpl object, but on "www.randomUrl123.com" this always return null, instead of an error (even though the sign in did not succeed).
I confirmed the issue is caused by using an authDomain different from the domain the app is hosted to, as I changed the authDomain on the staging environment to be "www.randomUrl123.com" and the sign in succeeded on "www.randomUrl123.com" . Given what I mentioned above, I would expect to see the following:
- An error that states sign in could not be completed, and why
- Why it did not work, and how can we make it succeed (note that I cannot allow all the possible URLs, so there must be a way to make sign in work when redirecting to a different
authDomain)
I couldn't figure out how to label this issue, so I've labeled it for a human to triage. Hang tight.
@nicolassanmar I have the same issue, this prevents me signing in with Google on localhost for testing my app locally. Temporary workaround that worked for me is using signInWithPopup instead of signInWithRedirect, that method works as expected on localhost too.
Hi, thank you for filing this issue.
Why it did not work
In your case, “staging.com" is the authDomain, so it is cross origin compared to “www.randomUrl123.com”. This means login cannot succeed because “www.randomUrl123.com” will try to read session storage of “www.staging.com” which is disallowed.
how can we make it succeed
The only to make it succeed is to disable third-party storage partitioning on Chrome. The steps are:
- Open Chrome
- Visit chrome://flags/#third-party-storage-partitioning
- Setting the "Experimental third-party storage partitioning" status to "Disabled"
But, the best practice is to keep all the domains (the authDomain and the app) to be the same origin. One way to do that is to keep "randomapp.com" a top-level domain. Then use "staging.randomapp.com" as authDomain with the main deployment at "randomurl1.randomapp.com". This is just one approach. You can follow any approach to keep everything on the same origin - https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy.
@NhienLam Thanks for your response! Unfortunately, having both deployments under the same top level domain did not work either. I don't want to disable the security configuration in my browser, so disabling third-party storage partitioning is not an option.
Following the best practice, I have "staging.vercel.app" (not the real URL, but real url is under .vercel.app as well ) as the authDomain. If I try to sign in from "randomUrl123.vercel.app" I experience the same issue (no errors, but no sign in).
According to the documentation, "siblings" are not considered as same origin (as they have different hosts: https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy#definition_of_an_origin).
Given this, and given how popular Vercel is, is there really no way of enabling signInWithRedirect on the random URLs that Vercel generates?
Given this, and given how popular Vercel is, is there really no way of enabling signInWithRedirect on the random URLs that Vercel generates?
Currently, there is no way to do this other than disabling third-party storage partitioning on Chrome. We will make this a feature request and put it on our radar, but we're unable to promise a timeline right now.
Currently, there is no way to do this other than disabling third-party storage partitioning on Chrome. We will make this a feature request and put it on our radar, but we're unable to promise a timeline right now.
@NhienLam Thanks for confirming my suspicions and for considering this as a feature request. I'm eager to see included in the future!
A possible implementation should be to share data from the embedded iframe to the parent using something like window.postMessage()
@NhienLam any guidance on how to make signInWithRedirect work with localhost for development without disabling the global security feature? This was working fine for us until recently.
In my case I am trying to setup cicd on web.app with firebase hosting github action. I don't know of a way to feed in the auth domain generated by firebase hosting github action. If I don't feed it properly I am unable to use signInWithRedirect for the pr environment @NhienLam
@jb4e Unfortunately, there's currently no way to make signInWithRedirect work with localhost without disabling third-party storage partitioning.
@mrsylerpowers Could you try setting the authDomain to be location.hostname if it’s in cicd environment?
I can but the authDomain for google authentication doesn't accept wildcards so when trying to sign in it fails
@NhienLam
@mrsylerpowers can you try adding your redirect url to Authorized redirect URIs and your domain to Authorized JavaScript origins? You can find both under cloud console credentials.
Hello @Xiaoshouzi-gh, I can not as I get a new deployed url with each pr that is created. I am using firebase hosting github action which for every deployment creates a new domain for every pr and so as soon as I add it it will be expired. example urls: http://pr-334-prtitleplusextranumbers-332434-mygcpprojectid.web.app http://pr-366-prtitleplusextranumbersextratitle-9812893-mygcpprojectid.web.app