I recently changed the scope of some JavaScript cookies on our site. They were all scoped to the subdomain in which they were created. They are now scoped globally to the domain. The issue is I now have duplicate cookies that have different scopes.Is it possible to programatically eliminate the JavaScript cookies based on name and scope (domain)? Example:
cookieA --> domain=.mysite.com
cookieA--> domain=sub.mysite.com
cookieB --> domain=.mysite.com
cookieB --> domain=sub.mysite.com
I want to remove only cookies with domain = sub.mysite.com by name.
You can do this using JavaScript Cookie library.
If you want delete cookie named cookieA, which is set do domain sub.mysite.com, just run:
Cookies.remove("cookieA", {domain: "sub.mysite.com"})
This will remove sub.mysite.com's cookieA, and leave .mysite.com's cookieA untouched.
If you don't want to use this library, you can do it directly:
document.cookie = "cookieA=;domain=sub.mysite.com;expires=Thu, 01 Jan 1970 00:00:01 GMT"
We had the same problem when changing our cookies to a global domain. Quite a lot of functionality was affected because duplicate cookies now exist (ex: www.domain.com and .domain.com). Since we deploy our website to different domains (dev, acc, prod) these issues were spread out across different domains.
Without going through all the pages to find issues cross domain, we've come up with a solution that doesn't require to know all the cookie names:
/*
* #param c: window.Cookies
* #doc https://github.com/js-cookie/js-cookie
*/
(function(c) {
var arrCookies = document.cookie.split(/; */);
var arrCookie;
for (var cookie in arrCookies) {
if (arrCookies.hasOwnProperty(cookie)) {
arrCookie = arrCookies[cookie].split('=');
c.remove(arrCookie[0], { domain: window.location.hostname });
console.log('removing cookie ' + arrCookie[0] + ' on: ' + window.location.hostname);
}
}
}(window.Cookies));
This solution cleans up the active domain by using window.location.hostname and re-enables functionality for your previously set subdomain.
Related
This is how I create my cookie with Javascript and after that redirect to cart page.
var d = new Date();
d.setTime(d.getTime() + (1 * 24 * 60 * 60 * 1000));
var expires = ";expires=" + d.toUTCString();
var product = { productId: btn.value, colorId: productColorId, quantity: 0 };
products.push(product);
document.cookie = "products=" + JSON.stringify(products) + expires + "; path=/; SameSite=strict";
window.location.href = "cart";
and I can find this cookie in my browser in cookie section, but in server side I get nothing.
At first I use this code and I get null.
string products = HttpContext.Request.Cookies["products"];
After that I try this code
if (HttpContext.Request.Cookies.TryGetValue("products", out cookieValue))
{
// TODO: use the cookieValue
}
else
{
// this cookie doesn't exist.
}
and always it runs else, It seems, even don't find cookie.
Is there any suggestion?
According to this documentation,a can optionally be set in double quotes and any US-ASCII characters excluding CTLs, whitespace, double quotes, comma, semicolon, and backslash are allowed.
Try the following changes in your javascript ,use encodeURIComponent() to convert double quotes
document.cookie = "products=" + encodeURIComponent(JSON.stringify(product)) + expires + "; path=/; SameSite=strict";
The screenshot of the cookie value got in the server-side
In response to a comment, Cookie headers in javascript is forbidden, which means it cannot be set programmatically. Only the browser may set it, and it may choose to not send cookie information along with the HTTP request depending on their browser settings. (Typically inside privacy settings)
First I would confirm that the cookie header is indeed being sent. You can usually find this out by using the browser's web inspector and looking at network request. Here is a screenshot in chrome:
If you don't see the cookie header then I would advise double checking browser privacy settings to ensure cookies are enabled and disabling ad/tracking blockers if you have them installed. If this is a case, unfortunately there isn't much you can do other than beg the user to change their settings or disable their ad blockers.
If you DO see the cookie header, then this suggest that it may be a problem in the back-end code, but I'm not familiar with ASP.NET so I can't really comment on that.
Hope this helps
This issue is related to GDPR compliance but I'll keep it more focused on the technical issue at hand:
I have found some great open source resources for cookie consent banners, like Cookie Consent and Cookie Script. The implementation of the banner looks simple enough. The issue though is they require cookies to be disabled by default, which I am unsure how to do on a global level on a domain.
I don't know a lot of JavaScript but what I'm wondering is: Is there a method with Javascript to universally allow or deny cookies on a domain? Or, would this method be unique to each script in question? Google Analytics for example has documentation on disabling cookies. How would I lump that together with Facebook, Youtube, and all the other scripts using cookies and only allow cookies after a user has consented? Or, would I have to address it for each individual script?
In other words, is there a method in JavaScript where I can universally turn off/on cookies depending on user preference? Just from my research so far it seems there is not.
I have created a Proxy script on the document.cookie variable.
Run this script as the first script in your document.
Note
This solution assumes:
Cookies are set through javascript (and server side uses sessions).
It also only works on browsers which support the use of javascript proxies.
It only works for local domains (it only prevents external domain cookies from being set)
The Proxy script
Setting a cookie
What it does it that it intercepts the document.cookie variable because window.disableCookies is set to true in the script below. It stores the cookies in the window.cookieList array until the enableCookies script is executed. If enableCookies is executed, it will disable the proxy and iterate over the window.cookieList variable, to set the cookies in the browser.
Reading the cookies
If a script sets a cookie it expects the cookie in the document.cookie variable. So until the enableCookies function is called (and window.disableCookies is set to false), it fakes a document.cookie response, it builds it based upon the window.cookieList variable.
var cookie_setter_orig = document.__lookupSetter__("cookie").bind(document);
var cookie_getter_orig = document.__lookupGetter__("cookie").bind(document);
window.cookieList = [];
window.disableCookies = true;
Object.defineProperty(document, "cookie", {
get: function () {
if(!window.disableCookies) {
return cookie_getter_orig();
} else {
var response = "";
window.cookieList.forEach(function(cookie){
var splitted = cookie.split(";")[0].split("=");
response += splitted[0] + "=" + splitted[1] + "; ";
});
return response.slice(0, response.length - 2);
}
},
set: function (val) {
if(!window.disableCookies) {
cookie_setter_orig(val);
} else {
window.cookieList.push(val);
}
}
});
function enableCookies()
{
window.disableCookies = false;
window.cookieList.forEach(function(cookie){
document.cookie = cookie;
});
window.cookieList =[];
}
Testing it out
To test it out you can execute the following script:
/* These cookies are not set; they are set on the window.cookieList, until enableCookies is activated */
document.cookie = 'cookie1=test; expires=Sun, 1 Jan 2023 00:00:00 UTC; path=/';
document.cookie = 'cookie2=test; expires=Sun, 1 Jan 2023 00:00:00 UTC; path=/';
document.cookie = 'cookie3=test; expires=Sun, 1 Jan 2023 00:00:00 UTC; path=/';
/* This is a fake cookie list from the window.cookieList variable
* Output: cookie1=test; cookie2=test; cookie3=test
*/
console.log(document.cookie);
setTimeout(function(){
enableCookies(); /* Enable cookies and pass them to the browser */
/* The cookie below is passed to the browser directly, since cookies are enabled */
document.cookie = 'cookie4=test; expires=Sun, 1 Jan 2023 00:00:00 UTC; path=/';
/* This is the real cookie list
* Output: cookie1=test; cookie2=test; cookie3=test; cookie4=test
*/
console.log(document.cookie);
}, 2500);
Is there a method with Javascript to universally allow or deny cookies on a domain?
No.
I'm using the Hapi framework for a Node.js application, and the Hapi framework comes with its own Cookie management tools, which i'm using for authentication.
The framework then sets a cookie named session, with a json value encoded to base64. The domain is set to example.com (not .example.com)
Now, the problem lies when i attempt to edit this cookie client-side, by doing the following
document.cookie = 'session=' + btoa(JSON.stringify(_decoded)) + "; path=/; domain=example.com";
This actually sets a duplicate cookie with the domain '.example.com'
I haven't asked Javascript to prepend the dot, and i cant seem to get rid of it.
I'm assuming that it is because of this dot, that the cookie is being duplicated. How do i set the domain without it automatically prepending a dot?
EDIT
I've given up on trying to remove the leading dot, and instead am trying to delete the old cookie and then create a new one. However i still end up with duplicate cookies!
Navigate to /login and enter login details
Redirected to /account and cookie set by server (WITHOUT Leading Dot)
Execute Javascript to delete and re-create cookie
1 cookie now exists and it has a Leading Dot before the domain
The above behaviour is good, however the following also happens, which is bad
Navigate to /login and enter login details
Redirected to /account and cookie set by server (WITHOUT Leading Dot)
Navigate to /example
Execute Javascript to delete and re-create cookie
2 cookies now exists, one with the leading dot(created by JS) and one without (created by server)
The code i'm using is
API.Session = {
Encoded : function () { return document.cookie.replace(/(?:(?:^|.*;\s*)session\s*\=\s*([^;]*).*$)|^.*$/, "$1")},
Decoded : function () { return JSON.parse(atob(this.Encoded()))},
Update : function (_decoded) {
document.cookie = 'session=; expires=Thu, 01 Jan 1970 00:00:01 GMT;';
document.cookie = 'session=' + btoa(JSON.stringify(_decoded)) + "; path=/; domain=example.com;";
}
}
API.Helpers.ShowAdvancedOptions = function () {
var s = API.Session.Decoded()
s.ShowAdvancedOptions = true
API.Session.Update(s)
}
Is by some chance the original cookie already present in this?
btoa(JSON.stringify(_decoded))
Cause from:
document.cookie
document.cookie is defined as:
a string containing a semicolon-separated list of all cookies
So it seems to me you are adding a new semicolon-separated value (new cookie) to that list (without removing the original cookie)
Ok, it's not that, have you tried this?
link
Sounds like the same problem you described
For anyone with a similar issue, this was eventually solved by dropping the domain property altogether. See other related question
We have a webshop. We use a cookie that stores the order ID of every single order/user. All of the items in the basket and the user's address info are related to that ID. The cookie is only meant to be changed when an order is complete or if its value is empty. We check the cookie with the server on each page load and only change it when conditions above are met.
A few months ago, we discovered that in some cases, the browser can keep multiple versions of that cookie value, and "switch" between those values randomly on page load. Moreover, the value is not overwritten - if the browser switches from value A to value B, a few page loads later it can load value A again. The browser can hold up to 5 (possibly more) values for a single cookie, and it keeps changing them randomly as the user navigates our webshop. It is very problematic since once the cookie value is changed - the basket contents changes with it. We experienced this problem primarily in Google Chrome and Internet Explorer. Trying to check the cookie value in the console shows only the value that is being used for the current page load.
We use the following function to set cookies:
function SetCookie(c_name, value, exdays){
var expires = "";
if(exdays)
{
var date = new Date();
date.setTime(date.getTime() + (exdays*24*60*60*1000));
expires = "; expires=" + date.toUTCString();
}
document.cookie = c_name + "=" + escape(value) + expires + "; path=/";
}
Whenever I read about cookies, everyone says that overwriting a cookie with the same name and path is supposed to destroy the previous value. So I tried to do the following when setting the order ID cookie (delete cookie before setting it):
SetCookie(name , "", -1);
SetCookie(name , val, 14);
However, the problem still persists and the browser keeps randomly choosing the value on page load. What could be causing such behaviour? Is there any way to check the (shadow) values of the cookie that the browser is currently NOT using? Is there any way to check how many values for a specific cookie name and path the browser has stored?
EDIT: Our javascript order ID cookie setter function runs on page load. It is the only place we ever change the order ID cookie.
Recently, we tested this behaviour with dev tools open and it showed interesting results. A simple page reload can change the cookie header of the request to a request containing a different cookie value, before our cookie setter function ever had a chance to run. We thought it could be a caching issue (request being cached and used later), but it seems this behaviour persists when we set up the server to return a no-cache and no-store response header.
Look at the Nate answer to this question How to handle multiple cookies with the same name?
Hope it helps !!
My page HTML contains a span (with text) whose onClick = "goDropShip();"
The page contains a script that contains:
function goDropShip() {
var date = new Date();
date.setTime(date.getTime()+(24*60*60*1000));
document.cookie = "dropShip=true; expires="+date.toGMTString();
window.location.href="http://www.domain.com";
}
I have verified, with "alert()", that the function is in fact executing. And testing the cookie immediately after dropping it is successful. However, after the redirect, the cookie seems to be empty.
www.domain.com's index.html (which receives this redirect) has a script with the following:
if (document.cookie.indexOf("dropShip=true") >= 0 ) {
window.location = "http://www.domain.com/processDropShip";
}
However, the cookie appears to be completely blank after the redirect.
I am trying .indexOf() only because attempts to retrieve the cookie specifically by name have also failed, so I am trying to find the cookie in the entire document.cookie text.
I am probably just not using the cookies properly, or I do not know how to.
Forgive the fact that "dropShip" doesn't seem to make sense in this context, but I am having to obfuscate the details for security reasons. But the only thing I have changed is the cookie name.
As always, thanks for any help.
If the domain your are setting the cookie from and redirecting to are same, you just need to have the path set to / while adding the cookie so that it's accessible throughout the domain.
document.cookie = "dropShip=true; path=/; expires="+date.toGMTString();