
RFC6265-compliant cookie parsing and CookieJar management library for Node.js, with CVE-2023-26136 security patch. Supports cookie creation, validation, storage, and retrieval for HTTP clients.
RFC6265 Cookies and CookieJar for Node.js
var tough = require('tough-cookie');
var Cookie = tough.Cookie;
var cookie = Cookie.parse(header);
cookie.value = 'somethingdifferent';
header = cookie.toString();
var cookiejar = new tough.CookieJar();
cookiejar.setCookie(cookie, 'http://currentdomain.example.com/path', cb);
// ...
cookiejar.getCookies('http://example.com/otherpath',function(err,cookies) {
res.headers['cookie'] = cookies.join('; ');
});
It's so easy!
npm install tough-cookie
Why the name? NPM modules cookie, cookies and cookiejar were already taken.
Support for versions of node.js will follow that of the request module.
Functions on the module you get from require('tough-cookie'). All can be used as pure functions and don't need to be "bound".
Note: prior to 1.0.x, several of these functions took a strict parameter. This has since been removed from the API as it was no longer necessary.
parseDate(string)Parse a cookie date string into a Date. Parses according to RFC6265 Section 5.1.1, not Date.parse().
formatDate(date)Format a Date into a RFC1123 string (the RFC6265-recommended format).
canonicalDomain(str)Transforms a domain-name into a canonical domain-name. The canonical domain-name is a trimmed, lowercased, stripped-of-leading-dot and optionally punycode-encoded domain-name (Section 5.1.2 of RFC6265). For the most part, this function is idempotent (can be run again on its output without ill effects).
domainMatch(str,domStr[,canonicalize=true])Answers "does this real domain match the domain in a cookie?". The str is the "current" domain-name and the domStr is the "cookie" domain-name. Matches according to RFC6265 Section 5.1.3, but it helps to think of it as a "suffix match".
The canonicalize parameter will run the other two parameters through canonicalDomain or not.
defaultPath(path)Given a current request/response path, gives the Path apropriate for storing in a cookie. This is basically the "directory" of a "file" in the path, but is specified by Section 5.1.4 of the RFC.
The path parameter MUST be only the pathname part of a URI (i.e. excludes the hostname, query, fragment, etc.). This is the .pathname property of node's uri.parse() output.
pathMatch(reqPath,cookiePath)Answers "does the request-path path-match a given cookie-path?" as per RFC6265 Section 5.1.4. Returns a boolean.
This is essentially a prefix-match where cookiePath is a prefix of reqPath.
parse(cookieString[, options])alias for Cookie.parse(cookieString[, options])
fromJSON(string)alias for Cookie.fromJSON(string)
getPublicSuffix(hostname)Returns the public suffix of this hostname. The public suffix is the shortest domain-name upon which a cookie can be set. Returns null if the hostname cannot have cookies set for it.
For example: www.example.com and www.subdomain.example.com both have public suffix example.com.
For further information, see http://publicsuffix.org/. This module derives its list from that site. This call is currently a wrapper around psl's get() method.
cookieCompare(a,b)For use with .sort(), sorts a list of cookies into the recommended order given in the RFC (Section 5.4 step 2). The sort algorithm is, in order of precedence:
.path.creation (which has a 1ms precision, same as Date).creationIndex (to get beyond the 1ms precision)var cookies = [ /* unsorted array of Cookie objects */ ];
cookies = cookies.sort(cookieCompare);
Note: Since JavaScript's Date is limited to a 1ms precision, cookies within the same milisecond are entirely possible. This is especially true when using the now option to .setCookie(). The .creationIndex property is a per-process global counter, assigned during construction with new Cookie(). This preserves the spirit of the RFC sorting: older cookies go first. This works great for MemoryCookieStore, since Set-Cookie headers are parsed in order, but may not be so great for distributed systems. Sophisticated Stores may wish to set this to some other logical clock such that if cookies A and B are created in the same millisecond, but cookie A is created before cookie B, then A.creationIndex < B.creationIndex. If you want to alter the global counter, which you probably shouldn't do, it's stored in Cookie.cookiesCreated.
permuteDomain(domain)Generates a list of all possible domains that domainMatch() the parameter. May be handy for implementing cookie stores.
permutePath(path)Generates a list of all possible paths that pathMatch() the parameter. May be handy for implementing cookie stores.
Exported via tough.Cookie.
Cookie.parse(cookieString[, options])Parses a single Cookie or Set-Cookie HTTP header into a Cookie object. Returns undefined if the string can't be parsed.
The options parameter is not required and currently has only one property:
true enable parsing of key-less cookies like =abc and =, which are not RFC-compliant.If options is not an object, it is ignored, which means you can use Array#map with it.
Here's how to process the Set-Cookie header(s) on a node HTTP/HTTPS response:
if (res.headers['set-cookie'] instanceof Array)
cookies = res.headers['set-cookie'].map(Cookie.parse);
else
cookies = [Cookie.parse(res.headers['set-cookie'])];
Note: in version 2.3.3, tough-cookie limited the number of spaces before the = to 256 characters. This limitation has since been removed.
See Issue 92
Cookie object properties:
Date - if set, the Expires= attribute of the cookie (defaults to the string "Infinity"). See setExpires()Max-Age= attribute in seconds of the cookie. May also be set to strings "Infinity" and "-Infinity" for non-expiry and immediate-expiry, respectively. See setMaxAge()Domain= attribute of the cookiePath= of the cookieSecure cookie flagHttpOnly cookie flagArray - any unrecognized cookie attributes as strings (even if equal-signs inside)Date - when this cookie was constructedcookieCompare(a,b) for a full explanation)After a cookie has been passed through CookieJar.setCookie() it will have the following additional attributes:
defaultPath() was used to derive one.Date - modified from construction to when the cookie was added to the jarDate - last time the cookie got accessed. Will affect cookie cleaning once implemented. Using cookiejar.getCookies(...) will update this attribute.