From c4380a4a166a808b07d57f9909d76472ec3e7d1e Mon Sep 17 00:00:00 2001
From: Paul Vaneveld
Date: Wed, 17 Sep 2025 16:43:16 +0200
Subject: [PATCH 1/8] fix: fialing tests
---
packages/express-adapter/src/cookies.test.ts | 6 +++---
packages/fastify-adapter/src/cookies.test.ts | 6 +++---
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/packages/express-adapter/src/cookies.test.ts b/packages/express-adapter/src/cookies.test.ts
index 9898fba..e131e25 100644
--- a/packages/express-adapter/src/cookies.test.ts
+++ b/packages/express-adapter/src/cookies.test.ts
@@ -114,7 +114,7 @@ describe("CookieTokenSource", () => {
sameSite: "strict",
domain: undefined,
expires: undefined,
- path: "/",
+ path: undefined,
});
});
@@ -139,7 +139,7 @@ describe("CookieTokenSource", () => {
secure: true,
sameSite: "strict",
domain: undefined,
- path: "/",
+ path: undefined,
expires: expect.any(Date),
});
});
@@ -164,7 +164,7 @@ describe("CookieTokenSource", () => {
sameSite: "strict",
expires: undefined,
domain: undefined,
- path: "/",
+ path: undefined,
});
});
diff --git a/packages/fastify-adapter/src/cookies.test.ts b/packages/fastify-adapter/src/cookies.test.ts
index 72189d9..401bef8 100644
--- a/packages/fastify-adapter/src/cookies.test.ts
+++ b/packages/fastify-adapter/src/cookies.test.ts
@@ -126,7 +126,7 @@ describe("CookieTokenSource", () => {
sameSite: "strict",
domain: undefined,
expires: undefined,
- path: "/",
+ path: undefined,
});
});
@@ -151,7 +151,7 @@ describe("CookieTokenSource", () => {
secure: true,
sameSite: "strict",
domain: undefined,
- path: "/",
+ path: undefined,
expires: expect.any(Date),
});
});
@@ -176,7 +176,7 @@ describe("CookieTokenSource", () => {
sameSite: "strict",
domain: undefined,
expires: undefined,
- path: "/",
+ path: undefined,
});
});
From b13077b305105003fcf14b696f1e9a45a81ccf10 Mon Sep 17 00:00:00 2001
From: Paul Vaneveld
Date: Wed, 17 Sep 2025 16:54:55 +0200
Subject: [PATCH 2/8] feat: add refresh token and auth token path option
---
.../core/src/tokensource/cookies-base.test.ts | 39 ++++++++++++++++---
packages/core/src/tokensource/cookies-base.ts | 24 ++++++++----
packages/express-adapter/src/cookies.ts | 4 +-
packages/fastify-adapter/src/cookies.test.ts | 2 +-
packages/fastify-adapter/src/cookies.ts | 4 +-
5 files changed, 56 insertions(+), 17 deletions(-)
diff --git a/packages/core/src/tokensource/cookies-base.test.ts b/packages/core/src/tokensource/cookies-base.test.ts
index 1c7d560..21c2a59 100644
--- a/packages/core/src/tokensource/cookies-base.test.ts
+++ b/packages/core/src/tokensource/cookies-base.test.ts
@@ -1,5 +1,5 @@
import { parse, type SerializeOptions, serialize } from "cookie";
-import { describe, expect, it } from "vitest";
+import { describe, expect, it, } from "vitest";
import {
type BaseCookieSourceOptions,
BaseCookieTokenSource,
@@ -13,7 +13,7 @@ import {
* support multiple Set-Cookie headers, so we just 'join' them with a comma.
*/
class TestAdapter implements CookieAdapter {
- constructor(private options: BaseCookieSourceOptions) {}
+ constructor(private options: BaseCookieSourceOptions) {}
getCookie(request: Request, name: string): string | undefined {
const header = request.headers.get("cookie");
@@ -55,7 +55,7 @@ class TestAdapter implements CookieAdapter {
class TestCookieTokenSource extends BaseCookieTokenSource {
protected adapter: CookieAdapter;
- constructor(options: BaseCookieSourceOptions) {
+ constructor(options: BaseCookieSourceOptions) {
super(options);
this.adapter = new TestAdapter(options);
}
@@ -282,7 +282,7 @@ describe("CookieTokenSource", () => {
cookieTokenSource.deleteAccessToken(request, response);
const cookies = getCookies(response);
- expect(cookies).toEqual([{ userToken: "" }, { guestToken: "" }]);
+ expect(cookies).toEqual([{ userToken: "", Path: "/" }, { guestToken: "", Path: "/" }]);
});
// Test for deleting refresh tokens
@@ -305,8 +305,8 @@ describe("CookieTokenSource", () => {
const cookies = getCookies(response);
expect(cookies).toEqual([
{ refreshToken: "", Path: "/refresh" },
- { guestRefreshTokenExists: "" },
- { userRefreshTokenExists: "" },
+ { guestRefreshTokenExists: "" , Path: "/"},
+ { userRefreshTokenExists: "" , Path: "/"},
]);
});
@@ -330,4 +330,31 @@ describe("CookieTokenSource", () => {
const cookies = getCookies(response);
expect(cookies).toEqual([{ refreshToken: "", Path: "/refresh" }]);
});
+
+ it("should get the refresh path from the refresh path function", () => {
+ const request: Request = new Request("http://localhost");
+
+ const cookieTokenSource = new TestCookieTokenSource({
+ secure: true,
+ sameSite: "strict",
+ refreshTokenPath: () => "/refresh",
+ });
+
+ const result = cookieTokenSource["_getRefreshTokenPath"](request);
+ expect(result).toBe("/refresh");
+ });
+
+ it("should get the cookiePath from the cookiePath function", () => {
+ const request: Request = new Request("http://localhost");
+
+ const cookieTokenSource = new TestCookieTokenSource({
+ secure: true,
+ sameSite: "strict",
+ refreshTokenPath: "/refresh",
+ cookiePathFn: () => "/cookie",
+ });
+
+ const result = cookieTokenSource["options"].cookiePathFn?.(request);
+ expect(result).toBe("/cookie");
+ });
});
diff --git a/packages/core/src/tokensource/cookies-base.ts b/packages/core/src/tokensource/cookies-base.ts
index dd7d028..c1faf83 100644
--- a/packages/core/src/tokensource/cookies-base.ts
+++ b/packages/core/src/tokensource/cookies-base.ts
@@ -63,14 +63,15 @@ type CookieSettings = {
expiresIn: number | "session";
};
-export type BaseCookieSourceOptions = {
+export type BaseCookieSourceOptions = {
secure: boolean;
sameSite: "strict" | "lax" | "none" | boolean;
- refreshTokenPath: string;
+ refreshTokenPath: string | ((request: TRequest) => string | undefined);
cookieNames?: Partial;
guestToken?: CookieSettings;
userToken?: CookieSettings;
refreshToken?: CookieSettings;
+ cookiePathFn?: (request: TRequest) => string | undefined;
};
export abstract class BaseCookieTokenSource
@@ -79,7 +80,7 @@ export abstract class BaseCookieTokenSource
protected cookieNames: CookieNames;
protected abstract adapter: CookieAdapter;
- constructor(protected options: BaseCookieSourceOptions) {
+ constructor(protected options: BaseCookieSourceOptions) {
this.cookieNames = {
...DEFAULT_COOKIE_NAMES,
...(options.cookieNames ?? {}),
@@ -96,7 +97,7 @@ export abstract class BaseCookieTokenSource
deleteRefreshToken(request: TRequest, response: TResponse): void {
this.adapter.clearCookie(request, response, this.cookieNames.refreshToken, {
- path: this.options.refreshTokenPath,
+ path: this._getRefreshTokenPath(request),
domain: this.adapter.getPrivateDomain(request),
});
@@ -128,6 +129,7 @@ export abstract class BaseCookieTokenSource
if (this.adapter.getCookie(request, name)) {
this.adapter.clearCookie(request, response, name, {
domain: this.adapter.getPublicDomain(request),
+ path: this.options.cookiePathFn?.(request) ?? "/",
});
}
}
@@ -140,6 +142,7 @@ export abstract class BaseCookieTokenSource
if (this.adapter.getCookie(request, name)) {
this.adapter.clearCookie(request, response, name, {
domain: this.adapter.getPublicDomain(request),
+ path: this.options.cookiePathFn?.(request) ?? "/",
});
}
}
@@ -180,7 +183,7 @@ export abstract class BaseCookieTokenSource
opts.expiresIn === "session"
? undefined
: new Date(Date.now() + opts.expiresIn * 1000),
- path: "/",
+ path: this.options.cookiePathFn?.(request) ?? "/",
};
if (isAuthenticated) {
@@ -189,7 +192,7 @@ export abstract class BaseCookieTokenSource
response,
this.cookieNames.userData,
token,
- cookieOptions,
+ cookieOptions
);
this.deleteAccessTokenByName(
request,
@@ -244,7 +247,7 @@ export abstract class BaseCookieTokenSource
opts.expiresIn === "session"
? undefined
: new Date(Date.now() + opts.expiresIn * 1000),
- path: "/",
+ path: this.options.cookiePathFn?.(request) ?? "/",
};
if (isAuthenticated) {
@@ -299,7 +302,7 @@ export abstract class BaseCookieTokenSource
{
...cookieOptions,
httpOnly: true,
- path: this.options.refreshTokenPath,
+ path: this._getRefreshTokenPath(request),
},
);
@@ -331,4 +334,9 @@ export abstract class BaseCookieTokenSource
);
}
}
+
+ private _getRefreshTokenPath(req: TRequest): string | undefined {
+ const path = this.options.refreshTokenPath;
+ return typeof path === "function" ? path(req) : path;
+ }
}
diff --git a/packages/express-adapter/src/cookies.ts b/packages/express-adapter/src/cookies.ts
index 0e77239..31dafbf 100644
--- a/packages/express-adapter/src/cookies.ts
+++ b/packages/express-adapter/src/cookies.ts
@@ -5,9 +5,11 @@ import {
} from "@labdigital/federated-token/tokensource";
import type { CookieOptions, Request, Response } from "express";
-type ExpressCookieSourceOptions = BaseCookieSourceOptions & {
+type ExpressCookieSourceOptions = BaseCookieSourceOptions & {
+ refreshTokenPath: string | ((request: Request) => string | undefined);
publicDomainFn?: (request: Request) => string | undefined;
privateDomainFn?: (request: Request) => string | undefined;
+ cookiePathFn?: (request: Request) => string | undefined;
};
class ExpressCookieAdapter implements CookieAdapter {
diff --git a/packages/fastify-adapter/src/cookies.test.ts b/packages/fastify-adapter/src/cookies.test.ts
index 401bef8..46edbd9 100644
--- a/packages/fastify-adapter/src/cookies.test.ts
+++ b/packages/fastify-adapter/src/cookies.test.ts
@@ -1,6 +1,6 @@
import type { CookieSerializeOptions } from "@fastify/cookie";
import type { FastifyReply, FastifyRequest } from "fastify";
-import { describe, expect, it } from "vitest";
+import { describe, expect, it, } from "vitest";
import { CookieTokenSource } from "./cookies";
type CookieValue = {
diff --git a/packages/fastify-adapter/src/cookies.ts b/packages/fastify-adapter/src/cookies.ts
index 4f9159b..1086cb2 100644
--- a/packages/fastify-adapter/src/cookies.ts
+++ b/packages/fastify-adapter/src/cookies.ts
@@ -6,9 +6,11 @@ import {
} from "@labdigital/federated-token/tokensource";
import type { FastifyReply, FastifyRequest } from "fastify";
-type FastifyCookieSourceOptions = BaseCookieSourceOptions & {
+type FastifyCookieSourceOptions = BaseCookieSourceOptions & {
+ refreshTokenPath: string | ((request: Request) => string | undefined);
publicDomainFn?: (request: FastifyRequest) => string | undefined;
privateDomainFn?: (request: FastifyRequest) => string | undefined;
+ cookiePathFn?: (request: Request) => string | undefined;
};
class FastifyCookieAdapter
From e4e2f8960cde104e9c5fa35ecb715ae8778ddbe9 Mon Sep 17 00:00:00 2001
From: Paul Vaneveld
Date: Wed, 17 Sep 2025 16:56:07 +0200
Subject: [PATCH 3/8] Revert "fix: fialing tests"
This reverts commit c4380a4a166a808b07d57f9909d76472ec3e7d1e.
---
packages/express-adapter/src/cookies.test.ts | 6 +++---
packages/fastify-adapter/src/cookies.test.ts | 6 +++---
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/packages/express-adapter/src/cookies.test.ts b/packages/express-adapter/src/cookies.test.ts
index e131e25..9898fba 100644
--- a/packages/express-adapter/src/cookies.test.ts
+++ b/packages/express-adapter/src/cookies.test.ts
@@ -114,7 +114,7 @@ describe("CookieTokenSource", () => {
sameSite: "strict",
domain: undefined,
expires: undefined,
- path: undefined,
+ path: "/",
});
});
@@ -139,7 +139,7 @@ describe("CookieTokenSource", () => {
secure: true,
sameSite: "strict",
domain: undefined,
- path: undefined,
+ path: "/",
expires: expect.any(Date),
});
});
@@ -164,7 +164,7 @@ describe("CookieTokenSource", () => {
sameSite: "strict",
expires: undefined,
domain: undefined,
- path: undefined,
+ path: "/",
});
});
diff --git a/packages/fastify-adapter/src/cookies.test.ts b/packages/fastify-adapter/src/cookies.test.ts
index 46edbd9..274cfb7 100644
--- a/packages/fastify-adapter/src/cookies.test.ts
+++ b/packages/fastify-adapter/src/cookies.test.ts
@@ -126,7 +126,7 @@ describe("CookieTokenSource", () => {
sameSite: "strict",
domain: undefined,
expires: undefined,
- path: undefined,
+ path: "/",
});
});
@@ -151,7 +151,7 @@ describe("CookieTokenSource", () => {
secure: true,
sameSite: "strict",
domain: undefined,
- path: undefined,
+ path: "/",
expires: expect.any(Date),
});
});
@@ -176,7 +176,7 @@ describe("CookieTokenSource", () => {
sameSite: "strict",
domain: undefined,
expires: undefined,
- path: undefined,
+ path: "/",
});
});
From f51ce5de76b6c092572051d2c1c4cd361874e73f Mon Sep 17 00:00:00 2001
From: Paul Vaneveld
Date: Wed, 17 Sep 2025 16:57:14 +0200
Subject: [PATCH 4/8] fix: linting
---
packages/core/src/tokensource/cookies-base.test.ts | 11 +++++++----
packages/core/src/tokensource/cookies-base.ts | 2 +-
packages/fastify-adapter/src/cookies.test.ts | 2 +-
3 files changed, 9 insertions(+), 6 deletions(-)
diff --git a/packages/core/src/tokensource/cookies-base.test.ts b/packages/core/src/tokensource/cookies-base.test.ts
index 21c2a59..fcecafb 100644
--- a/packages/core/src/tokensource/cookies-base.test.ts
+++ b/packages/core/src/tokensource/cookies-base.test.ts
@@ -1,5 +1,5 @@
import { parse, type SerializeOptions, serialize } from "cookie";
-import { describe, expect, it, } from "vitest";
+import { describe, expect, it } from "vitest";
import {
type BaseCookieSourceOptions,
BaseCookieTokenSource,
@@ -282,7 +282,10 @@ describe("CookieTokenSource", () => {
cookieTokenSource.deleteAccessToken(request, response);
const cookies = getCookies(response);
- expect(cookies).toEqual([{ userToken: "", Path: "/" }, { guestToken: "", Path: "/" }]);
+ expect(cookies).toEqual([
+ { userToken: "", Path: "/" },
+ { guestToken: "", Path: "/" },
+ ]);
});
// Test for deleting refresh tokens
@@ -305,8 +308,8 @@ describe("CookieTokenSource", () => {
const cookies = getCookies(response);
expect(cookies).toEqual([
{ refreshToken: "", Path: "/refresh" },
- { guestRefreshTokenExists: "" , Path: "/"},
- { userRefreshTokenExists: "" , Path: "/"},
+ { guestRefreshTokenExists: "", Path: "/" },
+ { userRefreshTokenExists: "", Path: "/" },
]);
});
diff --git a/packages/core/src/tokensource/cookies-base.ts b/packages/core/src/tokensource/cookies-base.ts
index c1faf83..c600c37 100644
--- a/packages/core/src/tokensource/cookies-base.ts
+++ b/packages/core/src/tokensource/cookies-base.ts
@@ -192,7 +192,7 @@ export abstract class BaseCookieTokenSource
response,
this.cookieNames.userData,
token,
- cookieOptions
+ cookieOptions,
);
this.deleteAccessTokenByName(
request,
diff --git a/packages/fastify-adapter/src/cookies.test.ts b/packages/fastify-adapter/src/cookies.test.ts
index 274cfb7..72189d9 100644
--- a/packages/fastify-adapter/src/cookies.test.ts
+++ b/packages/fastify-adapter/src/cookies.test.ts
@@ -1,6 +1,6 @@
import type { CookieSerializeOptions } from "@fastify/cookie";
import type { FastifyReply, FastifyRequest } from "fastify";
-import { describe, expect, it, } from "vitest";
+import { describe, expect, it } from "vitest";
import { CookieTokenSource } from "./cookies";
type CookieValue = {
From 7940e40566ffad9c20908ee996f5cb80ddd72f91 Mon Sep 17 00:00:00 2001
From: Paul Vaneveld
Date: Wed, 17 Sep 2025 17:01:33 +0200
Subject: [PATCH 5/8] chore: changeset
---
.changeset/tidy-tips-study.md | 7 +++++++
1 file changed, 7 insertions(+)
create mode 100644 .changeset/tidy-tips-study.md
diff --git a/.changeset/tidy-tips-study.md b/.changeset/tidy-tips-study.md
new file mode 100644
index 0000000..af3171e
--- /dev/null
+++ b/.changeset/tidy-tips-study.md
@@ -0,0 +1,7 @@
+---
+"@labdigital/federated-token-express-adapter": minor
+"@labdigital/federated-token-fastify-adapter": minor
+"@labdigital/federated-token": minor
+---
+
+Add support for setting the cookie path on both auth and refresh tokens
From ae86ecfceb71e4c7edafd5c080e217a39d93cd81 Mon Sep 17 00:00:00 2001
From: Paul Vaneveld
Date: Thu, 18 Sep 2025 09:21:16 +0200
Subject: [PATCH 6/8] fix: use fastify request
---
packages/fastify-adapter/src/cookies.ts | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/packages/fastify-adapter/src/cookies.ts b/packages/fastify-adapter/src/cookies.ts
index 1086cb2..d16eee7 100644
--- a/packages/fastify-adapter/src/cookies.ts
+++ b/packages/fastify-adapter/src/cookies.ts
@@ -7,10 +7,10 @@ import {
import type { FastifyReply, FastifyRequest } from "fastify";
type FastifyCookieSourceOptions = BaseCookieSourceOptions & {
- refreshTokenPath: string | ((request: Request) => string | undefined);
+ refreshTokenPath: string | ((request: FastifyRequest) => string | undefined);
publicDomainFn?: (request: FastifyRequest) => string | undefined;
privateDomainFn?: (request: FastifyRequest) => string | undefined;
- cookiePathFn?: (request: Request) => string | undefined;
+ cookiePathFn?: (request: FastifyRequest) => string | undefined;
};
class FastifyCookieAdapter
From 49eeaca5f45a0fdc95fd8407f73553695759ef05 Mon Sep 17 00:00:00 2001
From: Paul Vaneveld
Date: Thu, 18 Sep 2025 10:05:58 +0200
Subject: [PATCH 7/8] chore: changeset
---
.changeset/pre.json | 13 +++++++++++++
.../{tidy-tips-study.md => slick-rabbits-count.md} | 2 +-
2 files changed, 14 insertions(+), 1 deletion(-)
create mode 100644 .changeset/pre.json
rename .changeset/{tidy-tips-study.md => slick-rabbits-count.md} (67%)
diff --git a/.changeset/pre.json b/.changeset/pre.json
new file mode 100644
index 0000000..b71f52b
--- /dev/null
+++ b/.changeset/pre.json
@@ -0,0 +1,13 @@
+{
+ "mode": "pre",
+ "tag": "beta",
+ "initialVersions": {
+ "@labdigital/federated-token-apollo": "2.1.0",
+ "@labdigital/federated-token": "2.1.0",
+ "@labdigital/federated-token-express-adapter": "2.1.0",
+ "@labdigital/federated-token-fastify-adapter": "2.1.0",
+ "@labdigital/federated-token-react": "2.1.0",
+ "@labdigital/federated-token-yoga": "2.1.0"
+ },
+ "changesets": []
+}
diff --git a/.changeset/tidy-tips-study.md b/.changeset/slick-rabbits-count.md
similarity index 67%
rename from .changeset/tidy-tips-study.md
rename to .changeset/slick-rabbits-count.md
index af3171e..0b02320 100644
--- a/.changeset/tidy-tips-study.md
+++ b/.changeset/slick-rabbits-count.md
@@ -4,4 +4,4 @@
"@labdigital/federated-token": minor
---
-Add support for setting the cookie path on both auth and refresh tokens
+Add support for cookie path and refresh token path function
From 73b29def89edb159f4f3baee37864c77f8fa0405 Mon Sep 17 00:00:00 2001
From: Paul Vaneveld
Date: Thu, 18 Sep 2025 10:07:29 +0200
Subject: [PATCH 8/8] chore: lint
---
.changeset/pre.json | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/.changeset/pre.json b/.changeset/pre.json
index b71f52b..9e4948a 100644
--- a/.changeset/pre.json
+++ b/.changeset/pre.json
@@ -1,13 +1,13 @@
{
- "mode": "pre",
- "tag": "beta",
- "initialVersions": {
- "@labdigital/federated-token-apollo": "2.1.0",
- "@labdigital/federated-token": "2.1.0",
- "@labdigital/federated-token-express-adapter": "2.1.0",
- "@labdigital/federated-token-fastify-adapter": "2.1.0",
- "@labdigital/federated-token-react": "2.1.0",
- "@labdigital/federated-token-yoga": "2.1.0"
- },
- "changesets": []
+ "mode": "pre",
+ "tag": "beta",
+ "initialVersions": {
+ "@labdigital/federated-token-apollo": "2.1.0",
+ "@labdigital/federated-token": "2.1.0",
+ "@labdigital/federated-token-express-adapter": "2.1.0",
+ "@labdigital/federated-token-fastify-adapter": "2.1.0",
+ "@labdigital/federated-token-react": "2.1.0",
+ "@labdigital/federated-token-yoga": "2.1.0"
+ },
+ "changesets": []
}