nuxt-community / firebase-module

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

Access Token was refresh but still Unauthorized #396

Closed shidcordero closed 3 years ago

shidcordero commented 3 years ago

Version

@nuxtjs/firebase: 7.1.0 firebase: 8.0.1 nuxt: 2.14.7

Reproduction Link

I am using this code to somewhat refresh my token. I am getting a new token and it has new expiration time. But whenever i use it to call on my server it returned an Unauthorized error.

switch (error.response.status) {
      case 401:
        {
          const self = this
          this.$fire.auth.currentUser
            .getIdTokenResult(true)
            .then((data) => {
              this.$store.commit('auth/SET_CLAIMS', data)
            })
            .catch(() => {
              // token is expired, sign out user
              self.$fire.auth.signOut().then((res) => {
                self.clearCache()
                self.$router.replace({
                  path: '/login',
                  query: { returnPath: window.location.pathname }
                })
              })
            })
        }
        break
}

In my server, I use the firebase-admin to verify the sent token const decodedToken = await admin.auth().verifyIdToken(token)

Steps to reproduce

N/A

What is Expected?

Should refresh the token and won't throw Unauthorized error

What is actually happening?

Throws unauthorized error and been refreshing many times but still I cannot authorized it

lupas commented 3 years ago

Hey @shidcordero

Where is this code you posted located? On the server? It would be appreciated if you provided a minimal Codesandbox example so we can work with a same basis.

If you want to authenticate your user on the client-side before initial render from the server you need to work with service workers. See the service worker example here. This is basically the same we do for ssr mode - have a look at these docs aswell.

br, Pascal

lupas commented 3 years ago

Closing since no Feedback from author.

shidcordero commented 3 years ago

Sorry for not actively replying on the thread. I already fixed the issue. My solution was to use the axios interceptor instead of calling a global function everytime an error is thrown.

here's my solution

const maxRetry = 3
let retry = 1
$axios.onResponseError((error) => {
  if (error.config && error.response && error.response.status === 401) {
    // try to refresh the token using getIdTokenResult method
    if ($fire.auth.currentUser) {
      if (retry <= maxRetry) {
        retry++
        return $fire.auth.currentUser
          .getIdTokenResult(true)
          .then((data) => {
            // update token saved on auth local storage
            store.commit('auth/SET_CLAIMS', data)

            // retry request
            return $axios.request(error.config)
          })
          .catch(() => {
            // token is expired, sign out user
            $fire.auth.signOut().then((res) => {
              app.router.replace({
                path: '/login',
                query: { returnPath: btoa(route.fullPath) }
              })
            })
          })
      }
    }
  }

  retry = 1

  return Promise.reject(error)
})