I use electron 0.36.0 and I have a cookie for a page and this page has a nested frame with a different domain.
I need to somehow keep a cookie alive when going to this frame directly (different domain) and ideally, I want to avoid upgrades of electron (otherwise I would have to rewrite my code).
What's an ideal solution for my situation (it can be also a small workaround)?
Thank you!
Cookies can now be shared with different domains so you will have to find a different way of doing what your trying to do.
For cross domain cookies alcuadrado has described a work around to do this in his post like below:
centralize all cookies in a single domain, let's say cookiemaker.com
when the user makes a request to example.com you redirect him to cookiemaker.com
cookiemaker.com redirects him back to example.com with the information you need
check this answer and this.
Related
Is there any alternative ways to secure cookies access other then domains?
in my application i am setting cookie on 1 fix domain (cookie.xyz.com) and i need to track user on any domain, basically we are SaSS company and our client will put our js code on his website(s), then we set and get cookie on our one cookie.xyz.com because client can put our js on multiple domains. (right now i am using iframe and window messaging to get/set cookies on cookie.xyz.com)
So now in my case anybody can steal cookie of end user using js and use that and he can himself became that end user.
So what could be solution this so only my code (running in context on any domain) can read and write cookie from particular domain (we do this because our client don't have one or fix domains).
Before downvote this question let me tell you.
I know its not possible, thats why i ask here to find possible or hacky solutions?
You are facing a Cross Origin use case where you want to give liberty on your origin domain BUT you want to add control on it.
Both cases are complicated to coexist.
A solution is to add on your back end webservice a control on the origin of the request such as :
header("Access-Control-Allow-Origin: http://origin.domain:port");
Access-Control-Allow-Credentials: true
And update your JS Call to add credentials to true.
I'm replacing cookies with localStorage on browsers that can support it (anyone but IE). The problem is site.example and www.site.example store their own separate localStorage objects. I believe www is considered a subdomain (a stupid decision if you ask me). If a user was originally on site.example and decides to type in www.site.example on her next visit, all her personal data will be inaccessible. How do I get all my "subdomains" to share the same localStorage as the main domain?
This is how I use it across domains...
Use an iframe from your parent domain - say parent.example
Then on each child.example domain, just do a postMessage to your parent.example iframe
All you need to do is setup a protocol of how to interpret your postMessage messages to talk to the parent.example iframe.
If you're using the iframe and postMessage solution just for this particular problem, I think it might be less work (both code-wise and computation-wise) to just store the data in a subdomain-less cookie and, if it's not already in localStorage on load, grab it from the cookie.
Pros:
Doesn't need the extra iframe and postMessage set up.
Cons:
Will make the data available across all subdomains (not just www) so if you don't trust all the subdomains it may not work for you.
Will send the data to the server on each request. Not great, but depending on your scenario, maybe still less work than the iframe/postMessage solution.
If you're doing this, why not just use the cookies directly? Depends on your context.
4K max cookie size, total across all cookies for the domain (Thanks to Blake for pointing this out in comments)
I agree with other commenters though, this seems like it should be a specifiable option for localStorage so work-arounds aren't required.
I suggest making site.example redirect to www.site.example for both consistency and for avoiding issues like this.
Also, consider using a cross-browser solution like PersistJS that can use each browser native storage.
Set to cookie in the main domain:
document.cookie = "key=value;domain=.mydomain.example"
and then take the data from any main domain or sub domain and set it on the localStorage
This is how:
[November 2020 Update: This solution relies on being able to set document.domain. The ability to do that has now been deprecated, unfortunately. NOTE ALSO that doing so removes the "firewall" between domains and subdomains for vulnerability to XSS attacks or other malicious script, and has further security implications for shared hosting, as described on the MDN page. September 2022 Update: From Chrome v109, setiing document.domain will only be possible on pages that also send an Origin-Agent-Cluster: ?0 header.]
For sharing between subdomains of a given superdomain (e.g. example.com), there's a technique you can use in that situation. It can be applied to localStorage, IndexedDB, SharedWorker, BroadcastChannel, etc, all of which offer shared functionality between same-origin pages, but for some reason don't respect any modification to document.domain that would let them use the superdomain as their origin directly.
(1) Pick one "main" domain to for the data to belong to: i.e. either https://example.com or https://www.example.com will hold your localStorage data. Let's say you pick https://example.com.
(2) Use localStorage normally for that chosen domain's pages.
(3) On all https://www.example.com pages (the other domain), use javascript to set document.domain = "example.com";. Then also create a hidden <iframe>, and navigate it to some page on the chosen https://example.com domain (It doesn't matter what page, as long as you can insert a very little snippet of javascript on there. If you're creating the site, just make an empty page specifically for this purpose. If you're writing an extension or a Greasemonkey-style userscript and so don't have any control over pages on the example.com server, just pick the most lightweight page you can find and insert your script into it. Some kind of "not found" page would probably be fine).
(4) The script on the hidden iframe page need only (a) set document.domain = "example.com";, and (b) notify the parent window when this is done. After that, the parent window can access the iframe window and all its objects without restriction! So the minimal iframe page is something like:
<!doctype html>
<html>
<head>
<script>
document.domain = "example.com";
window.parent.iframeReady(); // function defined & called on parent window
</script>
</head>
<body></body>
</html>
If writing a userscript, you might not want to add externally-accessible functions such as iframeReady() to your unsafeWindow, so instead a better way to notify the main window userscript might be to use a custom event:
window.parent.dispatchEvent(new CustomEvent("iframeReady"));
Which you'd detect by adding a listener for the custom "iframeReady" event to your main page's window.
(NOTE: You need to set document.domain = "example.com" even if the iframe's domain is already example.com: Assigning a value to document.domain implicitly sets the origin's port to null, and both ports must match for the iframe and its parent to be considered same-origin. See the note here: https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy#Changing_origin)
(5) Once the hidden iframe has informed its parent window that it's ready, script in the parent window can just use iframe.contentWindow.localStorage, iframe.contentWindow.indexedDB, iframe.contentWindow.BroadcastChannel, iframe.contentWindow.SharedWorker instead of window.localStorage, window.indexedDB, etc. ...and all these objects will be scoped to the chosen https://example.com origin - so they'll have the this same shared origin for all of your pages!
The most awkward part of this technique is that you have to wait for the iframe to load before proceeding. So you can't just blithely start using localStorage in your DOMContentLoaded handler, for example. Also you might want to add some error handling to detect if the hidden iframe fails to load correctly.
Obviously, you should also make sure the hidden iframe is not removed or navigated during the lifetime of your page... OTOH I don't know what the result of that would be, but very likely bad things would happen.
And, a caveat: setting/changing document.domain can be blocked using the Feature-Policy header, in which case this technique will not be usable as described.
However, there is a significantly more-complicated generalization of this technique, that can't be blocked by Feature-Policy, and that also allows entirely unrelated domains to share data, communications, and shared workers (i.e. not just subdomains off a common superdomain). #Mayank Jain already described it in their answer, namely:
The general idea is that, just as above, you create a hidden iframe to provide the correct origin for access; but instead of then just grabbing the iframe window's properties directly, you use script inside the iframe to do all of the work, and you communicate between the iframe and your main window only using postMessage() and addEventListener("message",...).
This works because postMessage() can be used even between different-origin windows. But it's also significantly more complicated because you have to pass everything through some kind of messaging infrastructure that you create between the iframe and the main window, rather than just using the localStorage, IndexedDB, etc. APIs directly in your main window's code.
I'm using xdLocalStorage, this is a lightweight js library which implements LocalStorage interface and support cross domain storage by using iframe post message communication.( angularJS support )
https://github.com/ofirdagan/cross-domain-local-storage
this kind of solution causes many problems like this. for consistency and SEO considerations
redirect on the main domain is the best solution.
do it redirection at the server level
How To Redirect www to Non-www with Nginx
https://www.digitalocean.com/community/tutorials/how-to-redirect-www-to-non-www-with-nginx-on-centos-7
or
any other level like route 53 if are using
This is how I solved it for my website. I redirected all the pages without www to www.site.example. This way, it will always take localstorage of www.site.example
Add the following to your .htaccess, (create one if you already don't have it) in root directory
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [R=301,L]
I am creating a bookmarklet that is to be used across a wide range of domains. I wanted to set some cookies to store temporary settings for this bookmarklet, so I assumed that setting a cookie from this script would assign the cookie to the domain of the script's origin.
This was not the case, the bookmarklet is able to assign cookies to the domain of the current site being viewed. This is not suitable for my needs (this would remember settings per domain, rather than for the bookmarklet across all domains).
My question is, is this somehow breaking the cross domain policy? And a follow up question, how can I store cookies for the bookmarklet rather than the correct domain it is used on.
Bookmarklets are running in the context of the current page so that is the security context they run in and thus this doesn't break cross domain policy. You can only set cookies on the current page's domain. Because of this your bookmarklet can't have it's own cookies.
This is the same as scripts that are loaded into a given page from a variety of domains. The origin of the page is what matters, not the origin of the script.
The only way I know of for you to save settings once for your script across all domains would be to use cross domain JSONP and store the settings on your server, but you still may have difficulty identifying a unique user.
It sounds like what you're trying to do would be much more suited to a browser plug-in which has local storage for the plug-in.
It does not break cross domain policy, since it is in fact run on a separate domain (that's the point behind a bookmarklet).
If you want to store cookie information, either make use of a 3rd party service (as in, have your own server with code that accepts cookie changes).
Note that this can be a security issue since every domain would be able to get cookies for your user, unless you make your service write-only (which I doubt).
Then there's another alternative - don't save settings in a cookie. Use a different storage medium instead.
I'm iframing an external site. That site tries to call location from parent for analytics reasons and access is refused (for obvious default security reasons) .
Yet I would like to disable that security and answer, because that site is a 'friend' but not on the same domain.
Seems impossible to grant that access... any idea ?
I ran into a similar situation before. Allowing for cross domain javascript access through iframes is not possible since this would result in a cross-scripting-attack nightmare. Like the other poster said, you will have to post this data to them yourself. One way to fix this is to set a cookie that can be read by the other domain with whatever information they are looking for then they can read the data from the cookie. Javascript can set to the cookie when you load the other site in the iframe. For a function to do that, check http://phpjs.org/functions/setcookie:509
If the site is a 'friend' as you say - how about passing them the location data yourself?
I'm replacing cookies with localStorage on browsers that can support it (anyone but IE). The problem is site.example and www.site.example store their own separate localStorage objects. I believe www is considered a subdomain (a stupid decision if you ask me). If a user was originally on site.example and decides to type in www.site.example on her next visit, all her personal data will be inaccessible. How do I get all my "subdomains" to share the same localStorage as the main domain?
This is how I use it across domains...
Use an iframe from your parent domain - say parent.example
Then on each child.example domain, just do a postMessage to your parent.example iframe
All you need to do is setup a protocol of how to interpret your postMessage messages to talk to the parent.example iframe.
If you're using the iframe and postMessage solution just for this particular problem, I think it might be less work (both code-wise and computation-wise) to just store the data in a subdomain-less cookie and, if it's not already in localStorage on load, grab it from the cookie.
Pros:
Doesn't need the extra iframe and postMessage set up.
Cons:
Will make the data available across all subdomains (not just www) so if you don't trust all the subdomains it may not work for you.
Will send the data to the server on each request. Not great, but depending on your scenario, maybe still less work than the iframe/postMessage solution.
If you're doing this, why not just use the cookies directly? Depends on your context.
4K max cookie size, total across all cookies for the domain (Thanks to Blake for pointing this out in comments)
I agree with other commenters though, this seems like it should be a specifiable option for localStorage so work-arounds aren't required.
I suggest making site.example redirect to www.site.example for both consistency and for avoiding issues like this.
Also, consider using a cross-browser solution like PersistJS that can use each browser native storage.
Set to cookie in the main domain:
document.cookie = "key=value;domain=.mydomain.example"
and then take the data from any main domain or sub domain and set it on the localStorage
This is how:
[November 2020 Update: This solution relies on being able to set document.domain. The ability to do that has now been deprecated, unfortunately. NOTE ALSO that doing so removes the "firewall" between domains and subdomains for vulnerability to XSS attacks or other malicious script, and has further security implications for shared hosting, as described on the MDN page. September 2022 Update: From Chrome v109, setiing document.domain will only be possible on pages that also send an Origin-Agent-Cluster: ?0 header.]
For sharing between subdomains of a given superdomain (e.g. example.com), there's a technique you can use in that situation. It can be applied to localStorage, IndexedDB, SharedWorker, BroadcastChannel, etc, all of which offer shared functionality between same-origin pages, but for some reason don't respect any modification to document.domain that would let them use the superdomain as their origin directly.
(1) Pick one "main" domain to for the data to belong to: i.e. either https://example.com or https://www.example.com will hold your localStorage data. Let's say you pick https://example.com.
(2) Use localStorage normally for that chosen domain's pages.
(3) On all https://www.example.com pages (the other domain), use javascript to set document.domain = "example.com";. Then also create a hidden <iframe>, and navigate it to some page on the chosen https://example.com domain (It doesn't matter what page, as long as you can insert a very little snippet of javascript on there. If you're creating the site, just make an empty page specifically for this purpose. If you're writing an extension or a Greasemonkey-style userscript and so don't have any control over pages on the example.com server, just pick the most lightweight page you can find and insert your script into it. Some kind of "not found" page would probably be fine).
(4) The script on the hidden iframe page need only (a) set document.domain = "example.com";, and (b) notify the parent window when this is done. After that, the parent window can access the iframe window and all its objects without restriction! So the minimal iframe page is something like:
<!doctype html>
<html>
<head>
<script>
document.domain = "example.com";
window.parent.iframeReady(); // function defined & called on parent window
</script>
</head>
<body></body>
</html>
If writing a userscript, you might not want to add externally-accessible functions such as iframeReady() to your unsafeWindow, so instead a better way to notify the main window userscript might be to use a custom event:
window.parent.dispatchEvent(new CustomEvent("iframeReady"));
Which you'd detect by adding a listener for the custom "iframeReady" event to your main page's window.
(NOTE: You need to set document.domain = "example.com" even if the iframe's domain is already example.com: Assigning a value to document.domain implicitly sets the origin's port to null, and both ports must match for the iframe and its parent to be considered same-origin. See the note here: https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy#Changing_origin)
(5) Once the hidden iframe has informed its parent window that it's ready, script in the parent window can just use iframe.contentWindow.localStorage, iframe.contentWindow.indexedDB, iframe.contentWindow.BroadcastChannel, iframe.contentWindow.SharedWorker instead of window.localStorage, window.indexedDB, etc. ...and all these objects will be scoped to the chosen https://example.com origin - so they'll have the this same shared origin for all of your pages!
The most awkward part of this technique is that you have to wait for the iframe to load before proceeding. So you can't just blithely start using localStorage in your DOMContentLoaded handler, for example. Also you might want to add some error handling to detect if the hidden iframe fails to load correctly.
Obviously, you should also make sure the hidden iframe is not removed or navigated during the lifetime of your page... OTOH I don't know what the result of that would be, but very likely bad things would happen.
And, a caveat: setting/changing document.domain can be blocked using the Feature-Policy header, in which case this technique will not be usable as described.
However, there is a significantly more-complicated generalization of this technique, that can't be blocked by Feature-Policy, and that also allows entirely unrelated domains to share data, communications, and shared workers (i.e. not just subdomains off a common superdomain). #Mayank Jain already described it in their answer, namely:
The general idea is that, just as above, you create a hidden iframe to provide the correct origin for access; but instead of then just grabbing the iframe window's properties directly, you use script inside the iframe to do all of the work, and you communicate between the iframe and your main window only using postMessage() and addEventListener("message",...).
This works because postMessage() can be used even between different-origin windows. But it's also significantly more complicated because you have to pass everything through some kind of messaging infrastructure that you create between the iframe and the main window, rather than just using the localStorage, IndexedDB, etc. APIs directly in your main window's code.
I'm using xdLocalStorage, this is a lightweight js library which implements LocalStorage interface and support cross domain storage by using iframe post message communication.( angularJS support )
https://github.com/ofirdagan/cross-domain-local-storage
this kind of solution causes many problems like this. for consistency and SEO considerations
redirect on the main domain is the best solution.
do it redirection at the server level
How To Redirect www to Non-www with Nginx
https://www.digitalocean.com/community/tutorials/how-to-redirect-www-to-non-www-with-nginx-on-centos-7
or
any other level like route 53 if are using
This is how I solved it for my website. I redirected all the pages without www to www.site.example. This way, it will always take localstorage of www.site.example
Add the following to your .htaccess, (create one if you already don't have it) in root directory
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [R=301,L]