Skip to content

Commit c30c387

Browse files
Merge branch 'main' into feature/configuration-validation
2 parents 89aae53 + 82f8246 commit c30c387

6 files changed

+124
-4
lines changed

src/server/client.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -198,13 +198,15 @@ export class Auth0Client {
198198
const sessionCookieOptions: SessionCookieOptions = {
199199
name: options.session?.cookie?.name ?? "__session",
200200
secure: options.session?.cookie?.secure ?? false,
201-
sameSite: options.session?.cookie?.sameSite ?? "lax"
201+
sameSite: options.session?.cookie?.sameSite ?? "lax",
202+
path: options.session?.cookie?.path ?? "/"
202203
};
203204

204205
const transactionCookieOptions: TransactionCookieOptions = {
205206
prefix: options.transactionCookie?.prefix ?? "__txn_",
206207
secure: options.transactionCookie?.secure ?? false,
207-
sameSite: options.transactionCookie?.sameSite ?? "lax"
208+
sameSite: options.transactionCookie?.sameSite ?? "lax",
209+
path: options.transactionCookie?.path ?? "/"
208210
};
209211

210212
if (appBaseUrl) {

src/server/session/abstract-session-store.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ export interface SessionCookieOptions {
2525
* Default: depends on the protocol of the application's base URL. If the protocol is `https`, then `true`, otherwise `false`.
2626
*/
2727
secure?: boolean;
28+
/**
29+
* The path attribute of the session cookie. Will be set to '/' by default.
30+
*/
31+
path?: string;
2832
}
2933

3034
export interface SessionConfiguration {
@@ -103,7 +107,7 @@ export abstract class AbstractSessionStore {
103107
httpOnly: true,
104108
sameSite: cookieOptions?.sameSite ?? "lax",
105109
secure: cookieOptions?.secure ?? false,
106-
path: "/"
110+
path: cookieOptions?.path ?? "/"
107111
};
108112
}
109113

src/server/session/stateful-session-store.test.ts

+44
Original file line numberDiff line numberDiff line change
@@ -595,6 +595,50 @@ describe("Stateful Session Store", async () => {
595595
expect(cookie?.secure).toEqual(false);
596596
});
597597

598+
it("should apply the path to the cookie", async () => {
599+
const currentTime = Date.now();
600+
const createdAt = Math.floor(currentTime / 1000);
601+
const secret = await generateSecret(32);
602+
const session: SessionData = {
603+
user: { sub: "user_123" },
604+
tokenSet: {
605+
accessToken: "at_123",
606+
refreshToken: "rt_123",
607+
expiresAt: 123456
608+
},
609+
internal: {
610+
sid: "auth0-sid",
611+
createdAt
612+
}
613+
};
614+
const store = {
615+
get: vi.fn().mockResolvedValue(session),
616+
set: vi.fn(),
617+
delete: vi.fn()
618+
};
619+
620+
const requestCookies = new RequestCookies(new Headers());
621+
const responseCookies = new ResponseCookies(new Headers());
622+
623+
const sessionStore = new StatefulSessionStore({
624+
secret,
625+
store,
626+
rolling: true,
627+
absoluteDuration: 3600,
628+
inactivityDuration: 1800,
629+
630+
cookieOptions: {
631+
path: "/custom-path"
632+
}
633+
});
634+
await sessionStore.set(requestCookies, responseCookies, session);
635+
636+
const cookie = responseCookies.get("__session");
637+
638+
expect(cookie).toBeDefined();
639+
expect(cookie?.path).toEqual("/custom-path");
640+
});
641+
598642
it("should apply the cookie name", async () => {
599643
const currentTime = Date.now();
600644
const createdAt = Math.floor(currentTime / 1000);

src/server/session/stateless-session-store.test.ts

+32
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,38 @@ describe("Stateless Session Store", async () => {
496496
expect(cookie?.secure).toEqual(true);
497497
});
498498

499+
it("should apply the path to the cookie", async () => {
500+
const secret = await generateSecret(32);
501+
const session: SessionData = {
502+
user: { sub: "user_123" },
503+
tokenSet: {
504+
accessToken: "at_123",
505+
refreshToken: "rt_123",
506+
expiresAt: 123456
507+
},
508+
internal: {
509+
sid: "auth0-sid",
510+
createdAt: Math.floor(Date.now() / 1000)
511+
}
512+
};
513+
const requestCookies = new RequestCookies(new Headers());
514+
const responseCookies = new ResponseCookies(new Headers());
515+
516+
const sessionStore = new StatelessSessionStore({
517+
secret,
518+
cookieOptions: {
519+
path: '/custom-path'
520+
}
521+
});
522+
await sessionStore.set(requestCookies, responseCookies, session);
523+
524+
const cookie = responseCookies.get("__session");
525+
526+
expect(cookie).toBeDefined();
527+
expect((await decrypt(cookie!.value, secret)).payload).toEqual(session);
528+
expect(cookie?.path).toEqual("/custom-path");
529+
});
530+
499531
it("should apply the cookie name", async () => {
500532
const secret = await generateSecret(32);
501533
const session: SessionData = {

src/server/transaction-store.test.ts

+34
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,40 @@ describe("Transaction Store", async () => {
199199
expect(cookie?.secure).toEqual(false);
200200
});
201201

202+
it("should apply the path to the cookie", async () => {
203+
const secret = await generateSecret(32);
204+
const codeVerifier = oauth.generateRandomCodeVerifier();
205+
const nonce = oauth.generateRandomNonce();
206+
const state = oauth.generateRandomState();
207+
const transactionState: TransactionState = {
208+
nonce,
209+
maxAge: 3600,
210+
codeVerifier: codeVerifier,
211+
responseType: "code",
212+
state,
213+
returnTo: "/dashboard"
214+
};
215+
const headers = new Headers();
216+
const responseCookies = new ResponseCookies(headers);
217+
218+
const transactionStore = new TransactionStore({
219+
secret,
220+
cookieOptions: {
221+
path: "/custom-path"
222+
}
223+
});
224+
await transactionStore.save(responseCookies, transactionState);
225+
226+
const cookieName = `__txn_${state}`;
227+
const cookie = responseCookies.get(cookieName);
228+
229+
expect(cookie).toBeDefined();
230+
expect((await decrypt(cookie!.value, secret)).payload).toEqual(
231+
transactionState
232+
);
233+
expect(cookie?.path).toEqual("/custom-path");
234+
});
235+
202236
it("should apply the cookie prefix to the cookie name", async () => {
203237
const secret = await generateSecret(32);
204238
const codeVerifier = oauth.generateRandomCodeVerifier();

src/server/transaction-store.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ export interface TransactionCookieOptions {
3232
* Default: depends on the protocol of the application's base URL. If the protocol is `https`, then `true`, otherwise `false`.
3333
*/
3434
secure?: boolean;
35+
/**
36+
* The path attribute of the transaction cookie. Will be set to '/' by default.
37+
*/
38+
path?: string;
3539
}
3640

3741
export interface TransactionStoreOptions {
@@ -57,7 +61,7 @@ export class TransactionStore {
5761
httpOnly: true,
5862
sameSite: cookieOptions?.sameSite ?? "lax", // required to allow the cookie to be sent on the callback request
5963
secure: cookieOptions?.secure ?? false,
60-
path: "/",
64+
path: cookieOptions?.path ?? "/",
6165
maxAge: 60 * 60 // 1 hour in seconds
6266
};
6367
}

0 commit comments

Comments
 (0)