0
# Cookie and Session Implementations
1
2
Node.js-specific implementations of cookie and session utilities using cookie-signature for secure signing and various storage strategies.
3
4
## Capabilities
5
6
### Create Cookie
7
8
Creates a cookie with Node.js-specific signing using the cookie-signature library.
9
10
```typescript { .api }
11
/**
12
* Creates a cookie with Node.js-specific signing
13
* @param name - The name of the cookie
14
* @param cookieOptions - Configuration options for the cookie
15
* @returns Cookie instance
16
*/
17
function createCookie(name: string, cookieOptions?: CookieOptions): Cookie;
18
```
19
20
**Usage Examples:**
21
22
```typescript
23
import { createCookie } from "@remix-run/node";
24
25
// Basic cookie
26
const sessionCookie = createCookie("__session");
27
28
// Cookie with options
29
const secureCookie = createCookie("user-prefs", {
30
maxAge: 86400, // 24 hours
31
httpOnly: true,
32
secure: process.env.NODE_ENV === "production",
33
sameSite: "lax",
34
secrets: ["cookie-secret-key"]
35
});
36
37
// Use in a Remix loader
38
export async function loader({ request }: LoaderFunctionArgs) {
39
const cookieHeader = request.headers.get("Cookie");
40
const userPrefs = await secureCookie.parse(cookieHeader);
41
42
return json({ preferences: userPrefs });
43
}
44
45
// Use in a Remix action
46
export async function action({ request }: ActionFunctionArgs) {
47
const formData = await request.formData();
48
const theme = formData.get("theme");
49
50
return redirect("/", {
51
headers: {
52
"Set-Cookie": await secureCookie.serialize({ theme })
53
}
54
});
55
}
56
```
57
58
### Create Cookie Session Storage
59
60
Creates cookie-based session storage where session data is stored in the cookie itself.
61
62
```typescript { .api }
63
/**
64
* Creates cookie-based session storage
65
* @param options - Configuration options for cookie session storage
66
* @returns SessionStorage instance that stores data in cookies
67
*/
68
function createCookieSessionStorage<Data = SessionData, FlashData = Data>(
69
options: CookieSessionStorageOptions
70
): SessionStorage<Data, FlashData>;
71
```
72
73
**Usage Examples:**
74
75
```typescript
76
import { createCookieSessionStorage } from "@remix-run/node";
77
78
// Basic cookie session storage
79
const sessionStorage = createCookieSessionStorage({
80
cookie: {
81
name: "__session",
82
secrets: ["session-secret"],
83
maxAge: 86400 // 24 hours
84
}
85
});
86
87
// Advanced configuration
88
const sessionStorage = createCookieSessionStorage({
89
cookie: {
90
name: "__session",
91
secrets: ["primary-secret", "fallback-secret"],
92
maxAge: 86400,
93
httpOnly: true,
94
secure: process.env.NODE_ENV === "production",
95
sameSite: "lax",
96
path: "/",
97
domain: process.env.NODE_ENV === "production" ? ".example.com" : undefined
98
}
99
});
100
101
// Use in authentication
102
export async function loader({ request }: LoaderFunctionArgs) {
103
const session = await sessionStorage.getSession(
104
request.headers.get("Cookie")
105
);
106
107
const userId = session.get("userId");
108
const user = userId ? await getUserById(userId) : null;
109
110
return json({ user });
111
}
112
113
export async function action({ request }: ActionFunctionArgs) {
114
const formData = await request.formData();
115
const email = String(formData.get("email"));
116
const password = String(formData.get("password"));
117
118
const user = await authenticateUser(email, password);
119
120
if (user) {
121
const session = await sessionStorage.getSession();
122
session.set("userId", user.id);
123
124
return redirect("/dashboard", {
125
headers: {
126
"Set-Cookie": await sessionStorage.commitSession(session)
127
}
128
});
129
}
130
131
return json({ error: "Invalid credentials" }, { status: 400 });
132
}
133
```
134
135
### Create Session Storage
136
137
Creates generic session storage with custom storage strategy.
138
139
```typescript { .api }
140
/**
141
* Creates session storage with custom storage strategy
142
* @param options - Configuration options including storage strategy
143
* @returns SessionStorage instance with custom storage
144
*/
145
function createSessionStorage<Data = SessionData, FlashData = Data>(
146
options: SessionStorageOptions<Data, FlashData>
147
): SessionStorage<Data, FlashData>;
148
```
149
150
**Usage Examples:**
151
152
```typescript
153
import { createSessionStorage } from "@remix-run/node";
154
155
// Custom database session storage
156
const databaseSessionStorage = createSessionStorage({
157
cookie: {
158
name: "__session",
159
secrets: ["session-secret"],
160
maxAge: 86400
161
},
162
async createData(data, expires) {
163
const sessionId = generateId();
164
await db.sessions.create({
165
id: sessionId,
166
data: JSON.stringify(data),
167
expires
168
});
169
return sessionId;
170
},
171
async readData(id) {
172
const session = await db.sessions.findUnique({ where: { id } });
173
if (!session || (session.expires && session.expires < new Date())) {
174
return null;
175
}
176
return JSON.parse(session.data);
177
},
178
async updateData(id, data, expires) {
179
await db.sessions.update({
180
where: { id },
181
data: {
182
data: JSON.stringify(data),
183
expires
184
}
185
});
186
},
187
async deleteData(id) {
188
await db.sessions.delete({ where: { id } });
189
}
190
});
191
```
192
193
### Create Memory Session Storage
194
195
Creates in-memory session storage for development and testing.
196
197
```typescript { .api }
198
/**
199
* Creates in-memory session storage
200
* @param options - Optional configuration for memory session storage
201
* @returns SessionStorage instance that stores data in memory
202
*/
203
function createMemorySessionStorage<Data = SessionData, FlashData = Data>(
204
options?: MemorySessionStorageOptions
205
): SessionStorage<Data, FlashData>;
206
```
207
208
**Usage Examples:**
209
210
```typescript
211
import { createMemorySessionStorage } from "@remix-run/node";
212
213
// Basic memory session storage
214
const sessionStorage = createMemorySessionStorage();
215
216
// With custom cookie configuration
217
const sessionStorage = createMemorySessionStorage({
218
cookie: {
219
name: "__session",
220
maxAge: 3600, // 1 hour
221
httpOnly: true,
222
secure: false // OK for development
223
}
224
});
225
226
// Development authentication
227
export async function loader({ request }: LoaderFunctionArgs) {
228
const session = await sessionStorage.getSession(
229
request.headers.get("Cookie")
230
);
231
232
const user = session.get("user");
233
234
return json({ user });
235
}
236
237
export async function action({ request }: ActionFunctionArgs) {
238
const session = await sessionStorage.getSession(
239
request.headers.get("Cookie")
240
);
241
242
// Store user in memory session
243
session.set("user", { id: 1, name: "Test User" });
244
245
return redirect("/", {
246
headers: {
247
"Set-Cookie": await sessionStorage.commitSession(session)
248
}
249
});
250
}
251
```
252
253
## Session Storage Types
254
255
All session storage implementations provide the same interface:
256
257
```typescript { .api }
258
interface SessionStorage<Data = SessionData, FlashData = Data> {
259
/**
260
* Parses a Cookie header and returns a Session or null if cookie is invalid
261
*/
262
getSession(cookieHeader?: string | null): Promise<Session<Data, FlashData>>;
263
264
/**
265
* Stores all data in the session and returns a Set-Cookie header
266
*/
267
commitSession(
268
session: Session<Data, FlashData>,
269
options?: CookieSerializeOptions
270
): Promise<string>;
271
272
/**
273
* Destroys the session and returns a Set-Cookie header that expires the cookie
274
*/
275
destroySession(
276
session: Session<Data, FlashData>,
277
options?: CookieSerializeOptions
278
): Promise<string>;
279
}
280
281
interface Session<Data = SessionData, FlashData = Data> {
282
/** Unique session identifier */
283
readonly id: string;
284
/** Session data */
285
readonly data: Partial<Data>;
286
287
/** Check if the session has a value for the given key */
288
has(key: keyof Data | keyof FlashData): boolean;
289
290
/** Get a value from the session */
291
get<Key extends keyof Data>(key: Key): Data[Key] | undefined;
292
293
/** Set a value in the session */
294
set<Key extends keyof Data>(key: Key, value: Data[Key]): void;
295
296
/** Flash a value that will be available only on the next request */
297
flash<Key extends keyof FlashData>(key: Key, value: FlashData[Key]): void;
298
299
/** Remove a value from the session */
300
unset(key: keyof Data | keyof FlashData): void;
301
}
302
```
303
304
## Security Features
305
306
- **Cookie Signing**: All cookies are signed using cookie-signature for tamper detection
307
- **Secret Rotation**: Support for multiple secrets to enable secret rotation
308
- **Secure Defaults**: HTTPOnly, Secure, and SameSite attributes configured appropriately
309
- **Expiration Handling**: Automatic cleanup of expired sessions
310
- **Data Integrity**: Signed cookies prevent client-side tampering
311
312
## Storage Strategy Comparison
313
314
| Storage Type | Data Location | Capacity | Performance | Persistence |
315
|--------------|---------------|----------|-------------|-------------|
316
| Cookie | Client browser | ~4KB | Fast | Browser-dependent |
317
| Memory | Server RAM | Unlimited | Fastest | Process lifetime |
318
| File | Server filesystem | Unlimited | Good | Persistent |
319
| Custom | User-defined | Varies | Varies | User-defined |