nuxt-community / firebase-module

🔥 Easily integrate Firebase into your Nuxt project. 🔥
https://firebase.nuxtjs.org
MIT License
641 stars 99 forks source link

[Google Cloud Run] SSR auth and page refresh issue in production #424

Open Flawe opened 3 years ago

Flawe commented 3 years ago

I'm seeing an issue when I'm signed in and refresh the page. Instead of staying signed in, I get redirected to the /signin page due to my middleware not detecting the user being logged in. It's almost as if nuxtServerInit isn't running, but only on refresh. Is that a thing? I have SSR set to true, which should be triggering this on the server side, but perhaps I'm missing something.

The only thing that seems to fix this is setting pwa.workbox.dev to true, but that's probably not a correct fix for production? I would also like to avoid doing a second redirect in beforeMount() if that's possible.

This is the setup I use:

store/index.js

export const actions = {
  nuxtServerInit({ dispatch, commit }, { res }) {
    if (res && res.locals && res.locals.user) {
      const { allClaims: claims, idToken: token, ...authUser } = res.locals.user
      commit('user/ON_AUTH_STATE_CHANGED_MUTATION', { authUser, claims, token })
    }
  },
}

store/user.js

export const getters = {
  isAuthenticated(state) {
    return state.uid !== null
  },
}
export const mutations = {
  ON_AUTH_STATE_CHANGED_MUTATION(state, { authUser, claims }) {
    if (!authUser) {
      state.uid = null
      return
    }

    const { uid } = authUser
    state.uid = uid
  },
}

And then in my middleware where I redirect to /signin

export default function ({ store, redirect }) {
  if (!store.getters['user/isAuthenticated']) {
    return redirect('/signin')
  }
}
lupas commented 3 years ago

Hey @Flawe I guess I will need to add that to the documentation, changing your workbox settings like so should fix the issue:

dev: process.env.NODE_ENV === 'development',

Let me know if that works for you.

BR, Pascal

Flawe commented 3 years ago

Hi @lupas,

Thanks for the reply!

I will try this, but it probably won't do anything if that resolves to false in production?

Basically, if I set dev: true it works as expected, and dev: false breaks it. Any chance something else may affect it, the domain maybe or something like that? I've been changing settings randomly but haven't found anything else that affects its behavior except the dev setting.

lupas commented 3 years ago

@Flawe Have you tried it in production? The issue should not appear in production.

We set pwa.workbox.dev to true in dev because workbox has issues with the HMR module which is used in dev by the dev server but non in production. So the issue should not appear there.

Flawe commented 3 years ago

@lupas Yea, it's when deployed on Cloud Run with dev: false where I see this issue.

lupas commented 3 years ago

@Flawe Hmm... Do you start your production server with nuxt build & nuxt start commands or only with nuxt or nuxt dev?

Flawe commented 3 years ago

@lupas I'm running nuxt build and nuxt start in a docker container

lupas commented 3 years ago

Hey @Flawe

Sorry for the late response - did you find the solution to your problem in the meantime or does the problem still exist?

Flawe commented 3 years ago

@lupas No worries! I haven't had much time to dig into it yet I'm afraid, but still same issue. I'll try to test a few things soon.

dosstx commented 3 years ago

Just wanted to report I got same issue as above, so am wondering if you ever fixed it @Flawe ? My bug report: https://github.com/nuxt-community/firebase-module/issues/452 although I haven't tested in production because I don't have a server yet for hosting.

Flawe commented 3 years ago

@dosstx I haven't yet, but, I'm about to do some work on it again. Hopefully I'll get back to you soon.

Flawe commented 3 years ago

@lupas Is this error expected when running locally in dev with pwa.workbox.dev = true?

Error registering workbox: TypeError: Cannot read property 'addEventListener' of undefined
    at new Workbox (workbox-window.dev.es5.mjs?ae33:643)
    at _callee$ (workbox.js?148b:8)
    at tryCatch (runtime.js?96cf:63)
    at Generator.invoke [as _invoke] (runtime.js?96cf:293)
    at Generator.eval [as next] (runtime.js?96cf:118)
    at asyncGeneratorStep (asyncToGenerator.js?c973:3)
    at _next (asyncToGenerator.js?c973:25)
Flawe commented 3 years ago

Actually you know what, this is caused by this setting:

server: {
  port: 3000,
  host: '0.0.0.0',
  timing: false
}

If I remove the host field so it gets served on localhost it's all working as expected. Any chance this could be causing the original issue too? I need this setting for the Cloud Run deployment.

lupas commented 3 years ago

@Flawe Can you check in Chrome Dev Tools if the service worker (sw.js) gets properly loaded in your productive app?

Screenshot 2021-02-06 at 10 51 42

Most likely the problem lies not with your code above but with the fact that the service-worker does not get loaded properly. Since you get the error message above (which is not expected) your auth service worker most likely is not running and therefore you don't get the user object.

We might find the solution here https://pwa.nuxtjs.org/workbox , but for now I'm also a bit clueless. Would it be easy for you to build a simple minimal case where this error is happening on https://template.nuxtjs.org/ ?

Flawe commented 3 years ago

@lupas You're right, the service worker isn't running.

I tried create a sandbox example but it doesn't work because setting server.host to "0.0.0.0" still serves on localhost instead of a random ip. It seems like that's the root of the problem.

Flawe commented 3 years ago

It may be related to https. If I add my local ip as an insecure origin like here, the worker runs, but refreshing the page still logs me out for some reason.

Flawe commented 3 years ago

Ok so I think I manage to fix this locally:

  1. Ignore my previous message, I couldn't get the chrome trust flag to work correctly
  2. Create a self-signed certificate for the local ip where the app is served when host: "0.0.0.0" is used.
  3. Point nuxt at the certificate, my server setting now looks like this:
    server: {
    port: 3000,
    host: '0.0.0.0',
    timing: false,
    https: {
      key: fs.readFileSync(path.resolve(__dirname, 'key.pem')),
      cert: fs.readFileSync(path.resolve(__dirname, 'cert.pem'))
    }
    },

It works now locally. Service-worker runs, refresh keeps me signed in, etc. I haven't tried deploying it to Cloud Run yet. I worry there may be some funny business with redirection on their end to mess up the origin not matching the SSL certificate.

IDLYA-David commented 3 years ago

I was having the same issue locally, for me it was resolved without needing a self-signed certificate by using localhost:3000 in the browser rather than 192.168.0.5:3000 or whatever your local IP is. This thread pointed me in the right direction. Seems like Nuxt PWA doesn't play nicely with local IPs.

Flawe commented 3 years ago

@IDLYA-David The ip is needed if you want to test with a different device on the local network, unfortunately.

simeon9696 commented 3 years ago

@Flawe not entirely, you can use ngrok to create an http/https tunnel. It's really simple, just install it globally then use ngrok http <your_local_port e.g. 3000>.

It'll give you a link that's valid for about an hour and 30 mins and when that expires just run the command again.

edgarmacas commented 2 years ago

@Flawe any solution?. I'm presenting the same problem, local it works but mounted on my digital ocean server the service worker does not work. My ip is without ssl certificate, my domain is without ssl certificate?? thanks

edgarmacas commented 2 years ago

@simeon9696 I try ngrok with only "http" it does not load the service worker and try with "https" and loads the service worker perfectly, that seems to be my problem, I must have my domain configured with https so that the service worker works perfectly, thanks