nuxt-community / auth-module

Zero-boilerplate authentication support for Nuxt 2
https://auth.nuxtjs.org
MIT License
1.93k stars 925 forks source link

Refresh scheme doesn't automatically refresh token when token expires #1269

Open sts-ryan-holton opened 3 years ago

sts-ryan-holton commented 3 years ago

Version

module: 5.0.0-1624817847.21691f1 nuxt: 2.15.8

Nuxt configuration

mode:

Nuxt configuration

auth: {
  redirect: {
    login: '/account/login/',
    logout: '/account/login/',
    callback: '/account/login/',
    home: '/account/beams/'
  },
  strategies: {
    local: {
      scheme: 'refresh',
      refreshToken: {
        property: 'token',
        data: 'token'
       },
      endpoints: {
        login: { url: '/api/account/login', method: 'post', propertyName: 'token' },
        refresh: { url: '/api/account/refresh', method: 'post', },
        logout: { url: '/api/account/logout', method: 'post' },
        user: { url: '/api/account', method: 'get', propertyName: 'user' }
      }
    }
  }
},

Additional information

Checklist

Steps to reproduce

What is expected?

When a user's token expires and refresh scheme is implemented, a user shouldn't be logged out and redirected back to the login screen, the refresh token should be used to obtain a new token and the transition should be seamless allowing any authenticated route to continue to work.

What is actually happening?

In my Nuxt project with the Auth module I've implemented the refresh scheme, however, when my token expires I don't see any request in my network being made to the refresh route after my token expires and I navigate to a protected page via the auth middleware.

I expect I'm missing some simple configuration?

My current token has an expiry of 1 minute for testing, and my refresh token has an expiry of 14 days for testing.

However, when adding:

the functionality appears to not be fetching my user and automatically logging me in.

My /api/account/refresh endpoint in my API returns the following:

{
  token: 'my refresh token',
  token_type: 'bearer',
  expired_in: 5000
}

My /api/account/login endpoint in my API returns the following:

{
  token: 'my token',
  token_type: 'bearer',
  expired_in: 1000
}

What am I missing?

sts-ryan-holton commented 3 years ago

Is there any update on this?

Destaq commented 3 years ago

Also encountering this issue, were you able to find a solution?

sts-ryan-holton commented 3 years ago

@Destaq in my set up, I'm using the tymon/jwt-auth package for Laravel, turns out by switching to the Laravel JWT provider in the auth-module, and exposing my refresh endpoint it works.

Destaq commented 3 years ago

Hmmm, I guess that means there's an issue within the refresh scheme source code. Thanks for sharing; unfortunately I'm using Flask so going to have to keep digging.

alimuradov commented 3 years ago

I have the same problem. After authorization, if you press F5, authorization disappears, although I see a valid token in the storage. Here is my config auth: { scopeKey: 'user_type', rewriteRedirects: true, strategies: { local: { scheme: 'refresh', localStorage: { prefix: 'auth.' }, token: { prefix: 'access_token.', property: 'access_token', maxAge: 1800, type: 'Bearer' }, refreshToken: { prefix: 'refresh_token.', property: 'refresh_token', data: 'refresh_token', maxAge: 86400 }, user: { property: 'user', autoFetch: true }, endpoints: { login: { url: '/login', method: 'post'}, refresh: { url: '/token/refresh/', method: 'post' }, user: { url: '/user', method: 'get' } }, } }, redirect: { home: '/redirect', }, cookie: { options: { maxAge: 86400 // 24 hours } }, resetOnError: true, },

toniengelhardt commented 2 years ago

Hey @Destaq, I have a Nuxt / Django project with JWT and it works for me with the djangorestframework-simplejwt package. Maybe you can get some inspiration there.

Here's my Nuxt config for the auth module:

  auth: {
    cookie: {
      options: {
        secure: process.env.NODE_ENV === 'production', // Enable in production only.
        sameSite: 'lax',
      },
    },
    redirect: {
      login: '/login',
      logout: '/login',
      callback: '/login',
      home: '/write',
    },
    resetOnError: (error, name, endpoint) => {
      console.log('resetOnError', error, name, endpoint)
      return true
    },
    strategies: {
      local: {
        scheme: 'refresh',
        token: {
          property: 'access',
          type: 'JWT',
        },
        refreshToken: {
          property: 'refresh',
          data: 'refresh', // This is not a JWT token!
        },
        user: {
          property: false,
        },
        endpoints: {
          login: {
            url: '/auth/token/',
            method: 'post',
          },
          refresh: {
            url: '/auth/token/refresh/',
            method: 'post',
          },
          user: false,
          logout: {
            url: '/user/logout/',
            method: 'post',
          },
        },
      },
    },
  }

You have to be careful, in the case of djangorestframework-simplejwt the refresh token is not a JWT token for instance, see token type.

sadeghi-aa commented 2 years ago

Hey @Destaq, I have a Nuxt / Django project with JWT and it works for me with the djangorestframework-simplejwt package. Maybe you can get some inspiration there.

How did you handle parallel API calls for refresh tokens? What happens in my case is that several API calls result in a 401 response which triggers parallel API calls for refresh tokens and only the first one receives a 200. The other ones get 401 responses which make auth think that the refresh token itself has expired too.

toniengelhardt commented 2 years ago

Wow interesting @sadeghi-aa! I'm having these random logouts sometime that I couldn't figure out, maybe it's related to that problem. Do you have any ideas on how to resolve this?

sadeghi-aa commented 2 years ago

Not yet. I found this open pull request about this issue. I applied it locally in my node_modules folder, but that caused some other issues that I haven't been able to solve. You could try it yourself though.