I use firebase for authentication on my website and I want to keep the users auth session active across subdomains.
Unfortunately, firebase uses Local Storage to sto
this is correct. Firebase only supports single host origin sessions. Firebase Auth is looking into supporting cookies. For now there is no easy solution for this. Feel free to request this feature at the Firebase forum: https://groups.google.com/forum/#!forum/firebase-talk
For now, if you really need this, here is one relatively easy option: Create an endpoint that takes a Firebase ID token and basically returns a custom token for its underlying user (you would need to use the Admin SDK to do this, you verify then ID token, get the user UID and then mint a custom token). The subdomain where the user signed in would pass the ID token to the other subdomain where the user is still not authenticated (you can use iframe cross origin postMessage to pass it, or just save that ID token in a *.domain.com policy). The custom token can then be used to signInWithCustomToken with the custom token, effectively signing in the same user on this page.
This is risky though as the endpoint could expose a vulnerability (it transforms a short lived token to an indefinite one). If the ID token is leaked, an attacker can basically sign-in as the user exploiting this endpoint.
After having spent much longer then I intended to getting single-sign-in working across subdomains, I wrote up a blog post detailing how to accomplish this.
We have three applications at different domains.
accounts.domain.com
app1.domain.com
app2.domain.com
We have three Firebase Functions
...cloudfunctions.net/users-signin
...cloudfunctions.net/users-checkAuthStatus
...cloudfunctions.net/users-signout
In order to sign in:
accounts.domain.com
app/users-signin
cloud function which verifies the information and, if valid, sets a signed __session
cookie which contains the user's UID and returns a success indication to the client./users-checkAuthStatus
cloud function which looks for the signed __session
cookie, extracts the user UID, and uses the UID and the firebase-admin SDK to mint a custom auth token which it returns to the client.app1.domain.com
, the app first checks to see if the person is already signed in using the firebase javascript SDK.
/users-checkAuthStatus
cloud function which looks for the signed __session
cookie and returns a custom auth token to the client if a valid __session
cookie is found.
Again, this is a high level overview which ignores issues like cross-site-scripting attacks, actually signing out, etc. For more information, check out the blog post.
I used NGINX to load diffrent web apps which want to share same firebase auth which works out of box in firebase if domain or sub domain is same.
server {
root /var/lib/jenkins/workspace/app/dist;
index index.html index.htm index.nginx-debian.html;
server_name app.com; # example
location /app1 {
alias /var/lib/jenkins/workspace/app1/dist;
try_files $uri $uri/ =404;
}
location /app2 {
alias /var/lib/jenkins/workspace/app2;
try_files $uri $uri/ =404;
}
location /static {
alias /var/lib/jenkins/workspace/build/static;
try_files $uri $uri/ =404;
}
location ~ /\.ht {
deny all;
}
listen 80;
listen [::]:80;
}
The iframe doesn't work anymore for Safari because it doesn't let the iframe's origin page access its own indexeddb anymore. That means you cannot get the id token and onAuthStateChanged
will always return null
.
We've implemented another solution where we store a custom token into a secure cookie along with a redirect information, redirect the user to the other domain, use the cookie to sign in or sign out the user, delete the cookie and redirect him again to the location stored in the cookie.
That works for iOS and Desktop Safari again. But it only works if it's on the same domain so that both subdomains are going to have access to that cookie.