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

Infinite loop on refresh token endpoint in version 9.0.1 #890

Open
Suniron opened this issue Aug 29, 2024 · 6 comments
Open

Infinite loop on refresh token endpoint in version 9.0.1 #890

Suniron opened this issue Aug 29, 2024 · 6 comments
Labels
bug A bug that needs to be resolved p4 Important Issue

Comments

@Suniron
Copy link

Suniron commented Aug 29, 2024

Environment


  • Operating System: Linux
  • Node Version: v20.17.0
  • Nuxt Version: 3.13.0
  • CLI Version: 3.13.1
  • Nitro Version: 2.9.7
  • Package Manager: [email protected]
  • Builder: -
  • User Config: -
  • Runtime Modules: -
  • Build Modules: -

Nuxt auth version: 9.0.1

Reproduction

With the configuration below, sign in to the app and reload the page

const determineBaseUrl = () => {
  const baseUrl = process.env.NUXT_PUBLIC_BASE_API || '/api'
  // Check if the baseUrl finishes with a trailing slash
  return !baseUrl.endsWith('/') ? `${baseUrl}/auth/` : `${baseUrl}auth/`
}

const authOptions: ModuleOptions = {
  baseURL: determineBaseUrl(),
  globalAppMiddleware: true,
  isEnabled: true,
  provider: {
    endpoints: {
      getSession: { method: 'get', path: `session` },
      signIn: { method: 'post', path: `credentials` },
      signOut: { method: 'delete', path: `logout` },
      // @ts-expect-error disable sign up, like in the example from the docs: https://auth.sidebase.io/guide/local/quick-start#api-endpoints
      signUp: false,
    },
    pages: {
      login: '/login',
    },
    // See: https://github.com/sidebase/nuxt-auth/issues/867#issuecomment-2293906780
    refresh: {
      endpoint: { method: 'post', path: `refresh-token` },
      isEnabled: true,
      refreshOnlyToken: true,
      token: {
        cookieName: 'auth.refresh',
        httpOnlyCookieAttribute: false,
        maxAgeInSeconds: 2592000,
        refreshRequestTokenPointer: '/refreshToken',
        sameSiteAttribute: 'lax',
        secureCookieAttribute: false,
        signInResponseRefreshTokenPointer: '/refreshToken',
      },
    },
    session: {
      dataType: {
        companyHasAcceptedTermsOfUse: 'boolean',
        companyId: 'number',
        companyName: 'string',
        email: 'string',
        firstName: 'string',
        fullyConnected: 'boolean',
        id: 'string',
        isTwoFactorInitialized: 'boolean',
        lastName: 'string',
        roles: '(\'admin\' | \'member\')[]',
        username: 'string',
      },
    },
    token: {
      cookieName: 'auth.token',
      headerName: 'Authorization',
      httpOnlyCookieAttribute: false,
      maxAgeInSeconds: 15 * 60, // 15 minutes
      sameSiteAttribute: 'lax',
      secureCookieAttribute: false,
      signInResponseTokenPointer: '/accessToken',
    },
    type: 'local',
  },
  sessionRefresh: {
    enableOnWindowFocus: true, // disable to avoid conflicts when switching tabs
    enablePeriodically: 5 * 60 * 1000, // every 5 minutes
  },
}

Describe the bug

The /refresh-token route is called a loop. The first calls refresh the token and then saturate the backend.
image

Cookies seems to be correctly set
image

Additional context

No response

Logs

No response

@Suniron Suniron added bug A bug that needs to be resolved pending An issue waiting for triage labels Aug 29, 2024
@Suniron Suniron changed the title Infinite loop on refresh token endpoint Infinite loop on refresh token endpoint in version 9.0.1 Aug 29, 2024
@cip8
Copy link
Contributor

cip8 commented Aug 30, 2024

This is caused by your refresh.token.maxAgeInSeconds, which is 2592000.

