Handling cookies in JavaScript

While a contentious topic in many circles, cookie handling is nonetheless necessary in certain situations, so it's useful to be able to handle cookies in JavaScript should the need arise.

The most important thing to understand how cookies are stored and presented. In JavaScript, all cookies are retrieved within a single string, separated by a semicolon and space, as such:

forename=Jonathan; variable2=Doeseph

Therefore, to add or remove cookies from storage, we need to manipulate this string. Of course, to this end, I've written a handler to take care of most of the work:

function do_cookie(act,name,value = '') {
	let days		= 1;												// Cookie validity in days
	let path		= '/';											// Cookie path
	let extra		= 'SameSite=None; Secure';	// Optional extra info
	let cookie	= [];												// Hold cookie data for processing
	name				= 'cookie_prefix_' + name;

	let result = '';
	switch (act) {
		case 'set':

			let d = new Date();
			d.setTime(d.getTime() + (days * 24 * 3600 * 1000));

			cookie = [
				name + '=' + value,
				'expires=' + d.toUTCString(),
				'path=' + path,
			];
			if (extra) { cookie.push(extra); }

			document.cookie = cookie.join('; ');

		break;
		case 'get':

			let data = document.cookie.split('; ');
			for (let x = 0; x < data.length; x++) {
				data[x] = data[x].split('=');
				if (data[x][0] == name) {
					result = data[x][1];
					break;
				}
			}

		break;
	}
	return result;
}

To set a cookie:

do_cookie('set','forename','Jumbo');

And retrieve:

let forename = do_cookie('get','forename');

When setting a cookie, you need to keep the validity in mind; the function above defaults to a 24-hour cookie life, but this can be modified or added as an optional argument if required. This value is converted to a standard universal date/time string that ensures any computer in any time zone is capable of knowing the exact second of expiry:

Wed, 06 Apr 2022 16:12:43 UTC

On top of the cookie validity, other options are available upon setting a cookie: path and secure options. The path dictates where on the site this cookie may be called: if the cookie is set with a path of /folder1/, then the cookie will not be readable by any script running outside of that directory. Most of the time the path is set to /, meaning the root of the site, but there are functional reasons to limit this in certain circumstances, such as monitoring time spent in a particular directory.

The final option is whether this is to be considered a secure cookie. If this is set, the cookie may only be retrieved when accessed via HTTPS; if accessed by a script running in plain HTTP, this cookie will not be visible. Note that you cannot set a secure cookie from an insecure session.

You may have noticed that when setting the cookie, we're not setting the entire string - all we need to do is send our resultant single-cookie string to the document.cookie property. Attempting to write all known cookies every time would no doubt be a nightmare, so the JavaScript engine simply handles all string actions into this property and does the requisite work behind the scenes.

Data Formatting

In the function above, all the strings are joined and separated by characters that could very easily be included in the data you're attempting to store, causing a potential "Bobby Tables" issue - something that most people want to avoid. Most data retrieved from cookies is encoded or encrypted to prevent session hijacking, and this is usually encoded as Base64, which includes the equals sign, which can definitely screw things up.

The cookie will almost certainly be retrieved with such characters escaped, which means that if you're expecting to retrieve this kind of information, it would be worth running a regex filter on the cookie string to avoid separating by escaped characters.

The same also goes for storing data in cookies: if you're storing complex information that makes use of the observed separating characters, be sure to run your string through a sanitising routine before attempting to drop the data into the cookie string.