skip to Main Content

In a Nuxt3 project I am using Firebase auth. I have created the following middleware to protect not authenticated routes:

export default defineNuxtRouteMiddleware((to, from) => {
    const { $auth } = useNuxtApp();
    const { $localePath } = useNuxtApp();

    if(!$auth?.currentUser?.uid){
        return navigateTo({ path: $localePath({name: 'auth-login'}) });
    }
});

Everything is working fine at first. I login, then I navigate in the application. But when I refresh the browser even thou I haven’t logged out from the user profile I am redirected to the login page.

The $auth?.currentUser?.uid is returning null. I am storing the logged in user data in a firebaseUser store. However the same problem occurs when I try to get the state in the middleware. It tells me that I am not logged in and redirects me to the login page, but the user data is stored in the store.

How can I make the middleware to detect if I am logged in on refresh of the browser page?

This is my firebaseAuth:

import { initializeApp } from "firebase/app"
import { getAuth } from "firebase/auth"

export default defineNuxtPlugin(nuxtApp => {
    
    const firebaseConfig = {
        apiKey: process.env.FIREBASE_API_KEY,
        authDomain: process.env.FIREBASE_AUTH_DOMAIN,
        projectId: process.env.FIREBASE_PROJCT_ID,
        storageBucket: process.env.FIREBASE_STORAGE_BUCKET,
        messagingSenderId: process.env.FIREBASE_MESSAGING_SENDER_ID,
        appId: process.env.FIREBASE_MESSAGING_SENDER_ID,
        measurementId: process.env.FIREBASE_MEASURMENT_ID,
    };

    // Initialize Firebase
    const app = initializeApp(firebaseConfig);

    // Init user
    initUser();

    // Get auth
    const auth = getAuth();

    nuxtApp.vueApp.provide('auth', auth);
    nuxtApp.provide('auth', auth);
})

And this is my initUser logic in useFirebase:

export const initUser = async () => {

    const auth = getAuth();
    const firebaseUser = useFirebaseUser();
    firebaseUser.value = auth.currentUser;

    onAuthStateChanged(auth, (user) => {
        firebaseUser.value = user;
    });
}

And my store:

export const useFirebaseUser = () => useState('firebaseUser', () =>{});

2

Answers


  1. Chosen as BEST ANSWER

    I found some solution to the problem:

    Not the "correct" solution but I got it working by checking for a cookie instead of waiting for the firebase initialization.

    When the user creates and account or signs in, I set a cookie in the method with the value of the firebase user information:

      const response = await signInUser(email, password);
    
      const userCookie = useCookie("userCookie");
    
      userCookie.value = response;
    

    Then in the plugins/auth.ts, I check for the cookie instead of the auth.currentUser:

    addRouteMiddleware('auth', () => {
        const userCookie = useCookie("userCookie");
    
        if (!userCookie?.value?.user) {
            return navigateTo('/login')
        }
    
    })
    

    When the user signs out, I just set the cookie value to empty in the signOut method:

    const userCookie = useCookie("userCookie");
    userCookie.value = null;
    

    I also do the same but to redirect a signed in user away from the sign-in page:

    addRouteMiddleware('signedIn', () => {
            const userCookie = useCookie("userCookie");
    
            if (userCookie?.value?.user) {
                return navigateTo('/')
            }
        })
    

  2. Try adding async to your plugin and middleware as following:

    import { initializeApp } from "firebase/app";
    import { getAuth } from "firebase/auth";
    export default defineNuxtPlugin(async (nuxtApp) => {
    const firebaseConfig = {
      // Your Firebase configuration here
    };
    
    // Initialize Firebase
    const app = initializeApp(firebaseConfig);
    
    // Get auth
    const auth = getAuth();
    
    // Wait for Firebase authentication to initialize
    await new Promise((resolve) => {
      onAuthStateChanged(auth, (user) => {
        if (user) {
          resolve(user);
        } else {
          resolve(null);
        }
      });
    });
    
    nuxtApp.vueApp.provide("auth", auth);
    nuxtApp.provide("auth", auth);
    

    });

    and to your middleware as well so it looks like:

    export default defineNuxtRouteMiddleware(async (to, from) => {
      const { $auth } = useNuxtApp();
      const { $localePath } = useNuxtApp();
    
      // Wait for Firebase authentication to initialize
      await new Promise((resolve) => {
        $auth.onAuthStateChanged((user) => {
          if (user?.uid) {
            resolve();
          } else {
            navigateTo({ path: $localePath({ name: "auth-login" }) });
          }
        });
      });
    });
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search