Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[@nuxtjs/auth-next] - Auth middleware issue with SSR #853

Closed
RobinBertilsson opened this issue Oct 14, 2020 · 26 comments
Closed

[@nuxtjs/auth-next] - Auth middleware issue with SSR #853

RobinBertilsson opened this issue Oct 14, 2020 · 26 comments
Assignees

Comments

@RobinBertilsson
Copy link

I'm using @nuxtjs/auth-next in my Nuxt application.
The application is configured using universal mode (or ssr: true since mode: 'universal' is obsolete)

I have a super simple page called pages/test.vue, which looks like

<template>
  <div>Hello World!</div>
</template>

<script lang="ts">
import { defineComponent } from 'nuxt-composition-api'

export default defineComponent({
  middleware: 'auth',
})
</script>

I've also tested without Composition API, which looks like this:

import Vue from 'vue'

export default Vue.extend({
  middleware: 'auth',
})

It all works fine without SSR enabled, but when I enable it the auth middleware doesn't work and redirects me to the login page instead.

I can verify that I'm authenticated since I can access the user via $auth.user, and I also have a valid non-expired token in LocalStorage.

After digging a bit deeper into the auth-next/dist/core/middleware.js it seems like ctx.$auth.$state.loggedIn is false.
Can someone please help me?

Version
5.0.0-1595976864.509d9d6

@albertarni
Copy link

I have the same problem too

@albertarni
Copy link

@RobinBertilsson
OK, I found the source of this issue.
If you downgrade your @axios module to 5.12.1, then it should work.

#809 (comment)

@RobinBertilsson
Copy link
Author

@albertarni, thanks.

Sadly I still facing the same issue.
The middleware keeps redirecting me to /login...

Thinking if it could be related to a release of the auth-next package as well?
I'll try to downgrade a few versions and see, I'll keep you updated..

@RobinBertilsson
Copy link
Author

Sadly no luck with an older version of auth-next...

@fabiom91
Copy link

Downgrading didn't do anything for me

@fabiom91
Copy link

I have found a solution without downgrading axios: #478 (comment)

@israelroldan
Copy link

It seems this is not only limited to auth-next, I was just helping debug this same issue in an application that uses v4.x

@RobinBertilsson
Copy link
Author

@israelroldan really? Did the Axios downgrade solution work for you?

@pi0 pi0 self-assigned this Oct 23, 2020
@just-tom
Copy link

Having the same issue, happens only on page hard refresh.

Seems the auth middleware on page refresh gets called before the auth module has chance to verify authentication, hence the redirect

@velidonmez
Copy link

I think this is not related to auth-next. I created a project from scratch to test this. Only installed nuxt-auth and nuxt-axios. Still have the issue. Also suggested solutions above didn't work for me.

@velidonmez
Copy link

Ok, for my case setting expire time for auth options solved the problem. I added cookie options to nuxt.config file. The default value for cookies was Session and that was causing the problem.

auth: {
  cookie: {
    options: {
      expires: 10
    }
  },
  .
  .
}

@just-tom
Copy link

It's definitely a hydration timing issue between SSR and client side. I can clearly see the logged in state being hydrated after the page has loaded, at which point the middleware has already run for auth, and because client side hydration happening after this point is sees as not logged in and redirects to login.

Im using auth-next but pretty sure I had the same issue with 4.* although I cannot remember how I solved it annoyingly. Right now im using the sanctum strategy very simply.

auth: { strategies: { 'laravelSanctum': { provider: 'laravel/sanctum', url: process.env.API_URL, }, } },

@just-tom
Copy link

just-tom commented Nov 3, 2020

@albertarni downgrade solution on the Axios module worked for me.

@simonmaass
Copy link

we just encountered the exact same problem - same setup as @just-tom

we also just downgraded to axios nuxt module to 5.12.1... and now SSR works as expected...

the change that might cause this looks like it is related to upgrading axios from 0.19.2 to 0.20.0...

@g0rk4
Copy link

g0rk4 commented Nov 5, 2020

I also encountered the exact problem and the downgrade of axios nuxt module to 5.12.1 worked for me too

@msonowal
Copy link
Collaborator

