Search code examples
javascriptfirebasefirebase-authenticationnuxt.jssession-cookies

Sharing Firebase __session cookie in Nuxt between sub domains


Summary: To get a more detailed idea of what I'm trying to do, read my previous post. So briefly I'm trying to create a Firebase __session cookie on my first site (elearning.igeddit.ca) and then sharing and reading that __session cookie with my second site (technical.igeddit.ca)

So I'm using auth.onAuthStateChanged when a user signs into elearning.igeddit.ca with their email and password. I'm using onAuthStateChanged to trigger the cookie creation on log in.

//...
import Cookies from "js-cookie";
//...
async onAuthStateChangedAction(vuexContext, authUser) {
        if (!authUser) {
            console.log("removing session cookie")
            Cookies.remove('__session')
        } else {
            console.log("adding session cookie")
            let idToken = authUser.getIdToken();
            console.log("idToken: ", idToken);
            Cookies.set('__session', idToken, { expires: 0.04166667 })
        }
    },

As you can see by the picture of the console.log, the cookie is being set - at least I'm assuming it's being set correctly. So all seems to be good on the writing side of the __session cookie. session cookie console

When I launch technical.igeddit.ca in localhost (I'm testing both sites in a localhost environment btw) I can see the __session cookie: session cookie at technical.igeddit.ca

The problem I'm now having is that I still can't read the __session cookie on technical.igeddit.ca

//...
import Cookies from "js-cookie";
//....
nuxtServerInit({ req }) {
        console.log("nuxt init...")
        const sessionCookie = Cookies.get('__session')
        console.log("sessionCookie: ", sessionCookie);

        if (!sessionCookie) {
            console.log("no cookie found...")
        } else {
            console.log("there's a session cookie...")
        }
    },

The logs return the following: enter image description here enter image description here

I'm obviously missing something. Thanks for the help.


Solution

  • Looking at the following lines:

    console.log("adding session cookie")
    let idToken = authUser.getIdToken();
    console.log("idToken: ", idToken);
    Cookies.set('__session', idToken, { expires: 0.04166667 });
    

    Here, the __session cookie is defined with an expiry of 1h, but the value is set to idToken - a Promise<string> that will resolve to the ID token of the user.

    To fix this, you need to move the set cookie logic inside of the then handler of the ID token Promise.

    console.log("adding session cookie")
    authUser.getIdToken()
      .then((idTokenJWT) => {
        console.log("idToken: ", idTokenJWT); // TODO: Remove this line
        Cookies.set('__session', idTokenJWT, { expires: 0.04166667 });
      })
      .catch((err) => {
        // TODO: Handle errors
        console.error("Failed to get user ID token/update cookie: ", err);
      });
    

    By default, js-cookie will set the cookie's domain to the current domain (in your case - elearning.igeddit.ca). To make this cookie work on other subdomains, you need to provide the domain argument:

    Cookies.set('__session', idTokenJWT, { expires: 0.04166667, domain: '.igeddit.ca' });
    

    To remove the cookie later, you will also need to specify the same domain parameter:

    Cookies.remove('__session', { domain: '.igeddit.ca' });
    

    You could also specify new values for the default attributes when you import the library:

    import RawCookies from "js-cookies";
    const Cookies = RawCookies.withAttributes({ domain: '.igeddit.ca' });
    // ...
    Cookies.set('__session', idToken, { expires: 0.04166667 });
    // ...
    Cookies.remove('__session');
    

    Instead of expiring the cookie in 1 hour, consider using the expiry of the token itself.

    console.log("adding session cookie")
    authUser.getIdTokenResult() // note: API change
      .then((idToken) => {
        console.log("idToken: ", idToken); // TODO: Remove this line
        Cookies.set('__session', idToken.token, { expires: new Date(idToken.expirationTime) });
      })
      .catch((err) => {
        // TODO: Handle errors
        console.error("Failed to get user ID token/update cookie: ", err);
      });