0

I have a similar problem like this one: https://github.com/nuxt-community/firebase-module/issues/252

However, I tried the proposed solution but I am unsure if I did it correctly, thus posting here for help:

Here's my problem: When using middleware, the user store object is coming back as null if I try to access a page directly such as typing in the URL vs navigating to it.

There is no problem when navigating, but the issue is in directly accessing a page by typing in the URL in the browser window or doing a hard refresh. My use case is trying to prevent a signed in user from accessing the login page (or sign up page), thus I thought I'd write a middleware like so but console logging it shows user is null on direct page access and hard refresh.

middleware/auth

export default function ({ app, store, redirect }) {
  console.log('user?', store.state.user.currentUser)
}

I've followed the Auth SSR tutorial, but perhaps I am making a mistake somewhere. Can someone help me get this configured properly?

nuxt.config.js:

export default {
  vue: {
    config: {
      productionTip: false,
      devtools: true
    }
  },
  publicRuntimeConfig: {
    baseURL: process.env.BASE_URL || 'http://localhost:3000'
  },
  privateRuntimeConfig: {},
  head: {
    htmlAttrs: {
      lang: 'en'
    },
    title: 'pixstery',
    meta: [
      { charset: 'utf-8' },
      { name: 'viewport', content: 'width=device-width, initial-scale=1' },
      { hid: 'description', name: 'description', content: '' }
    ],
    link: [{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }]
  },

  // Global CSS (https://go.nuxtjs.dev/config-css)
  css: [],

  // Plugins to run before rendering page (https://go.nuxtjs.dev/config-plugins)
  plugins: [
    // {
    //   src: '~/plugins/vuex-persist',
    //   mode: 'client'
    // }
  ],

  // Auto import components (https://go.nuxtjs.dev/config-components)
  components: true,

  // Modules for dev and build (recommended) (https://go.nuxtjs.dev/config-modules)
  buildModules: [
    // https://go.nuxtjs.dev/eslint
    '@nuxtjs/eslint-module',
    // https://go.nuxtjs.dev/tailwindcss
    '@nuxtjs/tailwindcss',
    '@nuxtjs/html-validator'
  ],

  // Modules (https://go.nuxtjs.dev/config-modules)
  modules: ['@nuxtjs/pwa', '@nuxtjs/firebase', '@nuxt/content'],
  firebase: {
    config: {
      apiKey: 'AIzaSyD4ge8g6oe0xp6vQ1y85AbvI8PXcDKzoKk',
      authDomain: 'xxx.firebaseapp.com',
      databaseURL: '<databaseURL>',
      projectId: 'xxx',
      storageBucket: 'xxx.appspot.com',
      messagingSenderId: '471446831599',
      appId: '1:471446831599:web:16ec77402cbb336f67b61a',
      measurementId: 'G-XFVH7QFG4L' // optional
    },
    services: {
      auth: {
        persistence: 'local', // default
        initialize: {
          onAuthStateChangedAction: 'user/onAuthStateChangedAction',
          subscribeManually: false
        },
        ssr: true
        // emulatorPort: 9099,
        // emulatorHost: 'http://localhost'
      },
      firestore: {
        chunkName:
          process.env.NODE_ENV !== 'production' ? 'firebase-auth' : '[id]', // default
        enablePersistence: true
        // emulatorPort: 8080,
        // emulatorHost: 'localhost'
      },
      functions: {
        location: 'us-central1'
        // emulatorPort: 12345,
        // emulatorHost: 'http://10.10.10.3'
      },
      storage: true
    }
  },
  pwa: {
    // disable the modules you don't need
    meta: false,
    icon: false,
    // if you omit a module key form configuration sensible defaults will be applied
    // manifest: false,

    workbox: {
      importScripts: [
        // ...
        '/firebase-auth-sw.js'
      ],
      // by default the workbox module will not install the service worker in dev environment to avoid conflicts with HMR
      // only set this true for testing and remember to always clear your browser cache in development
      // dev: process.env.NODE_ENV === 'development'
      dev: true
    }
  },

  // Content module configuration (https://go.nuxtjs.dev/config-content)
  content: {},

  // Build Configuration (https://go.nuxtjs.dev/config-build)
  build: {},
  router: {
    middleware: ['auth']
  }
}

store/user:

  async nuxtServerInit({ dispatch, commit }, { res }) {
    if (res && res.locals && res.locals.user) {
      const { allClaims: claims, idToken: token, ...authUser } = res.locals.user

      await dispatch('onAuthStateChangedAction', {
        authUser,
        claims,
        token
      })
    }
  },
  async onAuthStateChangedAction({ commit, dispatch }, { authUser, claims }) {
    console.log('auth state changed....')
    console.log('authUser: ', authUser)
    console.log('claims: ', claims)

    try {
      if (!authUser) {
        await dispatch('logOutUser')
        return
      } else if (authUser && authUser.emailVerified) {
        const {
          uid,
          email,
          emailVerified,
          displayName = '',
          photoURL,
          metadata,
          providerData,
          providerId,
          tenantId
        } = authUser
        commit('SET_AUTH_USER', {
          uid,
          email,
          emailVerified,
          displayName,
          photoURL, // results in photoURL being undefined for server auth
          metadata,
          providerData,
          providerId,
          tenantId,
          isAdmin: claims.custom_claim // use custom claims to control access (see https://firebase.google.com/docs/auth/admin/custom-claims)
        })
        console.log('fetching profile...')
        await dispatch('getUserProfile', authUser)
      } else {
        console.log('User logged out or not verified')
        return
      }
    } catch (error) {
      console.error('Error with Auth State observer: ', error)
    }
  },

So, with above code, hard refresh (or direct navigation via browser URL) of my login page (when user is already logged in) shows this in console (note the console log of user?, null from middleware)

enter image description here

Thank you for any help!

redshift
  • 4,815
  • 13
  • 75
  • 138
  • You might want to remove sensitive data from this post (`firebase.config`) or change it to fake. – exmaxx Feb 07 '21 at 20:41
  • 1
    Thanks for the heads up! It's safe to post. See this: https://stackoverflow.com/questions/37482366/is-it-safe-to-expose-firebase-apikey-to-the-public/37484053#37484053 – redshift Feb 07 '21 at 21:03
  • Makes sense. Thanks for the link. – exmaxx Feb 07 '21 at 21:08

1 Answers1

0

There might be two sources of the problem:

  1. Try moving your nuxtServerInit action to store/index.js.

Currently, you have nuxtServerInit in store/user.js meaning that the actual action is namespaced as user/nuxtServerInit. Therefore it is not called.

  1. You mention hard reload. During hard reload, the service worker is bypassed and so it doesn't pass the authentication token to the server side. See here.
exmaxx
  • 3,252
  • 28
  • 27
  • Thanks. There has been an update since I made the original post...and I did move nuxtServerInit to root store index.js, rather than namespaced. However, that did not cure the problem. As for your second point, that looks interesting....I'll have to look it over in some more detail. Thanks! – redshift Feb 07 '21 at 21:08
  • I am going to clone this repo and see if I get the same issue: https://github.com/nuxt-community/firebase-module/issues/452#issuecomment-774441100 – redshift Feb 07 '21 at 21:09