Duplicate of #809

@msonowal
Copy link
Collaborator

Latest version fixes this close this issue

@JoaoPedroAS51
Copy link
Collaborator

Closing here since latest version of auth-next should solve this issue. @nuxtjs/axios updated to v5.12.4. Feel free to reopen if issue persists.

@Eve-rine
Copy link

I have an issue with @nuxt/auth-next my login details are being retrieved successfuly bt am not being logged in bt when i use @nuxt/auth everything works fine,what could be the problem please

@azmatzuberi
Copy link

I’m still having trouble with this. The route is protected and $auth.loggedIn === true but it keeps redirecting me to the homepage. I’ve tried updating all my packages but so far no luck.

@elreco
Copy link

elreco commented May 12, 2021

same issue here. I can't use the auth middleware.

To fix it, I used cookie-universal-nuxt and I created my own middleware :

// middleware/auth-user.js
export default async function ({ app, redirect }) {
  const user = await app.$cookies.get('auth._token.local')
  if (!user) {
    redirect('/')
  }
}

then I can use it in my components

export default {
  middleware: 'auth-user',
}

@Fahme
Copy link

Fahme commented Jun 13, 2021

This is still an issue even after the upgrade of axios @pi0

@timdrake
Copy link

I was hoping the auth-next package would handle things more gracefully than its' predecessor, but this does not seem to be the case. However, I was able to get everything working well, and without throwing navigation guard errors. My primary objective was to redirect the user back to the guarded path (including parameters) after a successful login.

An overview of my routes, and the desired redirect behavior is as follows:

If the user IS NOT authenticated the following should occur:

/ => /login
/login (no redirect occurs)
/sign-up (no redirect occurs ; the user needs to be able to sign up if they do not have a user account)
/logout (no redirect occurs)
/home => /login
/guarded/path => /login
/another/guarded/path?with= parameters => /login?with= parameters (the ?with=parameters displaying on the login page looks silly, and can likely be removed using a custom auth plugin via $auth.onRedirect. I just have not done this, yet. I will update this comment if I do.)

If the user IS authenticated the following should occur:

/ => /home
/login => /home
/sign-up => /home
/logout (no redirect occurs)
/home (no redirect occurs)
/guarded/path (no redirect occurs)
/another/guarded/path?with= parameters (no redirect occurs)

My auth relevant nuxt.config.js is as follows:

auth: {
  redirect: {
    // do not allow auth to automatically redirect to home. we will do this with our custom auth-redirect middleware.
    home: false,
    login: '/login',
    logout: '/logout',
  },
  strategies: {
    local: {
      token: {
        property: 'jwt',
        global: true,
      },
      user: {
        property: false,
        autoFetch: false,
      },
      endpoints: {
        login: { url: '/auth/local', method: 'post' },
        logout: { url: '/auth/logout', method: 'post' },
        user: { url: '/users/me', method: 'get' },
      },
    },
  },
},

// enable auth globally. we want to guard everything by default, and override on a case-by-case basis.
router: {
  middleware: ['auth'],
},

My custom middleware/auth-redirect.js middleware is as follows:

export default function ({ $auth, redirect, route }) {
  // if the user is not authenticated, and we are not on the login or sign up page then redirect to the login page.
  if (!$auth.loggedIn && !['/login', '/sign-up'].includes(route.path)) {
    return redirect('/login')
  // if the user is authenticated, and we are not on the home page then redirect to the home page.
  } else if ($auth.loggedIn && route.path !== '/home') {
    return redirect('/home')
  }
}

My / auth relevant logic is as follows:

<script>
export default {
  auth: false,
  middleware: 'auth-redirect',
}
</script>

My /login auth relevant logic is as follows:

