Fixing 3rd party cookies issue with Firebase Auth
Tags: webdev, firebase, tutorial, javascript
Published: 2022-05-14 13:04:58

Here's a scenario that might might have happened with you. You develop a great app with Firebase, your app supports log in with Google and other Social Identity providers, it works great when you're testing it, you connect your domain to firebase hosting and ship it and users start coming in, but then some of your users come to you(if you're lucky that some provide feedback) and they say, "I can't log in with Google, I click on the button, it takes me to Google but when it takes me back, nothing". You try to recreate, and you don't see the problem and you probably just mark it as PEBCAK, but you have just lost a potential customer and the culprit:- third party cookies.


## Third Party Cookies
I'm not going to try and explain the concept as you might have heard it enough number of times, so here are some great explanations.

- [dev.to](https://dev.to/voralagas/javascript-interview-3-what-is-a-cookie-why-do-we-need-them-and-what-is-third-party-cookie-122c)
- [DevOwl(where I shamelessly stole the image)](https://devowl.io/2021/first-party-cookies-third-party-cookies-definition/)

### How does Firebase handle OAuth logins
When you first create and app with firebase and enable auth, it creates an auth handler for you which can be accessed through the `_auth/handler` path in the app domain, which is another thing firebase creates for you which is something like "<firebase_app_id>.firebase.app".
The way social login works with firebase is you redirect your users to this handler with the right query params and it takes care of OAuth verification for you, it sends your users to the OAuth provider(Google in our case) and google verifies and sends the user back to this handler.
This handler is managed by firebase and is responsible for a bunch of auth related items like email verification, password reset, etc.
Firebase hosting understands this handler's path and runs the handler instead of taking users to your app as well.

_Note:- This is just a high level view. Don't quote me_.

### Why does this bug appear?
In the initial phase, the app was hosted on the default domain setup by firebase, but when you add your custom domain and send the user to that custom domain, firebase auth still sends the user to the base domain for this handler, making it a **third party**.
For example:- You add a custom domain in firebase hosting:- `app.domain.com` but the handler is located at `<firebase_app_id>.firebase.app/_auth/handler`. When we run `signInWithRedirect`, it still sends the user the `<firebase_app_id>.firebase.app/_auth/handler`, but the user came from `app.domain.com` making `<firebase_app_id>.firebase.app/_auth/handler` a third party.
With the browser scenario changing and 3rd party cookies coming under more scrutiny by users and authorities alike, a lot of browsers now block third parties by default and some users do this on purpose. This causes the browser to apply third party cookie policy on `<firebase_app_id>.firebase.app/_auth/handler`, preventing it from setting cookies and even accessing local-storage through iframe(which is what is happening). This is why some users can't log in, so the problem does not exist between chair and keyboard but between the browser and our app, which makes it our responsibility.

### So how do we fix it

#### Simple answer? 
Ask the user to allow third party cookies 😎
#### Good answer? Make the handler available on `app.domain.com/_auth/handler`, which can be achieved in x easy steps:-
- Update the `authDomain` in firebase config to `app.domain.com`
- Add `app.domain.com` to authorized domains in Firebase Auth page, Firebase Auth -> Sign In methods and scroll down to see list
- Add `app.domain.com/__/auth/handler` to authorized redirect URIs in google cloud console. 
  - Go to google cloud console.
  - Select your firebase project.
  - Go to -> APIs and Services -> Credentials.
  - Edit the "OAuth 2.0 Client IDs"

🎉 Problem solved!