sidebase / nuxt-auth

Authentication built for Nuxt 3! Easily add authentication via OAuth providers, credentials or Email Magic URLs!
https://auth.sidebase.io
MIT License
1.24k stars 160 forks source link

Refreshing a page removes the cookie using the local provider #732

Open jorni-moddit opened 5 months ago

jorni-moddit commented 5 months ago

Environment

Reproduction

We're using a WordPress back-end with the simple-JWT plugin. For this example I returned a hardcoded body in the api/auth/[...].ts And there is a simple login form.

https://stackblitz.com/edit/github-gpkaqq?file=server%2Fapi%2Fauth%2F[...].ts

Describe the bug

After logging in a cookie is set, when not configured it's under auth.token and I have an authenticated state. image

After a page refresh this cookie is removed. image

Additional context

No response

Logs

No response

MisterNox commented 5 months ago

Unfortunately I cannot reproduce your issue. When I try it with your stackblitz example and refresh the page the cookie persists and I am still authenticated (I tried it with Firefox and Chrome).

However, I had a similar issue when I touched the cookie after it was set by the signIn method with the Cookies class of the js-cookie library. My intention was to build a wrapper around the signIn to dynamically set the expires attribute of the cookie by the value the jwt token comes with instead of relying only on the static definition via the config in nuxt. Don't know if this is related to the useCookie method or the Set-Cookie header. By the way I use simple-jwt as well.

Do you touch the cookie somewhere in your process flow? What helps me in this situations when it seems to get buggy is hard refreshing via Ctrl + Shift + R and/or closing the browser entirely and/or deleting the .nuxt folder and let it rebuild everything from scratch. Dont know if it helps in your situation but you could give it a try.

husseinjahan commented 4 months ago

I have the same Issue.

I'm using local authentication but connect to api to get user login. Sometimes not all the times when I refresh the browser, the response comes with a 'SET-COOKIE' response header that clears auth token (I don't know why!). I think there is a bug.

Is there any workaround about it?

I checked this in development and production server with chrome and firefox browsers.

image

FireMasterK commented 4 months ago

This only happens in the production build, I can reproduce the issue on the stackblitz too with npm install && npm run build && npm run preview.

Edit: removing the set-cookie headers from the nuxt server doesn't fix it, the client is unauthenticated despite having a valid cookie.

Norel commented 4 months ago

I have the exact same problem except I can't reproduce the bug in a local project (dev or prod), only when deployed to a distant server.

FireMasterK commented 4 months ago

I have the exact same problem except I can't reproduce the bug in a local project (dev or prod), only when deployed to a distant server.

Same case for me, except I'm able to reproduce it on the Stackblitz in production mode!

phoenix-ru commented 4 months ago

I can reproduce on playground-local using pnpm build && pnpm nuxi preview.

Adding this to the reproduction app.vue fixes the issue.

onMounted(() => {
  getSession({ force: true });
});

Why is it needed, however? And why doesn't it work without force: true?

I assume it is related to https://github.com/sidebase/nuxt-auth/blob/9bd9f452d29cf2b93c768c017702bc9719fb8adf/src/runtime/composables/local/useAuth.ts#L84-L87 and https://github.com/sidebase/nuxt-auth/blob/9bd9f452d29cf2b93c768c017702bc9719fb8adf/src/runtime/composables/local/useAuthState.ts#L52-L57

If someone could further investigate and propose a fix, it would be great!

Norel commented 4 months ago

It turns out that using node 18 is problematic when using nuxt fetch (https://github.com/nuxt/nuxt/issues/12552). Upgrading to node 20 fixed the issue for me. Stackblitz is probably using node 18 too.

FireMasterK commented 4 months ago

It turns out that using node 18 is problematic when using nuxt fetch (nuxt/nuxt#12552). Upgrading to node 20 fixed the issue for me. Stackblitz is probably using node 18 too.

I'm able to reproduce it on node 20 still, my Dockerfile uses the node:20-slim image.

ndro commented 4 months ago

I have the same issue with local provider.

Cookie got removed in Firefox after reloading the browser or updating the app. But it's fine in Chrome.

my auth config in nuxt.config.ts:

  auth: {
    baseURL: `${process.env.SOME_DOMAIN_API}`,
    provider: {
      type: 'local',
      pages: {
        login: '/login'
      },
      endpoints: {
        signIn: { path: '/login', method: 'post' },
        signOut: { path: '/logout', method: 'delete' },
        signUp: { path: '/register', method: 'post' },
        getSession: { path: '/me', method: 'get' }
      },
      token: {
        signInResponseTokenPointer: '/token',
        type: '',
        maxAgeInSeconds: 1209600
      },
      sessionDataType: {
        data: {
          // some custom data
        }
      },
    },
    globalAppMiddleware: {
      isEnabled: true
    }
  },
albank commented 4 months ago

My cookies are also set to empty 4 times like @husseinjahan above, when I refresh the page. I have the issue with both node18 and node20. However, when using the network address created by nuxt, I don't have the issue: Ex. Network: http://172.19.x.x:3000/

When I use my development mydomain.localhost that points to that address, my cookies get deleted 4x.

Any idea why ?

mbellamyy commented 3 months ago

I can reproduce OP's scenario when I use Stackblitz's embedded browser (on the right column), but I cannot reproduce it when I open the output in a new tab

Edit: I can reproduce it either way now :) Really frustrating

I have the same issue with the refresh provider.

mbellamyy commented 3 months ago

can reproduce on playground-local using pnpm build && pnpm nuxi preview.

Adding this to the reproduction app.vue fixes the issue.

It does indeed resolve it on client side, but in server side the user is still unauthenticated.

GreenmeisterDavid commented 3 months ago

I'm experiencing this issue as well; prod env, using local provider, the cookie disappears on reload on Firefox, while everything seems fine on Chromium-based browsers.

Jonathanthedeveloper commented 3 months ago

I noticed that this issue only occurs when you set the baseUrl property in your nuxt.config.ts to a different domain from your nuxtjs frontend.

taharehany commented 3 months ago

@jorni-moddit After long and painstaking research, I found this:

const headers = useRequestHeaders(['cookie']) as HeadersInit
const { data } = await useFetch('/api/example', { headers })

this will set cookies from the client side to the request you want in the Nuxt server side

andre-silva9975 commented 3 months ago

I am having the same problem. I am also using local provider. Everything works in development and production mode while in localhost. But when I build the app in a remote server that serves as a reverse proxy (using nginx) between the client and the app running in the same server at localhost, every time I log in and reload the page, I am redirected to the login page after a few seconds and the access_token cookie disappears. Here is my configuration:

` auth: {

baseURL: "/api/auth",
globalAppMiddleware: true,
provider: {
  type: "local",
  endpoints: {
    signIn: { path: "/login", method: "post" },
    signOut: { path: "/logout", method: "post" },
    getSession: { path: "/user", method: "get" }
  },
  pages: {
    login: "/login"
  },
  token: {
    signInResponseTokenPointer: "/token/accessToken",
    sameSiteAttribute: "lax",
  },
},

} `

andre-silva9975 commented 2 months ago

I am having the same problem. I am also using local provider. Everything works in development and production mode while in localhost. But when I build the app in a remote server that serves as a reverse proxy (using nginx) between the client and the app running in the same server at localhost, every time I log in and reload the page, I am redirected to the login page after a few seconds and the access_token cookie disappears. Here is my configuration:

` auth: {

baseURL: "/api/auth",
globalAppMiddleware: true,
provider: {
  type: "local",
  endpoints: {
    signIn: { path: "/login", method: "post" },
    signOut: { path: "/logout", method: "post" },
    getSession: { path: "/user", method: "get" }
  },
  pages: {
    login: "/login"
  },
  token: {
    signInResponseTokenPointer: "/token/accessToken",
    sameSiteAttribute: "lax",
  },
},

} `

I have updated to version 0.8.0-alpha.2 and when I reload the page the user doesn't logged out.

HELWATANY commented 2 months ago

The issue is related to running your server (development server or on production) in a secure connection, trying the same steps while running localhost without https won't generate the issue, while setting the development server to run on https will cause the problem to occur.

How To Run Your Local Development On HTTPS

1- You can follow this article to generate and set up your locally signed certificate. 2- Copy your certificates and key to project-root-dir/certificates 3- You can add the following environment variable in your .env file

NUXT_DEV_SERVER_CONNECTION_TYPE="https"  # Nuxt Development Server Connection Type: Should be one of [http|https]

4- Update your nuxt.config.ts should look something like this

export default defineNuxtConfig({
  devServer: {
    https:
      process.env.NUXT_DEV_SERVER_CONNECTION_TYPE === 'https'
        ? {
            key: './certificates/localhost.key',
            cert: './certificates/localhost.crt'
          }
        : false
  },
// ... the reset of your nuxt configs
})

It seems that the issue had been fixed starting 0.8.0-alpha.2, I was able to run my development server with secure connection without facing this issue

fontanes-innatial commented 2 months ago

The issue is related to running your server (development server or on production) in a secure connection, trying the same steps while running localhost without https won't generate the issue, while setting the development server to run on https will cause the problem to occur.

How To Run Your Local Development On HTTPS

1- You can follow this article to generate and set up your locally signed certificate. 2- Copy your certificates and key to project-root-dir/certificates 3- You can add the following environment variable in your .env file

NUXT_DEV_SERVER_CONNECTION_TYPE="https"  # Nuxt Development Server Connection Type: Should be one of [http|https]

4- Update your nuxt.config.ts should look something like this

export default defineNuxtConfig({
  devServer: {
    https:
      process.env.NUXT_DEV_SERVER_CONNECTION_TYPE === 'https'
        ? {
            key: './certificates/localhost.key',
            cert: './certificates/localhost.crt'
          }
        : false
  },
// ... the reset of your nuxt configs
})

It seems that the issue had been fixed starting 0.8.0-alpha.2, I was able to run my development server with secure connection without facing this issue

I tried the partner's solution but it didn't work in my case.

yamachita0109 commented 2 months ago

I tried the same but it didn't work.

    "@sidebase/nuxt-auth": "^0.8.0-alpha.2",
    auth: {
        baseURL: process.env.API_BASE_URL,
        globalAppMiddleware: true,
        provider: {
            type: 'local',
            pages: {
                login: "/login"
            },
            endpoints: {
                signIn: { path: "admin/login", method: "post" },
                signOut: { path: "admin/logout", method: "post" },
                signUp: { path: "admin/login", method: "post" },
                getSession: { path: "admin/user", method: "get" },
            },
            token: {
                signInResponseTokenPointer: "/token",
                type: "Bearer",
                headerName: "Authorization",
                maxAgeInSeconds: 60 * 60 * 24,
                sameSiteAttribute: "lax",
            },
        }
    },
mtzrmzia commented 1 month ago

I'm facing the same issue, when log in, the cookie set correctly then refresh page and the cookie gets removed.

"@sidebase/nuxt-auth": "^0.8.0"
  auth: {
    baseURL: 'http://external_api.com/api/auth/',
    globalAppMiddleware: true,
    provider: {
      type: 'refresh',
      endpoints: {
        signIn: { path: 'login', method: 'post' },
        signOut: { path: 'logout', method: 'post' },
        signUp: false,
        getSession: { path: 'me', method: 'get' },
        refresh: { path: 'refresh', method: 'post' },
      },
      token: {
        sameSiteAttribute: 'strict',
        signInResponseTokenPointer: '/data/access_token',
        cookieName: 'access_token',
        maxAgeInSeconds: 60 * 60,
      },
      refreshToken: {
        signInResponseRefreshTokenPointer: '/data/access_token',
        cookieName: 'access_token',
        refreshRequestTokenPointer: 'access_token',
        maxAgeInSeconds: 20160 * 60,
      },
      pages: {
        login: '/login',
      },
    },
  },
Ulrich-Mbouna commented 1 month ago

Same problem

Ulrich-Mbouna commented 1 month ago

Any Updates ? Please i face this issue

mhamzamughal86 commented 1 month ago

It seems that the issue you're facing with the cookie being removed upon page refresh is due to the SSR (Server-Side Rendering) nature of the application.

To resolve this issue, you can disable SSR for your application by setting ssr: false in the nuxt.config.ts file. This will make your application run as a Single Page Application (SPA), ensuring that the cookie is available and preserved across page refreshes.

export default defineNuxtConfig({ ssr: false, // other configurations })

Ulrich-Mbouna commented 1 month ago

It seems that the issue you're facing with the cookie being removed upon page refresh is due to the SSR (Server-Side Rendering) nature of the application.

To resolve this issue, you can disable SSR for your application by setting ssr: false in the nuxt.config.ts file. This will make your application run as a Single Page Application (SPA), ensuring that the cookie is available and preserved across page refreshes.

export default defineNuxtConfig({ ssr: false, // other configurations })

I tried it and it solve the issue, but i'm asking myself if it's not a bad idea to disable ssr in nuxt application. 🤔

HELWATANY commented 1 month ago

It seems that the issue you're facing with the cookie being removed upon page refresh is due to the SSR (Server-Side Rendering) nature of the application.

To resolve this issue, you can disable SSR for your application by setting ssr: false in the nuxt.config.ts file. This will make your application run as a Single Page Application (SPA), ensuring that the cookie is available and preserved across page refreshes.

export default defineNuxtConfig({ ssr: false, // other configurations })

This can not be considered a solution if your main goal is to create an SSR application!

HELWATANY commented 1 month ago

@yamachita0109 @mtzrmzia If you are serving your app over a secure connection (using HTTPS), please consider setting secureCookieAttribute to true, please check here

  auth: {
    baseURL: 'http://external_api.com/api/auth/',
    globalAppMiddleware: true,
    provider: {
      type: 'refresh',
      endpoints: {
        signIn: { path: 'login', method: 'post' },
        signOut: { path: 'logout', method: 'post' },
        signUp: false,
        getSession: { path: 'me', method: 'get' },
        refresh: { path: 'refresh', method: 'post' },
      },
      token: {
        sameSiteAttribute: 'strict',
        signInResponseTokenPointer: '/data/access_token',
        cookieName: 'access_token',
        maxAgeInSeconds: 60 * 60,
        secureCookieAttribute: true, // <---- you need to add this, default is false and should be false if you are serving over HTTP
      },
      refreshToken: {
        signInResponseRefreshTokenPointer: '/data/access_token',
        cookieName: 'access_token',
        refreshRequestTokenPointer: 'access_token',
        maxAgeInSeconds: 20160 * 60,
        secureCookieAttribute: true, // <---- you need to add this, default is false and should be false if you are serving over HTTP
      },
      pages: {
        login: '/login',
      },
    },
  },
vincepaquette commented 2 weeks ago

Any update on this please ? Did anyone figure it out ? Disabling the SSR isn't a solution in my case

cip8 commented 2 weeks ago

Any update on this please ? Did anyone figure it out ? Disabling the SSR isn't a solution in my case

Have you tried the new version (0.9.1) & experiencing the same issues?

HELWATANY commented 2 weeks ago

Any update on this please ? Did anyone figure it out ? Disabling the SSR isn't a solution in my case

Have you tried the new version (0.9.1) & experiencing the same issues?

@cip8 I wasn't able to regenerate the issue since version 0.8.0-alpha.2

Ulrich-Mbouna commented 2 weeks ago

Any update on this please ? Did anyone figure it out ? Disabling the SSR isn't a solution in my case

Have you tried the new version (0.9.1) & experiencing the same issues?

@cip8 I wasn't able to regenerate the issue since version 0.8.0-alpha.2

So your problem is solved?

HELWATANY commented 2 weeks ago

Any update on this please ? Did anyone figure it out ? Disabling the SSR isn't a solution in my case

Have you tried the new version (0.9.1) & experiencing the same issues?

@cip8 I wasn't able to regenerate the issue since version 0.8.0-alpha.2

So your problem is solved?

I was trying to help by providing reproduction steps and a fix if needed 🙂

josselinonduty commented 1 week ago

I still get this issue on v0.9.1.

I have tried a few different setups, like using h3 as my session provider, and using nuxt-auth endpoints/token. Sometimes it does work, but it seems not to be reliable.

~I'll edit my message in a few hours and provide my config or a reproduction if I can.~

josselinonduty commented 1 week ago

I still get this issue on v0.9.1.

I have tried a few different setups, like using h3 as my session provider, and using nuxt-auth endpoints/token. Sometimes it does work, but it seems not to be reliable.

I'll edit my message in a few hours and provide my config or a reproduction if I can.

Okay, so I got it working. Here is what I found:

Before:

export default defineEventHandler(async (event) => {
    const token = getCookie(event, "session");
    // business logic here
});

The issue is that the cookie is not sent reliably or there is something I don't understand. What I can confirm is that I get session undefined when I reload the page manually (hence it invalidates the client cookie because throw an error when it's invalid).

After:

export default defineEventHandler(async (event) => {
    const authorization = event.headers.get("Authorization");
    const token = authorization?.split("Bearer ")[1];
});

Now I get the token reliably and can use it.

Conclusions: There might be an issue (or a conflicting intended behaviour) in Nuxt(-Auth) lifecycle that doesn't pass cookies or not at the right time on manual reload, hence it is undefined. I could be totally wrong tho.