<script>
export default {
  beforeRouteEnter(from, to, next) {
    // attempt to store the route full path (including parameters) so that we may redirect to it after a successful login.
    next((vm) => vm.setRedirectUrl(to))
  },
  auth: false,
  middleware: 'auth-redirect',
  data() {
    return {
      redirectUrl: null,
    }
  },
  methods: {
    setRedirectUrl(toRoute) {
      // only store the route full path (including parameters) if the path of the route does not match one of the following. we do not want to redirect a successful login back to any of the following pages.
      if (!['/', '/login', '/logout', '/sign-up'].includes(toRoute.path)) {
        this.redirectUrl = toRoute.fullPath
      }
    },
    async signinUser(userInfo) {
      const userData = {
        /* credentials go here */
      }

      try {
        const response = await this.$auth.loginWith('local', { data: userData })

        await this.$auth.setUserToken(response.data.jwt)

        // if a redirect URL is set then redirect to the URL.
        if (this.redirectUrl) {
          this.$router.push(this.redirectUrl)
        // if a redirect URL is not set then redirect to the home page.
        } else {
          this.$router.push('/home')
        }
      } catch (e) {
        /* exception handling goes here */
      }
    },
  },
}
</script>

My /sign-up auth relevant logic is as follows:

<script>
export default {
  auth: false,
  middleware: 'auth-redirect',
}
</script>

My /logout auth relevant logic is as follows:

<script>
export default {
  auth: false,
  created() {
    if (this.$auth.loggedIn) {
      this.$auth.logout()
    }
  },
  mounted() {
    this.$router.app.refresh()
  },
}
</script>

Lastly, do not forget to initialize the Vuex store by at least creating an empty store/index.js file. Redirects as well as many facets of auth seem to have issues when the Vuex store is not enabled.

My /guarded/paths need no auth relevant logic as auth has been enabled globally in nuxt.config.js.

I hope this helps. 🙏🏻

@Surt
Copy link

Surt commented Dec 20, 2021

All day lost looking for a solution to this without need to make my own middleware etc (wich is the same as recreting the entire functionality of the library)
Finally, it seems to be a problem with SSR. Deactivating SSR on nuxtconfig solves the problem (or starts a new one).
My thoughts are that the middleware seems to be firing before the "clean slate" from the server is filled (can see the nuxt store commiting the auth info during load) so at first it detects isloggedIn as false.

@irsyaadbp
Copy link

i found the solution if you use proxy for axios
you can see here #1283 (comment)

@HashanLi94
Copy link

HashanLi94 commented Apr 12, 2024

@RobinBertilsson did u sortout the issue? I'm working on a project which is bit old. The authentication part is handled on keycloak V21.1.2. I have updated both next-auth("@nuxtjs/auth-next": "5.0.0-1667386184.dfbbb54") and nuxt-axios ("@nuxtjs/axios": "^5.13.6",). I have updated the project's nuxt version from 2.14.0 to 2.17.3 too. Still not redirecting to the dashboard and just redirect to the login page and its looping between callback page and login page continuously.

auth: {
// plugins: ['~/plugins/auth.js'],

strategies: {
  keycloak: {
    // scheme: '~/plugins/keycloak.js',
    scheme: 'oauth2',
    endpoints: {
      authorization: `${process.env.API_HOST}/auth/realms/${process.env.AUTH_REALM}/protocol/openid-connect/auth`,
      token: `${process.env.API_HOST}/auth/realms/${process.env.AUTH_REALM}/protocol/openid-connect/token`,
      userInfo: `${process.env.API_HOST}/auth/realms/${process.env.AUTH_REALM}/protocol/openid-connect/userinfo`,
      logout: {
        url: `${process.env.API_HOST}/auth/realms/${process.env.AUTH_REALM}/protocol/openid-connect/logout?redirect_uri=` + encodeURIComponent(String(process.env.REDIRECT_URL)),
        method: 'get'
      },
    },
    token: {
      property: 'access_token',
      type: 'Bearer',
      name: 'Authorization',
      maxAge: 1800
    },
    refreshToken: {
      property: 'refresh_token',
      maxAge: 60 * 60 * 24 * 30,
    },
    responseType: 'code',
    grantType: 'authorization_code',
    clientId: `${process.env.AUTH_CLIENT_ID}`,
    scope: ['openid'],
    codeChallengeMethod: 'S256',
    autoLogout: true,
  }
},
redirect: {
  login: '/login',
  home: "/admin/dashboard",

},
localStorage: false,

},

Where its wrong in my code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests