Vic Wild
Vic Wild

Reputation: 87

Can't set Cookie with JavaScript in Safari or iOS

I'm working on some cookie consent and terms etc.. So I made a JS function to set a cookie after user clicks "Agree" button:

...html

<button onclick="setCookie('law_cookie', 'agree_all', 90)">


...js

function setCookie(name, value, daysToLive) {
    // Encode value in order to escape semicolons, commas, and whitespace
    let cookie = name + "=" + encodeURIComponent(value);

    if (typeof daysToLive === "number") {
        /* Sets the max-age attribute so that the cookie expires
        after the specified number of days */
        cookie += ";max-age=" + (daysToLive * 24 * 60 * 60) + ';Secure;path=/';

        document.cookie = cookie;
        cookie_set = true

    }
}

Now I tested in chrom and firefox, everything works great! BUT, safari isn't able to set a cookie. I tried to initialise by clicking on the button but after reload safari hasn't set the cookie.

I checked if javascript was enabled (it was) and I also tried to set cookie = encodeURIComponent(cookie); but nothing works.

Someone has an idea what I'm doing wrong?

Upvotes: 4

Views: 5628

Answers (4)

user3635325
user3635325

Reputation: 11

it seems that Safari, unlike Chrome/Firefox - does not store JS cookie that is Secure; if the site is an http

this behavior is not specified on cookies RFC, and MDN (;secure: Specifies that the cookie should only be transmitted over a secure protocol.)

so if you run the following in an http served page JS:

document.cookie = "k1=v1;Secure;";

it will behave the following

  • on most browsers - this will store cookie both from http and https
  • on Safari - this will store the cookie only when executed in https page context

That may explain this behvior

Upvotes: 1

Charles
Charles

Reputation: 111

Safari version 15.2, unlike Chrome and Firefox, refuses to set Secure cookies on the localhost origin, so you'll need to add a workaround just for Safari.

Upvotes: 5

Anton Krug
Anton Krug

Reputation: 1781

Encoding the value is good

let cookie = name + "=" + encodeURIComponent(value);

But encoding the whole sting not:

cookie = encodeURIComponent(cookie);

I modified your script I removed the 'secure' entry as that will limit it to working only with HTTPS, when you are troubleshooting give it the best chances, and add security only when everything works. In the past the might have worked with some browsers:

https://developer.mozilla.org/en-US/docs/web/api/document/cookie

;secure Cookie to only be transmitted over secure protocol as https. Before Chrome 52, this flag could appear with cookies from http domains.

And I added window.alert so you will see 3 things:

  • Proof that your button/event actually hit
  • Check that you provided the age argument (without age your condition will not save cookie)
  • Will show you what values are going to save so you can confirm if it's ok.

The modified JS:

function setCookie(name, value, daysToLive) {
    // Encode value in order to escape semicolons, commas, and whitespace
    let cookie = name + "=" + encodeURIComponent(value);

    if (typeof daysToLive === "number") {
        /* Sets the max-age attribute so that the cookie expires
        after the specified number of days */
        cookie += ";max-age=" + (daysToLive * 24 * 60 * 60) + ';path=/';

                window.alert(cookie);
        document.cookie = cookie;
        cookie_set = true
    }
}

setCookie('law_cookie', 'agree_all', 90)

Often using a lot of console.log helps with troubleshooting as well

Do you use some other frameworks which could interfere with this? Something might be doing stuff with cookies behind your back. Did you try saving cookies from the HTTP header as well?

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie

Did you try to minimalize the replicator, make smallest project which can still replicate the problem? Or start with a small self-contained JS fiddle:

https://jsfiddle.net/ao9p7e4j/1/

Here I added a function to show cookies to see what you have

Upvotes: 0

MicheleS
MicheleS

Reputation: 1

Have you tried using a private tab on safari? It may be possible that it didn’t load your new files. On my website I use the same method to write cookies and it works on Safari.

Upvotes: 0

Related Questions