Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions src/server/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -200,13 +200,15 @@ export class Auth0Client {
const sessionCookieOptions: SessionCookieOptions = {
name: options.session?.cookie?.name ?? "__session",
secure: options.session?.cookie?.secure ?? false,
sameSite: options.session?.cookie?.sameSite ?? "lax"
sameSite: options.session?.cookie?.sameSite ?? "lax",
path: options.session?.cookie?.path ?? "/"
};

const transactionCookieOptions: TransactionCookieOptions = {
prefix: options.transactionCookie?.prefix ?? "__txn_",
secure: options.transactionCookie?.secure ?? false,
sameSite: options.transactionCookie?.sameSite ?? "lax"
sameSite: options.transactionCookie?.sameSite ?? "lax",
path: options.transactionCookie?.path ?? "/"
};

if (appBaseUrl) {
Expand Down
6 changes: 5 additions & 1 deletion src/server/session/abstract-session-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ export interface SessionCookieOptions {
* Default: depends on the protocol of the application's base URL. If the protocol is `https`, then `true`, otherwise `false`.
*/
secure?: boolean;
/**
* The path attribute of the session cookie. Will be set to '/' by default.
*/
path?: string;
}

export interface SessionConfiguration {
Expand Down Expand Up @@ -103,7 +107,7 @@ export abstract class AbstractSessionStore {
httpOnly: true,
sameSite: cookieOptions?.sameSite ?? "lax",
secure: cookieOptions?.secure ?? false,
path: "/"
path: cookieOptions?.path ?? "/"
};
}

Expand Down
44 changes: 44 additions & 0 deletions src/server/session/stateful-session-store.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,50 @@ describe("Stateful Session Store", async () => {
expect(cookie?.secure).toEqual(false);
});

it("should apply the path to the cookie", async () => {
const currentTime = Date.now();
const createdAt = Math.floor(currentTime / 1000);
const secret = await generateSecret(32);
const session: SessionData = {
user: { sub: "user_123" },
tokenSet: {
accessToken: "at_123",
refreshToken: "rt_123",
expiresAt: 123456
},
internal: {
sid: "auth0-sid",
createdAt
}
};
const store = {
get: vi.fn().mockResolvedValue(session),
set: vi.fn(),
delete: vi.fn()
};

const requestCookies = new RequestCookies(new Headers());
const responseCookies = new ResponseCookies(new Headers());

const sessionStore = new StatefulSessionStore({
secret,
store,
rolling: true,
absoluteDuration: 3600,
inactivityDuration: 1800,

cookieOptions: {
path: "/custom-path"
}
});
await sessionStore.set(requestCookies, responseCookies, session);

const cookie = responseCookies.get("__session");

expect(cookie).toBeDefined();
expect(cookie?.path).toEqual("/custom-path");
});

it("should apply the cookie name", async () => {
const currentTime = Date.now();
const createdAt = Math.floor(currentTime / 1000);
Expand Down
32 changes: 32 additions & 0 deletions src/server/session/stateless-session-store.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,38 @@ describe("Stateless Session Store", async () => {
expect(cookie?.secure).toEqual(true);
});

it("should apply the path to the cookie", async () => {
const secret = await generateSecret(32);
const session: SessionData = {
user: { sub: "user_123" },
tokenSet: {
accessToken: "at_123",
refreshToken: "rt_123",
expiresAt: 123456
},
internal: {
sid: "auth0-sid",
createdAt: Math.floor(Date.now() / 1000)
}
};
const requestCookies = new RequestCookies(new Headers());
const responseCookies = new ResponseCookies(new Headers());

const sessionStore = new StatelessSessionStore({
secret,
cookieOptions: {
path: '/custom-path'
}
});
await sessionStore.set(requestCookies, responseCookies, session);

const cookie = responseCookies.get("__session");

expect(cookie).toBeDefined();
expect((await decrypt(cookie!.value, secret)).payload).toEqual(session);
expect(cookie?.path).toEqual("/custom-path");
});

it("should apply the cookie name", async () => {
const secret = await generateSecret(32);
const session: SessionData = {
Expand Down
34 changes: 34 additions & 0 deletions src/server/transaction-store.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,40 @@ describe("Transaction Store", async () => {
expect(cookie?.secure).toEqual(false);
});

it("should apply the path to the cookie", async () => {
const secret = await generateSecret(32);
const codeVerifier = oauth.generateRandomCodeVerifier();
const nonce = oauth.generateRandomNonce();
const state = oauth.generateRandomState();
const transactionState: TransactionState = {
nonce,
maxAge: 3600,
codeVerifier: codeVerifier,
responseType: "code",
state,
returnTo: "/dashboard"
};
const headers = new Headers();
const responseCookies = new ResponseCookies(headers);

const transactionStore = new TransactionStore({
secret,
cookieOptions: {
path: "/custom-path"
}
});
await transactionStore.save(responseCookies, transactionState);

const cookieName = `__txn_${state}`;
const cookie = responseCookies.get(cookieName);

expect(cookie).toBeDefined();
expect((await decrypt(cookie!.value, secret)).payload).toEqual(
transactionState
);
expect(cookie?.path).toEqual("/custom-path");
});

it("should apply the cookie prefix to the cookie name", async () => {
const secret = await generateSecret(32);
const codeVerifier = oauth.generateRandomCodeVerifier();
Expand Down
6 changes: 5 additions & 1 deletion src/server/transaction-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ export interface TransactionCookieOptions {
* Default: depends on the protocol of the application's base URL. If the protocol is `https`, then `true`, otherwise `false`.
*/
secure?: boolean;
/**
* The path attribute of the transaction cookie. Will be set to '/' by default.
*/
path?: string;
}

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