File size: 6,101 Bytes
5fae594
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# Tough Cookie · [![RFC6265][rfc6265-badge]][rfc6265-tracker] [![RFC6265bis][rfc6265bis-badge]][rfc6265bis-tracker] [![npm version][npm-badge]][npm-repo] [![CI on Github Actions: salesforce/tough-cookie][ci-badge]][ci-url] ![PRs Welcome][prs-welcome-badge]

A Node.js implementation of [RFC6265][rfc6265-tracker] for cookie parsing, storage, and retrieval.

## Getting Started

Install Tough Cookie using [`npm`][npm-repo]:

```shell
npm install tough-cookie
```

or [`yarn`][yarn-repo]:

```shell
yarn add tough-cookie
```

## Usage

```typescript
import { Cookie, CookieJar } from 'tough-cookie'

// parse a `Cookie` request header
const reqCookies = 'ID=298zf09hf012fh2; csrf=u32t4o3tb3gg43; _gat=1'.split(';').map(Cookie.parse)
// generate a `Cookie` request header
const cookieHeader = reqCookies.map(cookie => cookie.cookieString()).join(';')

// parse a Set-Cookie response header
const resCookie = Cookie.parse('foo=bar; Domain=example.com; Path=/; Expires=Tue, 21 Oct 2025 00:00:00 GMT')
// generate a Set-Cookie response header
const setCookieHeader = cookie.toString()

// store and retrieve cookies
const cookieJar = new CookieJar() // uses the in-memory store by default
await cookieJar.setCookie(resCookie, 'https://example.com/')
const matchingCookies = await cookieJar.getCookies('https://example.com/')
```

> [!IMPORTANT]
> For more detailed usage information, refer to the [API docs](./api/docs/tough-cookie.md).

## RFC6265bis

Support for [RFC6265bis][rfc6265bis-tracker] is being developed. As these revisions to [RFC6252][rfc6265-tracker] are
still in `Active Internet-Draft` state, the areas of support that follow are subject to change.

### SameSite Cookies

This change makes it possible for servers, and supporting clients, to mitigate certain types of CSRF
attacks by disallowing `SameSite` cookies from being sent cross-origin.

#### Example

```typescript
import { CookieJar } from 'tough-cookie'

const cookieJar = new CookieJar() // uses the in-memory store by default

// storing cookies with various SameSite attributes
await cookieJar.setCookie('strict=authorized; SameSite=strict', 'http://example.com/index.html')
await cookieJar.setCookie('lax=okay; SameSite=lax', 'http://example.com/index.html')
await cookieJar.setCookie('normal=whatever', 'http://example.com/index.html')

// retrieving cookies using a SameSite context
const laxCookies = await cookieJar.getCookies('http://example.com/index.html', {
  // the first cookie (strict=authorized) will not be returned if the context is 'lax'
  // but the other two cookies will be returned
  sameSiteContext: 'lax',
})
```

> [!NOTE]
> It is highly recommended that you read [RFC6265bis - Section 8.8][samesite-implementation] for more details on SameSite cookies, security considerations, and defense in depth.

### Cookie Prefixes

Cookie prefixes are a way to indicate that a given cookie was set with a set of attributes simply by
inspecting the first few characters of the cookie's name.

Two prefixes are defined:

- `"__Secure-"`

  If a cookie's name begins with a case-sensitive match for the string `__Secure-`, then the cookie was set with a "Secure" attribute.

- `"__Host-"`

  If a cookie's name begins with a case-sensitive match for the string `__Host-`, then the cookie was set with a "Secure" attribute, a "Path" attribute with a value of "/", and no "Domain" attribute.

If `prefixSecurity` is enabled for `CookieJar`, then cookies that match the prefixes defined above but do
not obey the attribute restrictions are not added.

You can define this functionality by passing in the `prefixSecurity` option to `CookieJar`. It can be one of 3 values:

1. `silent`: (**default**) Enable cookie prefix checking but silently fail to add the cookie if conditions are not met.
2. `strict`: Enable cookie prefix checking and error out if conditions are not met.
3. `unsafe-disabled`: Disable cookie prefix checking.

> If `ignoreError` is passed in as `true` when setting a cookie then the error is silent regardless of the `prefixSecurity` option (assuming it's enabled).

#### Example

```typescript
import { CookieJar, MemoryCookieStore } from 'tough-cookie'

const cookieJar = new CookieJar(new MemoryCookieStore(), {
  prefixSecurity: 'silent'
})

// this cookie will be silently ignored since the url is insecure (http)
await cookieJar.setCookie(
  '__Secure-SID=12345; Domain=example.com; Secure;',
  'http://example.com',
)

// this cookie will be stored since the url is secure (https)
await cookieJar.setCookie(
  '__Secure-SID=12345; Domain=example.com; Secure;',
  'https://example.com',
)
```

> [!NOTE]
> It is highly recommended that you read [RFC6265bis - Section 4.1.3][cookie-prefixes-implementation] for more details on Cookie Prefixes.

## Node.js Version Support

We follow the [Node.js release schedule](https://github.com/nodejs/Release#release-schedule) and support
all versions that are in Active LTS or Maintenance. We will always do a major release when dropping support
for older versions of node, and we will do so in consultation with our community.

[npm-badge]: https://img.shields.io/npm/v/tough-cookie.svg?style=flat
[npm-repo]: https://www.npmjs.com/package/tough-cookie
[ci-badge]: https://github.com/salesforce/tough-cookie/actions/workflows/integration.yaml/badge.svg
[ci-url]: https://github.com/salesforce/tough-cookie/actions/workflows/integration.yaml
[rfc6265-badge]: https://img.shields.io/badge/RFC-6265-flat?labelColor=000000&color=666666
[rfc6265-tracker]: https://datatracker.ietf.org/doc/rfc6265/
[rfc6265bis-badge]: https://img.shields.io/badge/RFC-6265bis-flat?labelColor=000000&color=666666
[rfc6265bis-tracker]: https://datatracker.ietf.org/doc/draft-ietf-httpbis-rfc6265bis/
[samesite-implementation]: https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis-02#section-8.8
[cookie-prefixes-implementation]: https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis-02#section-4.1.3
[prs-welcome-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg
[yarn-repo]: https://yarnpkg.com/package?name=tough-cookie