Transformed in milliseconds by the DefaultRefreshHandler, this means 2_592_000_000, which is higher than the maximum number allowed by JS for setInterval, which is 2_147_483_647. So the value overflows, goes to something negative (or maybe zero?) and the interval is triggered without any pauses.

I fixed this with PR#891 (link).

Meanwhile you can decrease your refresh token maxAge to a value less than 24.8 days or use the temporary package, that contains the fix, until PR#891 is merged & released:

pnpm add https://pkg.pr.new/@sidebase/nuxt-auth@b41f424

@Suniron
Copy link
Author

Suniron commented Sep 1, 2024

Omg thanks for the explanation.

Let me try it the next week 🤞

@Suniron
Copy link
Author

Suniron commented Sep 2, 2024

Now, I'm trying with a light config as possible (see below) and I haven't the loop on the refresh (thanks!), but the refreshing doesn't work well.

For eg. if I remove the cookie auth.token (and have a valid auth.refresh-token), after reloading the page, I'm redirected to the login page instead of having a new refreshed token set...

Also, I disabled the SSR to have a good view of what happened and I don't see any request to refresh the token... 😓 (this test was OK with the 0.8.2 version)

I tried a trick to refresh the token when a refresh-token is detected but the (access) token not:

const { refresh } = useAuth()

const refreshCookie = useCookie('auth.refresh-token')
const tokenCookie = useCookie('auth.token')

// If needed, refresh the token
if (refreshCookie.value && !tokenCookie.value) {
    await refresh()
}

The behavior is strange because I can log the refreshCookie cookie (which is valid) but a null value is sent to my refresh route...
image

Configuration

const authOptions: ModuleOptions = {
  baseURL: determineBaseUrl(),
  globalAppMiddleware: true,
  isEnabled: true,
  provider: {
    endpoints: {
      getSession: { method: 'get', path: `session` },
      signIn: { method: 'post', path: `credentials` },
      signOut: { method: 'delete', path: `logout` },
      // @ts-expect-error disable sign up, like in the example from the docs: https://auth.sidebase.io/guide/local/quick-start#api-endpoints
      signUp: false,
    },
    pages: {
      login: '/login',
    },
    // See: https://github.com/sidebase/nuxt-auth/issues/867#issuecomment-2293906780
    refresh: {
      endpoint: { method: 'post', path: `refresh-token` },
      isEnabled: true,
    },
    session: {
      dataType: {
        companyHasAcceptedTermsOfUse: 'boolean',
        companyId: 'number',
        companyName: 'string',
        email: 'string',
        firstName: 'string',
        fullyConnected: 'boolean',
        id: 'string',
        isTwoFactorInitialized: 'boolean',
        lastName: 'string',
        roles: '(\'admin\' | \'member\')[]',
        username: 'string',
      },
    },
    token: {
      signInResponseTokenPointer: '/accessToken',
    },
    type: 'local',
  },
}

@abzarak
Copy link

abzarak commented Sep 3, 2024

Numbers are in milliseconds. Seems like a typo...
A temporary fix for me was to multiply numbers to 60 * 1000

@cip8
Copy link
Contributor

cip8 commented Sep 6, 2024

Now, I'm trying with a light config as possible (see below) and I haven't the loop on the refresh (thanks!), but the refreshing doesn't work well.

For eg. if I remove the cookie auth.token (and have a valid auth.refresh-token), after reloading the page, I'm redirected to the login page instead of having a new refreshed token set...

Indeed, this happens to me too: when the refresh token is there and the auth one is missing, the refresh will not be triggered.

The error seems to be related to the refresh-token server this time - I will propose a fix soon.

@cip8
Copy link
Contributor

cip8 commented Sep 6, 2024

@Suniron the second part of the issue will be fixed by PR#902.

@phoenix-ru phoenix-ru added p4 Important Issue and removed pending An issue waiting for triage labels Sep 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A bug that needs to be resolved p4 Important Issue
Projects
None yet
Development

No branches or pull requests

4 participants