Closed mmmulani closed 1 year ago
Hello, today 16.1 version was released, and this problem still continues. Can you help us with this problem, please?
Hi folks, we're still diagnosing the particular issues at play, but it appears that signInWithRedirect
still works as expected if you update your authDomain
parameter in the Firebase app config to match the URL your site is hosted on (this works if you're on Firebase Hosting).
A full write-up of potential mitigations can be found in https://github.com/firebase/firebase-js-sdk/issues/6443#issuecomment-1187798276
hey thanks for the update.
just to save anyone else reading this some time, while we have the authDomain
parameter set up correctly, we do not use Firebase Hosting and thus are still running into this issue. (I tried to follow the mitigations linked but we already have all those configs set up correctly and notably, signInWithRedirect
works for us on Firefox.)
Yes, sorry I should have noted that that comment was for Firefox, but we believe it may be a similar underlying mechanism that's causing the user not to be populated.
Mitigation 3 from that list does not use signInWithRedirect
or signInWithPopup
and will get around this issue for you.
You can sign in to the OAuth provider manually, then simply authenticate with Firebase at the end using signInWithCredential(). For example, with Google: https://firebase.google.com/docs/auth/web/google-signin#advanced:-handle-the-sign-in-flow-manually
We are also experiencing this error. Using signInWithRedirect
vs signInWithPopup
did not help, we are seeing the same issue
I believe this is related to this [prematurely] closed issue: https://github.com/firebase/firebase-js-sdk/issues/6636
Unfortunately the instructions^ for manually signing in only seem to apply to GoogleProvider, which does not pertain to us
Can confirm this is happening on 16.1 Safari, including iOS 16.1. The suggested solutions all have flaws:
signInWithPopup
does not work on mobile web browsers, you must use signInWithRedirect
Does it look like there are any other solutions in sight? Can we switch to some cookie-based authentication possibly? As 16.1 rolls out this is going to affect a huge number of users. Thanks! cc @sam-gc @prameshj
This likely has the same cause as #6443.
Does it look like there are any other solutions in sight? Can we switch to some cookie-based authentication possibly? As 16.1 rolls out this is going to affect a huge number of users. Thanks!
We are exploring a few options for a longer-term fix. Cookie-based authentication will run into this same limitation since the oauth helper code is in \<project>.firebaseapp.com domain (or the firebase hosting domain, if specified in the authDomain parameter). If this domain is different from the domain where the app is running, there is a cross-origin storage access to complete sign in, which gets blocked by some browser policies.
Note that the FirebaseUI Web issue(https://github.com/firebase/firebaseui-web/issues/977) is different and presents with a "TypeError: Right side of assignment cannot be destructured" in the console.
Curiously on iOS 16.1, Chrome and Firefox and Brave also suffer the same issue as Safari!
signInWithPopup
does bypass the problem on all of those browsers too. So, whatever long-term fix is determined, it hopefully applies across all of iOS.
(Latest versions of Chrome and Firefox and Brave on MacOS still function using signInWithRedirect
.)
Curiously on iOS 16.1, Chrome and Firefox and Brave also suffer the same issue as Safari!
signInWithPopup
does bypass the problem on all of those browsers too. So, whatever long-term fix is determined, it hopefully applies across all of iOS.(Latest versions of Chrome and Firefox and Brave on MacOS still function using
signInWithRedirect
.)
There is only one actual browser on iOS: Safari. The other browsers use Safari beneath their own UI/UX.
Hello, is anyone still meet this issue ? since on my environment, I cannot meet in that means reproduce this phenomenon iOS 16.1 and safari with iPhone 14 pro
We are exploring a few options for a longer-term fix. Cookie-based authentication will run into this same limitation since the oauth helper code is in
.firebaseapp.com domain (or the firebase hosting domain, if specified in the authDomain parameter). If this domain is different from the domain where the app is running, there is a cross-origin storage access to complete sign in, which gets blocked by some browser policies.
@prameshj: If you want a privacy engineer at Mozilla to talk to, I can chat about some of these options!
Now that Safari 16.1 is released, this is affecting users. Are there any manual work arounds (like implementing the party flow not using the SDK) that we could implement?
Also if there is anything I can help with testing, let me know.
Ok. Been doing some digging into this and I can confirm that signInWithPopup
works exactly as expected as mentioned above. It was mentioned above that this doesn't work on mobile, this is untrue. It opens up another page where you login and it takes you back to the previous window after they have authed. We have a convoluted setup that is a bit more complex that simple popup on a page, and this was not an issue to implement.
I think the one thing that catches people out when implementing signInWithPopup
is that they initiate it in a way that isn't the direct result of a user interaction. Browsers will block popups unless they are created as a direct result of an action from the user. I.e. put it in the click handler and you won't have an issue.
Does signInWithPopup
work in native app web views? I have to assume it does not, but maybe someone figured it out.
@galaxyblur we have tried to use signInWithPopup
with web views for our mobile apps and it did not work for us. However I can also confirm that signInWithPopup
was our workaround for the browser.
Ok. Been doing some digging into this and I can confirm that
signInWithPopup
works exactly as expected as mentioned above. It was mentioned above that this doesn't work on mobile, this is untrue.
Hmm... I'm pretty sure some mobile web browsers, like Chrome iOS, block popups by default, even when they are the result of an action from the user. Or at least there is a setting to do this. Even if that's not the case, there's still other pitfalls: signInWithPopup will not work with in-app web views, and it can fail for a variety of reasons even on desktop — for example an aggresive adblocker.
Our strategy is to try signInWithPopup
, and if that fails with error code POPUP_BLOCKED
, we fallback to signInWithRedirect
. signInWithRedirect
is a failsafe that can be invoked for all sorts of odd reasons/edge cases.
You can prompt your users to sign in with their Google Accounts either by opening a pop-up window or by redirecting to the sign-in page. The redirect method is preferred on mobile devices.
@prameshj, do you or the Firebase team have an estimate/idea of if there is a fix for this in the short term? Any updates are appreciated — if there is no short-term fix on the horizon, our team needs to seriously consider implementing the OAuth providers ourselves, and only using Firebase SDK to get a FIrebase token (suggestion 3 of https://github.com/firebase/firebase-js-sdk/issues/6443#issuecomment-1187798276). This is obviously a fairly large resource commitment, so we'd like to know if there's any other possible solutions in the works...
I 2nd that -- knowing whether a fix in possible in the near term would help a great deal.
I also would like to know when a fix is planned.
If it comes to having to re-implement apple/Google/Twitter auth manually via OAuth, maybe this can be shared among the community here so everyone here can benefit from it.
Hi all, thanks for your patience on this issue.
Are there any manual work arounds (like implementing the party flow not using the SDK) that we could implement? Also if there is anything I can help with testing, let me know.
In addition to the workarounds listed here, there is the option to self-host the signin helper code.
Here is a flowchart to determine the most suitable mitigation depending on the setup:
Self-Hosting the widgets:
Note: This approach will not work for Apple sign in and SAML. Please use a different mitigation for those.
The signInWithRedirect
flow starts by redirecting from your app domain to the
domain specified in the authDomain
parameter in firebase config
("authDomain
hosts the sign-in helper
code that redirects to the Identity Provider, which, on success, redirects back
to the app domain.
When authentication flow returns to your app domain, the browser storage of the sign-in helper domain is accessed. Hosting the helper code in your app domain eliminates the cross-origin storage access, which otherwise gets blocked by browsers.
Hosting the helper code has the following steps:
Download the files to host from the <project>.firebaseapp.com
location by
executing the following commands:
mkdir signin_helpers/ && cd signin_helpers
wget https://<project>.firebaseapp.com/__/auth/handler
wget https://<project>.firebaseapp.com/__/auth/handler.js
wget https://<project>.firebaseapp.com/__/auth/experiments.js
wget https://<project>.firebaseapp.com/__/auth/iframe
wget https://<project>.firebaseapp.com/__/auth/iframe.js
2) Host the above files under your app domain. Ensure that your web server can
respond to https://<app domain>/__/auth/<filename>
.
Here is a sample server implementation that downloads and hosts the files - https://go.dev/play/p/qnI8PEPwME6
3) Follow the steps in this comment(option 2) to update authorized redirect_uri and your authDomain. Once you redeploy your app, the cross-origin storage access should no longer happen.
We will document these mitigation options in the official docs and drop a link here soon. We are investigating options for a more permanent solution, however, we do not have an ETA right now.
Download the files to host from the
.firebaseapp.com location by executing the following commands:
Looks like there is a missing iframe
html file from this list as the redirect back also loads /__/auth/iframe?apiKey=...
Also FYI - experiment.js
should be experiments.js
mkdir signin_helpers/ && cd signin_helpers
wget https://<project>.firebaseapp.com/__/auth/handler
wget https://<project>.firebaseapp.com/__/auth/handler.js
wget https://<project>.firebaseapp.com/__/auth/experiments.js
wget https://<project>.firebaseapp.com/__/auth/iframe
wget https://<project>.firebaseapp.com/__/auth/iframe.js
Thanks! fixed.
Download the files to host from the
.firebaseapp.com location by executing the following commands...
Out of curiosity, if we are self-hosting. I wonder if setting up a webserver proxy to these files would be a slightly more long-term/resilient option, rather than downloading and hosting the files directly (and risking them going out of date.)
E.g.: Forwarding https://customdomain.com/__/auth/
-- to --> https://<project>.firebaseapp.com/__/auth
nginx example config:
location /__/auth {
# Firebase Auth Helper Proxy Forwarding Config
allow all;
proxy_http_version 1.1;
proxy_pass https://<project>.firebaseapp.com;
}
If so, additionally, I wonder if this is something that might be added as an optional firebase configuration anyway (thus removing the need for the <project>.firebaseapp.com
domain redirect entirely?
EDIT: On further inspection, I see that's what your example server script is essentially doing. And I've now verified this and it works.
Hi @lincolnthree , you are right.. Setting up a reverse proxy on your app domain to route "/auth" requests to https://
You're right.. the example script does almost the same thing, but it does cache the files locally, but can be modified to sync the files periodically or proxy to the https://<project>.firebaseapp.com
destination.
@prameshj
Is there a work around for SAML? This is the flow we care about.
As others have mentioned the signInWithPopup
does not work on mobile. Native app webviews typically block the popups.
The list of mitigations have been published at https://firebase.google.com/docs/auth/web/third-party-storage-mitigation
Is there a work around for SAML? This is the flow we care about.
@sww314 if you are not on Firebase Hosting, then https://firebase.google.com/docs/auth/web/third-party-storage-mitigation#mitigation_3_proxy_auth_requests_to_firebaseappcom should work.
@prameshj we have many customers that use their own SSO providers with our stack of GCP's identity toolkit and changing the redirect domain is not really a valid option for us since we will need all the customers to do so as well, is there an ETA for supporting this issue without a mitigation?
Is there any reason there is no "Cookie" storage? Cookie can work across domains (same sub domains.. we have app.xxx.com and accounts.xxx.com). Are there any security reasons not to implement such solution? Perhaps implementing it would solve the problem?
Eg: Save user:
const userJson = JSON.stringify(currentUser.toJSON())
saveToCookie(userJson);
Load user:
const userData = JSON.parse(loadFromCookie())
const user = new firebase.User(userData, userData.stsTokenManager, userData)
firebase.auth().updateCurrentUser(user)
This work around does work for SAML. https://firebase.google.com/docs/auth/web/third-party-storage-mitigation#mitigation_3_proxy_auth_requests_to_firebaseappcom
However it requires:
Reply URL
. Google Provider
, we have to update the Authorized Redirect URIs
We use a Google Load Balancer (classic). Proxying the requests was not obvious, but you can do it with: https://cloud.google.com/load-balancing/docs/negs/internet-neg-concepts https://cloud.google.com/load-balancing/docs/https/setting-up-https-external-backend-internet-neg#gcloud_1
If you are using Next.js, you can solve this by adding following rewrite to your next.config.js
file:
/** @type {import('next').NextConfig} */
module.exports = {
rewrites: [
{
source: "/__/auth/:path*",
destination: `https://${firebaseAuthDomain}/__/auth/:path*`,
}
]
}
Note: Don't forget to (1) update authDomain
in the firebase config and (2) add the new Redirect URI in Google Cloud Console.
Check this doc for more details: https://firebase.google.com/docs/auth/web/third-party-storage-mitigation
Since no one talks about the error message causing the issue of signInWithRedirect
, I will address it here (also mentioned #6831 ).
Unrecognized Content-Security-Policy directive 'require-trusted-types-for'.
Hopefully this helps!
If anyone could offer a suggestion for SAML + GAE hosting, that would be fantastic.
We are on GAE, and we fixed it. What we had:
app.example.com
, served by google app engineauth.example.com
, served by firebase hostingWe fixed it essentially by using this variant of mitigation #3:
app.example.com
project-id.firebaseapp.com
dispatch.yaml
we mapped URL "*/__/auth/*"
to the GAE reverse proxy aboveapp.example.com
, which screwed up the sign with redirect flow, but in iOS you can add exceptions, so in file apple-app-site-association
we added the exception "NOT /__/auth/*"
This way, all interactions with firebase are now happening from the domain app.example.com
and everything works as before.
In android instead, since you cannot add exceptions, we are still using app.example.com
and auth.example.com
For those of you using Azure App Service on a Windows server to host your app and have this issue using signInWithRedirect() with mobile browsers, here are the steps to resolve using mitigation #3.
<rule name="FirebaseAuthRewrite" stopProcessing="true">
<match url="^__/auth/handler.js" />
<action type="Rewrite" url="https://<yourproject>.firebaseapp.com/__/auth/handler.js" appendQueryString="true" logRewrittenUrl="false" />
</rule>
<rule name="FirebaseAuthRewriteExperimentsJs" stopProcessing="true">
<match url="^__/auth/experiments.js" />
<action type="Rewrite" url="https://<yourproject>.firebaseapp.com/__/auth/experiments.js" appendQueryString="true" logRewrittenUrl="false" />
</rule>
<rule name="FirebaseAuthRewriteIframeJs" stopProcessing="true">
<match url="^__/auth/iframe.js" />
<action type="Rewrite" url="https://<yourproject>.firebaseapp.com.com/__/auth/iframe.js" appendQueryString="true" logRewrittenUrl="false" />
</rule>
<rule name="FirebaseAuthRewriteHandler" stopProcessing="true">
<match url="^__/auth/handler" />
<action type="Rewrite" url="https://<yourproject>.firebaseapp.com/__/auth/handler" appendQueryString="true" logRewrittenUrl="false" />
</rule>
<rule name="FirebaseAuthRewriteIframe" stopProcessing="true">
<match url="^__/auth/iframe" />
<action type="Rewrite" url="https://<yourproject>.firebaseapp.com/__/auth/iframe" appendQueryString="true" logRewrittenUrl="false" />
</rule>
You can use a wildcard instead so you have just one rule - but I wanted to list them explicitly, so it is clearer what files are involved. In our case, we are using a Node app so there are additional rules that capture any URLs and send to Node. If this is the case, then you must use stopProcessing="true" as in the above example. If not, you can set that value to false which is default.
<?xml version="1.0" encoding="UTF-8"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<system.webServer>
<proxy xdt:Transform="InsertIfMissing" enabled="true" preserveHostHeader="false" reverseRewriteHostInResponseHeaders="false" />
</system.webServer>
</configuration>
After both the web.config and applicationHost.xdt are configured, you can stop and start your app service. Any changes to either file require a restart of the app service to take effect.
Finally, change the authDomain in your Firebase config to yourmainappdomain.com to match where your app is hosted. Now signInWithRedirect() will work on mobile browsers since no third-party storage is used.
I just wanted to call out that the issue noted by @sww314 https://github.com/firebase/firebase-js-sdk/issues/6716#issuecomment-1320593233 "our customers update the Reply URL
." is pretty painful when you have a significant number of existing customers who you've integrated your site using SAML/OIDC with (taking the common pattern of having each customer create a custom app in their IdP as opposed to publishing an app in Okta/Auth0/Google Workspace/etc). Unless you take extra steps, all of them would need to update Reply URL
in lockstep, exactly as your site deploys mitigation #3
, otherwise their users will be locked out. That's just not a realistic path.
We ended up calling .deleteApp()
and re-initializing with the proper authDomain
just before .signInWithRedirect()
and .getRedirectResult()
, depending on the customer who was trying to sign in, so that we'd redirect to the same Reply URL
in their IdP, and can migrate each customer individually.
This was a pain and could have been avoided if Firebase provided us some control over *.firebaseapp.com/__/auth/*
. For example, configuring it to redirect/pass it's data on to oursite.com/__/auth/*
would seamlessly fix Safari for all our customers, without the need to manually migrate each one to the new Reply URL
. I'm disappointed this this sort of control isn't available to us as having an existing customer base to migrate seems like a common scenario.
@mmmulani request to remove "beta" from the issue title, since Safari 16.1 isn't in beta anymore (so that the impact of this bug is better indicated).
@mmmulani request to remove "beta" from the issue title, since Safari 16.1 isn't in beta anymore (so that the impact of this bug is better indicated).
good point, thanks
Finding a caniuse.com sort of resource for determining if/when other browsers will be impacted was tough (essentially this question https://github.com/privacycg/storage-partitioning/issues/12). Best resource appears to be https://github.com/cookie-status/cookie-status-dev, but it doesn’t capture the nuance that storage partitioning also applies to sessionStorage in Safari.
It seems this issue could suddenly start occurring in Firefox if firebaseapp.com ends up on their known tracker list.
Still happens on Safari 16.2 AFAIK.
@prameshj Is there a more long term solution being worked on or do we need to settle for the mitigations described above? It is currently very painful to switch authDomain
when you have several customers relying on SAML SSO with another Reply URL configured.
Hi folks, thanks for your patience on this issue.
Keeping the auth helpers on the same domain as the main app is the best way to future-proof the signInWithRedirect flow. As a result, the mitigations in the doc are best-practices for using signInWithRedirect, going forward. We will update the signInWithRedirect docs to reflect this as well.
The popup flow works differently since the main app window is always present and hence the necessary information can be passed along without relying on web storage. All other mitigations aim to keep the auth helper and the main app in the same domain.
Hence, changing the value of authDomain
is necessary, unfortunately.
✅ For those who faced with this problem in latest Safari's (16+) there is workaround:
The idea is to proxy your Sign-in requests:
https://<your domain name>/__/auth/handler
As an extra information to the discussion: making the mitigation # 1 (https://github.com/firebase/firebase-js-sdk/issues/6443#issuecomment-1187798276) is not working across sub-domains for me on firebase hosting with custom domains for application and one for authentication. The mitigation must be made for each sub-domain.
Overall conditions on my situation:
signInWithRedirect
because popup does not work well on iOS devicesauthDomain
firebase option in all sub-domainsThe fix for me was basically doing the mitigation # 1 for each sub-domain:
This also adds the overhead to update Authorized redirect URIs for each new sub-domain (essentially a new application), but we add new ones rarely. Eventually will probably go with mitigation # 3 and implement communication between subdomains if needed.
Additionally I could not find any HTTP header or privacy sandbox way of allowing the firebase authentication clients to share information between subdomains.
If anyone can share a guide on the steps to take with Vercel hosting, that'd be awesome. (we have a vite based SPA hosted on Vercel hosting)
would need to know
__/auth
files do I need to put in the repositorythanks!
✅ For those who faced with this problem in latest Safari's (16+) there is workaround:
The idea is to proxy your Sign-in requests:
- If you use something like Nginx, just proxy your request like shown in the firebase docs
Sign-in to your Google Cloud Console > APIs > Credentials
- Add your domain to authorised domains
- Add redirect URLs as
https://<your domain name>/__/auth/handler
Does this work with appengine preview URLs?
For the following scenario: Windows server (IIS) (on-premise) singInWithRedirect()
I've solved using mitigation #3
I've created a reverse proxy with following tools (extensions for IIS) ARR URL rewrite
And I've used the rules in this post (thanks for help):
For those of you using Azure App Service on a Windows server to host your app and have this issue using signInWithRedirect() with mobile browsers, here are the steps to resolve using mitigation #3.
- In your app hosted at https://yourmainappdomain.com, in the web.config file located inside the wwwroot folder, add the related rewrite rules in the rules section:
<rule name="FirebaseAuthRewrite" stopProcessing="true"> <match url="^__/auth/handler.js" /> <action type="Rewrite" url="https://<yourproject>.firebaseapp.com/__/auth/handler.js" appendQueryString="true" logRewrittenUrl="false" /> </rule> <rule name="FirebaseAuthRewriteExperimentsJs" stopProcessing="true"> <match url="^__/auth/experiments.js" /> <action type="Rewrite" url="https://<yourproject>.firebaseapp.com/__/auth/experiments.js" appendQueryString="true" logRewrittenUrl="false" /> </rule> <rule name="FirebaseAuthRewriteIframeJs" stopProcessing="true"> <match url="^__/auth/iframe.js" /> <action type="Rewrite" url="https://<yourproject>.firebaseapp.com.com/__/auth/iframe.js" appendQueryString="true" logRewrittenUrl="false" /> </rule> <rule name="FirebaseAuthRewriteHandler" stopProcessing="true"> <match url="^__/auth/handler" /> <action type="Rewrite" url="https://<yourproject>.firebaseapp.com/__/auth/handler" appendQueryString="true" logRewrittenUrl="false" /> </rule> <rule name="FirebaseAuthRewriteIframe" stopProcessing="true"> <match url="^__/auth/iframe" /> <action type="Rewrite" url="https://<yourproject>.firebaseapp.com/__/auth/iframe" appendQueryString="true" logRewrittenUrl="false" /> </rule>
You can use a wildcard instead so you have just one rule - but I wanted to list them explicitly, so it is clearer what files are involved. In our case, we are using a Node app so there are additional rules that capture any URLs and send to Node. If this is the case, then you must use stopProcessing="true" as in the above example. If not, you can set that value to false which is default.
- For Azure, there is one more step in order to enable Application Request Routing (ARR) to handle the proxy. Simply create a file named applicationHost.xdt and add to the SAME level as wwwroot, deployments, etc. (not inside wwwroot). As alternative to FTP, in the Azure console, go to your app service, click Development Tools -> Advanced Tools and choose Debug Console and either CMD or Powershell. This will give you the file explorer where you can create and edit both the web.config and the new applicationHost.xdt at the respective levels. Create and edit the applicationHost.xdt to contain the following:
<?xml version="1.0" encoding="UTF-8"?> <configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"> <system.webServer> <proxy xdt:Transform="InsertIfMissing" enabled="true" preserveHostHeader="false" reverseRewriteHostInResponseHeaders="false" /> </system.webServer> </configuration>
- After both the web.config and applicationHost.xdt are configured, you can stop and start your app service. Any changes to either file require a restart of the app service to take effect.
- Finally, change the authDomain in your Firebase config to yourmainappdomain.com to match where your app is hosted. Now signInWithRedirect() will work on mobile browsers since no third-party storage is used.
Also have a problem, Firebase JS SDK + Angular, redirect flow. angular 14.2.7 Firebase: 9.15.0 @angular/fire: 7.4.1
Added proxy on nginx to firebase application.
Everything works on chrome. On safari, both on Mac and iOs works after second call to getRedirectResult() after successful login redirect. When i build an application with pwabuilder.com:
Already spent 3 days trying to debug, and it is urgent now, can you help?
Is there any way to make it work in a localhost environment while keeping signInWithRedirect
?
To test locally, you need: some way to publicly expose your localhost (like port forwarding on your router, ngrok); and to add that public IP (or ngrok domain) to the list of authorized domains in GCP Identity Platform or Firebase Console.
Describe your environment
Describe the problem
Steps to reproduce:
Try logging in to a site using
signInWithRedirect
. Notably it redirects back to the site without an error, and does not log the user in. CheckinggetRedirectResult
returns a null user.This seems like a severe issue as iOS 16.1 will be released next week and presumably this issue will affect all those iOS users.
Notably there seems to be a workaround of using
signInWithPopup
. It seems to work for us, though it is unclear why.Relevant Code: