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

useCookie with maxAge or expires gets removed when updated #24227

Closed
ChrisGV04 opened this issue Nov 10, 2023 · 13 comments · Fixed by #24253
Closed

useCookie with maxAge or expires gets removed when updated #24227

ChrisGV04 opened this issue Nov 10, 2023 · 13 comments · Fixed by #24253

Comments

@ChrisGV04
Copy link
Contributor

ChrisGV04 commented Nov 10, 2023

Environment

  • Operating System: Darwin
  • Node Version: v18.17.1
  • Nuxt Version: 3.8.1
  • CLI Version: 3.9.1
  • Nitro Version: 2.7.2
  • Package Manager: pnpm@8.10.2
  • Builder: -
  • User Config: devtools
  • Runtime Modules: -
  • Build Modules: -

Reproduction

I used the starter project from pnpx nuxi@latest init and just replaced the app.vue with the following code:

<script setup lang="ts">
const hasConsent = useCookie('dialog', {
  sameSite: 'strict',
  default: () => 'no',
  maxAge: 2592000, // 30 days in seconds
});
const showConsentAlert = ref(false);

onMounted(() => {
  if (process.server) return;
  if (hasConsent.value === 'yes') return;

  showConsentAlert.value = true;
});

function acceptConsent() {
  hasConsent.value = 'yes';
  showConsentAlert.value = false;
}
</script>

<template>
  <Teleport to="body">
    <div v-if="showConsentAlert">
      <span>We use cookies</span>
      <button type="button" @click="acceptConsent">Accept</button>
    </div>
  </Teleport>
</template>

Describe the bug

When I click the acceptConsent button, I set the cookie value from no to yes. However, instead of saving the yes value inside the cookie, it gets removed completely. I tried on Firefox v119.0.1 and Chrome v119.0.6. Both browsers have the exact same behavior.

The strange part is that if I remove the maxAge option from useCookie, everything works fine. But I would like that the consent cookie expires after 30 days. I also tried with expires and the same issue happened.

I'm not sure if I'm doing something wrong or if it really is a bug, but I would expect that if I change the value of the cookie, it must be persisted, but it is getting deleted...

Additional context

I'm trying to create a cookie consent dialog that shows once and if it gets accepted, it doesn't show again for 30 days. My reproduction code is just a bare-bones demo with the minimal code I could reproduce it with. In the real website this functionality is inside a CookieConsent.vue component and it is a Modal.

cookies.mp4

Logs

No response

@RomanSkrypnik
Copy link

RomanSkrypnik commented Nov 10, 2023

@ChrisGV04 I'm facing the same issue
@danielroe says that's an expected behaviour for now
Here I created this issue but it was closed : #24041
As for me, I have a dynamic maxAge which I get from response and upgrading to nuxt 3.8.0 just breaks the logic
@danielroe we need flag or smth like that to save previously set options

@ChrisGV04
Copy link
Contributor Author

ChrisGV04 commented Nov 10, 2023

Hi @RomanSkrypnik! I see you had a similar issue, however in my case I'm not even using useCookie with different options. I just created it once and if I change the value it gets deleted completely...

If that's the expected behavior, I don't understand how should cookies with options be updated. I did as the docs show and just added options. It makes useCookie a lot less useful if I can't update the value just because I set options.

And yeah, that's a breaking change! I didn't notice until a customer told me that every time they enter or refresh my website they keep getting the cookie consent even after accepting...

@ZEA-repository
Copy link

Hi everyone! Pr #23697 seems to be related to this issue.

@positiveprogrammer
Copy link

positiveprogrammer commented Nov 11, 2023

Hi, We had a similar issue. The code is trying to convert maxAge to milliseconds to use setTimeout. But it looks like the value is too big. Our workaround would be to decrease maxAge to less than 20 days, but waiting for a more robust solution.

Maximum delay value
Browsers store the delay as a 32-bit signed integer internally. This causes an integer overflow when using delays larger than 2,147,483,647 ms (about 24.8 days), resulting in the timeout being executed immediately.

@affinage-digital
Copy link

affinage-digital commented Nov 11, 2023

Is there a solution to the problem?
this is a terrible bug

@ChrisGV04
Copy link
Contributor Author

Hi @positiveprogrammer!
You are right. I reduced the maxAge to 1,296,000 (15 days in seconds) and it worked... Even if it's not ideal to reduce the time.

I went through the code for the useCookie composable and it seems that PR #23549 created a customRef that is only used client-side to make expired cookies undefined on the browser. It uses setTimeout for that, which is why setting a long expiration time client-side doesn't work...

The default value doesn't have that issue because it runs server-side. Server-side cookies don't use that same functionality. They use a normal ref.

I think I have an idea on how to solve it or at least to work around it since it's a browser limitation. I will work on a PR for it

@fransyrcc
Copy link

Hello, I'm also facing the same issue. 1 to 24 days work but 25 days do not. However, if I set it to 1 year it works

 maxAge: 365 * 24 * 60 * 60,

Nuxt Version: 3.8.1

@junkiet
Copy link

junkiet commented Nov 16, 2023

365 * 24 * 60 * 60

cookie is using miliseconds, should do 365 * 24 * 60 * 60 * 1000

@ChrisGV04
Copy link
Contributor Author

Hi @junkiet!
useCookie uses seconds for the maxAge option. Internally it converts it to milliseconds

@junkiet
Copy link

junkiet commented Nov 16, 2023

What I test just now, maxAge: -1 at setCookie() at server side

at client side, need to set also but using useCookie():
let token = useCookie('token');
token.value = res.value.token;

I have no idea, why need to set both server and client side, is it something depreciated at 3.8.1 or a bug?

@ChrisGV04
Copy link
Contributor Author

ChrisGV04 commented Nov 16, 2023

Hi @junkiet

I wrote about this issue and why it's happening in detail at my currently open PR #24253.

The issue only exists on the client side, that's why if you set the cookie on the server, it always works. In the client it uses setTimeout which has a maximum wait time of 24.8 days, so adding any value above that on the client makes the cookie expire immediately

@junkiet
Copy link

junkiet commented Nov 16, 2023

Hi @junkiet

I wrote about this issue and why it's happening in detail at my currently open PR #24253.

The issue only exists on the client side, that's why if you set the cookie on the server, it always works. In the client it uses setTimeout which has a maximum wait time of 24.8 days, so adding any value above that on the client makes the cookie expire immediately

ii see, I will try it

@junkiet
Copy link

junkiet commented Nov 16, 2023

I found the problem, once execute deleteCookie, whever you set in setcookie, it will be automatically set to expiry immediately, so I use normal and simple way auth.value = null to delete it, then work as normal., before 3.7 nuxt, deleteCookie is working fine

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

Successfully merging a pull request may close this issue.

7 participants