Welcome to the Power Users community on Codidact!
Power Users is a Q&A site for questions about the usage of computer software and hardware. We are still a small site and would like to grow, so please consider joining our community. We are looking forward to your questions and answers; they are the building blocks of a repository of knowledge we are building together.
Setting a cookie with a userscript
Background:
I'm using a websites which uses a pin code locally stored in a cookie for login. As firefox does not recognise the field to input the pin as a password field, it won't store the password for me.
To avoid having to remember the pin myself, I'm using a greasemonkey user script to automatically set the cookie (security is not a concern, the website in question does not hold any important or personal information, so I don't mind that the pin is stored as plain text on my computer)
The user script I'm currently using looks like this:
// ==UserScript==
// @name test
// @match *://example.com/*
// @run-at document-start
// @grant none
// ==/UserScript==
(function() {
'use strict';
document.cookie = "uuid=xxx";
})();
Problem:
The above user script works fine on the second time. On the first time I open the website I won't be logged in, but if I reload the site or open a second tab, I'm logged in. So apparently the cookie is correctly created, but too late.
Is there a way to create the cookie earlier?
I'm using
- greasemonkey 4.11
- firefox 102.3.0ESR
- macOS 11.6.8
2 answers
@Canina had the brilliant idea to make my userscript reload the page in case the cookie did not exist previously.
Using this idea, my userscript now works like this:
Greasemonkey version
// ==UserScript==
// @name test
// @match *://example.com/*
// @run-at document-start
// @grant none
// ==/UserScript==
(
function() {
'use strict';
if (document.cookie.indexOf('uuid') == -1 ) {
document.cookie = "uuid=xxx";
location.reload();
}
}
)();
Tampermonkey version
// ==UserScript==
// @name test
// @description setting cookie
// @version 1.0
// @match https://example.com/*
// @run-at document-start
// @grant GM_cookie
// ==/UserScript==
if (document.cookie.indexOf('uuid') == -1 ) {
GM.cookie.set({ name: 'uuid', value: 'xxx'}, function(error) {
console.log(error || 'Quack');
});
location.reload();
}
0 comment threads
The following users marked this post as Works for me:
User | Comment | Date |
---|---|---|
samcarter | (no comment) | Oct 6, 2022 at 13:10 |
Unfortunately, it doesn't look like Greasemonkey will let you do this, at least not directly.
Per GreaseSpot's description of @run-at document-start
, that value maps to when document.readyState == 'loading'
. Per MDN, this maps to that "the document
is still loading".
As far as I can tell from a quick perusal of MDN, this would seem to map to that the request has already been sent and thus the set of cookies to be sent along with that request has already been committed to.
That also maps to the behavior you are seeing: the cookie is added locally (as would be the case also if the server returned a Set-Cookie:
HTTP response header) but the newly set cookie is sent to the web server only in subsequent requests.
You would need to use something that can modify a HTTP request before it is actually sent to the remote web server. It doesn't look to me like Greasemonkey offers a hook that fires that early.
I'm assuming that the web site in question sets the cookie as a non-persisted session cookie, but if it does set it to be persisted and your cookie deletion settings are responsible for deleting it, you could perhaps just add a cookie exception in the Privacy & Security section of the browser preferences to "allow" cookies for the site. Maybe you could use a Greasemonkey script to modify the cookie, changing it from a session cookie to a persisted cookie?
Another possibility would be to make your userscript automatically trigger a reload of the web page after setting the cookie if the cookie wasn't there previously. Doing so would likely cause the login page to flash by temporarily, but it would cause you to be logged in automatically. In that case you probably want to use @run-at
document-idle
or maybe document-end
instead of document-start
. If you go this route, be careful so that your userscript doesn't end up in an infinite loop that you can't get it out of.
The cleanest approach would probably be to write a simple custom WebExtension add-on that intercepts web requests for the specific host and modifies the request to add the appropriate cookie as needed. Without having looked at writing Firefox extensions, I doubt that this would be significantly more involved than the Greasemonkey userscript you show in your question.
Doing so should enable you to set the cookie before the initial request is sent to the server by your browser, making it appear to the server from the beginning that you already have logged in. It would also likely work better than the force-reload alternative if the site modifies how the log in process works; in such a case, what your plugin does would simply look to the server like a stray cookie, and you would be presented with a login page as normal.
For the ultimate in "hacky" solutions, it might even be possible to write a bookmarklet that loads something (anything) from the host in question; modifies the set of cookies for the host; and then makes the request that actually brings up the logged-in content. Whether this can even work probably depends heavily on the interaction between the different origins involved. If it works, it would have the benefit of leaving you with an obvious "escape hatch" of simply navigating normally to the login page and logging in manually, should the automation break at some point.
0 comment threads