@civic/auth 0.2.0 → 0.2.1-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/CHANGELOG.md +4 -1
  2. package/dist/cjs/browser/storage.d.ts.map +1 -1
  3. package/dist/cjs/browser/storage.js.map +1 -1
  4. package/dist/cjs/nextjs/providers/NextAuthProvider.d.ts.map +1 -1
  5. package/dist/cjs/nextjs/providers/NextAuthProvider.js +5 -2
  6. package/dist/cjs/nextjs/providers/NextAuthProvider.js.map +1 -1
  7. package/dist/cjs/reactjs/hooks/useAuth.d.ts +3 -0
  8. package/dist/cjs/reactjs/hooks/useAuth.d.ts.map +1 -0
  9. package/dist/cjs/reactjs/hooks/useAuth.js +15 -0
  10. package/dist/cjs/reactjs/hooks/useAuth.js.map +1 -0
  11. package/dist/cjs/server/index.d.ts +1 -1
  12. package/dist/cjs/server/index.d.ts.map +1 -1
  13. package/dist/cjs/server/index.js +2 -1
  14. package/dist/cjs/server/index.js.map +1 -1
  15. package/dist/cjs/shared/hooks/useClientTokenExchangeSession.d.ts +3 -0
  16. package/dist/cjs/shared/hooks/useClientTokenExchangeSession.d.ts.map +1 -0
  17. package/dist/cjs/shared/hooks/useClientTokenExchangeSession.js +16 -0
  18. package/dist/cjs/shared/hooks/useClientTokenExchangeSession.js.map +1 -0
  19. package/dist/cjs/shared/lib/session.d.ts +6 -0
  20. package/dist/cjs/shared/lib/session.d.ts.map +1 -1
  21. package/dist/cjs/shared/lib/session.js +12 -0
  22. package/dist/cjs/shared/lib/session.js.map +1 -1
  23. package/dist/cjs/shared/providers/AuthProvider.d.ts +22 -0
  24. package/dist/cjs/shared/providers/AuthProvider.d.ts.map +1 -0
  25. package/dist/cjs/shared/providers/AuthProvider.js +108 -0
  26. package/dist/cjs/shared/providers/AuthProvider.js.map +1 -0
  27. package/dist/cjs/shared/providers/CivicAuthProvider.d.ts +6 -0
  28. package/dist/cjs/shared/providers/CivicAuthProvider.d.ts.map +1 -0
  29. package/dist/cjs/shared/providers/CivicAuthProvider.js +38 -0
  30. package/dist/cjs/shared/providers/CivicAuthProvider.js.map +1 -0
  31. package/dist/cjs/shared/providers/ClientTokenExchangeSessionProvider.d.ts +17 -0
  32. package/dist/cjs/shared/providers/ClientTokenExchangeSessionProvider.d.ts.map +1 -0
  33. package/dist/cjs/shared/providers/ClientTokenExchangeSessionProvider.js +168 -0
  34. package/dist/cjs/shared/providers/ClientTokenExchangeSessionProvider.js.map +1 -0
  35. package/dist/cjs/shared/version.d.ts +1 -1
  36. package/dist/cjs/shared/version.d.ts.map +1 -1
  37. package/dist/cjs/shared/version.js +1 -1
  38. package/dist/cjs/shared/version.js.map +1 -1
  39. package/dist/esm/browser/storage.d.ts.map +1 -1
  40. package/dist/esm/browser/storage.js.map +1 -1
  41. package/dist/esm/nextjs/providers/NextAuthProvider.d.ts.map +1 -1
  42. package/dist/esm/nextjs/providers/NextAuthProvider.js +5 -2
  43. package/dist/esm/nextjs/providers/NextAuthProvider.js.map +1 -1
  44. package/dist/esm/reactjs/hooks/useAuth.d.ts +3 -0
  45. package/dist/esm/reactjs/hooks/useAuth.d.ts.map +1 -0
  46. package/dist/esm/reactjs/hooks/useAuth.js +12 -0
  47. package/dist/esm/reactjs/hooks/useAuth.js.map +1 -0
  48. package/dist/esm/server/index.d.ts +1 -1
  49. package/dist/esm/server/index.d.ts.map +1 -1
  50. package/dist/esm/server/index.js +1 -1
  51. package/dist/esm/server/index.js.map +1 -1
  52. package/dist/esm/shared/hooks/useClientTokenExchangeSession.d.ts +3 -0
  53. package/dist/esm/shared/hooks/useClientTokenExchangeSession.d.ts.map +1 -0
  54. package/dist/esm/shared/hooks/useClientTokenExchangeSession.js +13 -0
  55. package/dist/esm/shared/hooks/useClientTokenExchangeSession.js.map +1 -0
  56. package/dist/esm/shared/lib/session.d.ts +6 -0
  57. package/dist/esm/shared/lib/session.d.ts.map +1 -1
  58. package/dist/esm/shared/lib/session.js +11 -0
  59. package/dist/esm/shared/lib/session.js.map +1 -1
  60. package/dist/esm/shared/providers/AuthProvider.d.ts +22 -0
  61. package/dist/esm/shared/providers/AuthProvider.d.ts.map +1 -0
  62. package/dist/esm/shared/providers/AuthProvider.js +72 -0
  63. package/dist/esm/shared/providers/AuthProvider.js.map +1 -0
  64. package/dist/esm/shared/providers/CivicAuthProvider.d.ts +6 -0
  65. package/dist/esm/shared/providers/CivicAuthProvider.d.ts.map +1 -0
  66. package/dist/esm/shared/providers/CivicAuthProvider.js +32 -0
  67. package/dist/esm/shared/providers/CivicAuthProvider.js.map +1 -0
  68. package/dist/esm/shared/providers/ClientTokenExchangeSessionProvider.d.ts +17 -0
  69. package/dist/esm/shared/providers/ClientTokenExchangeSessionProvider.d.ts.map +1 -0
  70. package/dist/esm/shared/providers/ClientTokenExchangeSessionProvider.js +131 -0
  71. package/dist/esm/shared/providers/ClientTokenExchangeSessionProvider.js.map +1 -0
  72. package/dist/esm/shared/version.d.ts +1 -1
  73. package/dist/esm/shared/version.d.ts.map +1 -1
  74. package/dist/esm/shared/version.js +1 -1
  75. package/dist/esm/shared/version.js.map +1 -1
  76. package/dist/tsconfig.cjs.tsbuildinfo +1 -1
  77. package/dist/tsconfig.esm.tsbuildinfo +1 -1
  78. package/package.json +18 -19
  79. package/dist/src/lib/cookies.d.ts.map +0 -1
  80. package/dist/src/lib/cookies.js +0 -51
  81. package/dist/src/lib/cookies.js.map +0 -1
  82. package/dist/test/unit/lib/cookies.test.d.ts.map +0 -1
  83. package/dist/test/unit/lib/cookies.test.js +0 -25
  84. package/dist/test/unit/lib/cookies.test.js.map +0 -1
  85. package/dist/test/unit/nextjs/config.test.d.ts.map +0 -1
  86. package/dist/test/unit/nextjs/config.test.js +0 -203
  87. package/dist/test/unit/nextjs/config.test.js.map +0 -1
  88. package/dist/test/unit/server/refresh.test.d.ts.map +0 -1
  89. package/dist/test/unit/server/refresh.test.js +0 -55
  90. package/dist/test/unit/server/refresh.test.js.map +0 -1
  91. package/dist/test/unit/shared/GenericStandaloneAuthenticationRefresher.test.d.ts +0 -2
  92. package/dist/test/unit/shared/GenericStandaloneAuthenticationRefresher.test.d.ts.map +0 -1
  93. package/dist/test/unit/shared/GenericStandaloneAuthenticationRefresher.test.js +0 -144
  94. package/dist/test/unit/shared/GenericStandaloneAuthenticationRefresher.test.js.map +0 -1
  95. package/dist/test/unit/shared/GenericStandaloneAuthenticationRefresher.text.d.ts +0 -2
  96. package/dist/test/unit/shared/GenericStandaloneAuthenticationRefresher.text.d.ts.map +0 -1
  97. package/dist/test/unit/shared/GenericStandaloneAuthenticationRefresher.text.js +0 -144
  98. package/dist/test/unit/shared/GenericStandaloneAuthenticationRefresher.text.js.map +0 -1
  99. package/dist/tsconfig.tsbuildinfo +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@civic/auth",
3
- "version": "0.2.0",
3
+ "version": "0.2.1-beta.0",
4
4
  "type": "module",
5
5
  "main": "./dist/cjs/index.js",
6
6
  "module": "./dist/esm/index.js",
@@ -62,20 +62,6 @@
62
62
  }
63
63
  }
64
64
  },
65
- "scripts": {
66
- "prebuild": "pnpm generate-version",
67
- "build": "pnpm build:cjs && pnpm build:esm",
68
- "build:cjs": "tsc -p tsconfig.cjs.json --noEmit false $(if [ \"$WATCH_MODE\" = \"true\" ]; then echo \"--watch\"; fi) && tsc-alias -p tsconfig.cjs.json",
69
- "build:esm": "tsc -p tsconfig.esm.json --noEmit false $(if [ \"$WATCH_MODE\" = \"true\" ]; then echo \"--watch\"; fi) && tsc-alias -p tsconfig.esm.json",
70
- "prepublishOnly": "pnpm rm -rf dist && pnpm generate-version && node ../../etc/scripts/prompt-changelog.js && pnpm build",
71
- "dev": "WATCH_MODE=true pnpm build",
72
- "pretest": "pnpm generate-version",
73
- "test": "vitest",
74
- "lint": "eslint \"src/**/*.ts*\" --max-warnings 0",
75
- "lint:fix": "pnpm lint --fix",
76
- "test:update": "vitest --update",
77
- "generate-version": "npx tsx ./generateVersion.ts"
78
- },
79
65
  "dependencies": {
80
66
  "debug": "^4.3.7",
81
67
  "eventemitter3": "^5.0.1",
@@ -85,8 +71,6 @@
85
71
  "uuid": "^10.0.0"
86
72
  },
87
73
  "devDependencies": {
88
- "@repo/eslint-config": "workspace:*",
89
- "@repo/typescript-config": "workspace:*",
90
74
  "@rollup/plugin-typescript": "^12.1.1",
91
75
  "@testing-library/jest-dom": "^6.5.0",
92
76
  "@testing-library/react": "16.0.1",
@@ -111,9 +95,24 @@
111
95
  "tsx": "^4.19.1",
112
96
  "vite": "^5",
113
97
  "vite-plugin-dts": "^4.2.3",
114
- "vitest": "^2.1.8"
98
+ "vitest": "^2.1.8",
99
+ "@repo/eslint-config": "0.0.0",
100
+ "@repo/typescript-config": "0.0.0"
115
101
  },
116
102
  "optionalDependency": {
117
103
  "next": "^14"
104
+ },
105
+ "scripts": {
106
+ "prebuild": "pnpm generate-version",
107
+ "build": "pnpm build:cjs && pnpm build:esm",
108
+ "build:cjs": "tsc -p tsconfig.cjs.json --noEmit false $(if [ \"$WATCH_MODE\" = \"true\" ]; then echo \"--watch\"; fi) && tsc-alias -p tsconfig.cjs.json",
109
+ "build:esm": "tsc -p tsconfig.esm.json --noEmit false $(if [ \"$WATCH_MODE\" = \"true\" ]; then echo \"--watch\"; fi) && tsc-alias -p tsconfig.esm.json",
110
+ "dev": "WATCH_MODE=true pnpm build",
111
+ "pretest": "pnpm generate-version",
112
+ "test": "vitest",
113
+ "lint": "eslint \"src/**/*.ts*\" --max-warnings 0",
114
+ "lint:fix": "pnpm lint --fix",
115
+ "test:update": "vitest --update",
116
+ "generate-version": "npx tsx ./generateVersion.ts"
118
117
  }
119
- }
118
+ }
@@ -1 +0,0 @@
1
- {"version":3,"file":"cookies.d.ts","sourceRoot":"","sources":["../../../src/lib/cookies.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAK7E,QAAA,MAAM,oBAAoB,aACd;IACR,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,EAAE,4DAqBJ,CAAC;AAEF,cAAM,oBAAqB,SAAQ,aAAa;IAClC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,kBAAkB,CAAC;gBAAnC,MAAM,GAAE,OAAO,CAAC,kBAAkB,CAAM;IAOvD,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAUxC,GAAG,CAAC,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAG5D;AAED,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,CAAC"}
@@ -1,51 +0,0 @@
1
- import { CookieStorage } from "@/shared/lib/storage.js";
2
- // TODO move this into its own CookieStorage class that implements AuthStorage
3
- // and provides getters and a non-implemented setter
4
- // it should just return the string and let the user etc. be parsed by the caller
5
- const getWindowCookieValue = (requests) => {
6
- const cookie = window.document.cookie;
7
- if (!cookie)
8
- return null;
9
- const cookies = cookie.split(";");
10
- const response = {};
11
- for (const c of cookies) {
12
- const [name, value] = c.trim().split("=");
13
- const request = requests.find((r) => r.key === name);
14
- if (value && request) {
15
- try {
16
- const decodeURIComponentValue = decodeURIComponent(value);
17
- response[request.key] = request.parseJson
18
- ? JSON.parse(decodeURIComponentValue)
19
- : decodeURIComponentValue;
20
- }
21
- catch {
22
- response[request.key] = value;
23
- }
24
- }
25
- }
26
- return response;
27
- };
28
- class BrowserCookieStorage extends CookieStorage {
29
- config;
30
- constructor(config = {}) {
31
- super({
32
- secure: true,
33
- httpOnly: false,
34
- });
35
- this.config = config;
36
- }
37
- async get(key) {
38
- const value = `; ${document.cookie}`;
39
- const parts = value.split(`; ${key}=`);
40
- if (parts && parts.length === 2) {
41
- return parts.pop()?.split(";").shift() ?? null;
42
- }
43
- return null;
44
- }
45
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
46
- async set(_key, _value) {
47
- throw new Error("Not implemented.");
48
- }
49
- }
50
- export { BrowserCookieStorage, getWindowCookieValue };
51
- //# sourceMappingURL=cookies.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cookies.js","sourceRoot":"","sources":["../../../src/lib/cookies.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAGxD,8EAA8E;AAC9E,oDAAoD;AACpD,iFAAiF;AACjF,MAAM,oBAAoB,GAAG,CAC3B,QAIG,EACH,EAAE;IACF,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC;IACtC,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACzB,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAClC,MAAM,QAAQ,GAAqD,EAAE,CAAC;IACtE,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC1C,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,IAAI,CAAC,CAAC;QACrD,IAAI,KAAK,IAAI,OAAO,EAAE,CAAC;YACrB,IAAI,CAAC;gBACH,MAAM,uBAAuB,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;gBAC1D,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,SAAS;oBACvC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,uBAAuB,CAAC;oBACrC,CAAC,CAAC,uBAAuB,CAAC;YAC9B,CAAC;YAAC,MAAM,CAAC;gBACP,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;YAChC,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC,CAAC;AAEF,MAAM,oBAAqB,SAAQ,aAAa;IACzB;IAArB,YAAqB,SAAsC,EAAE;QAC3D,KAAK,CAAC;YACJ,MAAM,EAAE,IAAI;YACZ,QAAQ,EAAE,KAAK;SAChB,CAAC,CAAC;QAJgB,WAAM,GAAN,MAAM,CAAkC;IAK7D,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,GAAW;QACnB,MAAM,KAAK,GAAG,KAAK,QAAQ,CAAC,MAAM,EAAE,CAAC;QACrC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC;QACvC,IAAI,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAChC,OAAO,KAAK,CAAC,GAAG,EAAE,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,IAAI,IAAI,CAAC;QACjD,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,6DAA6D;IAC7D,KAAK,CAAC,GAAG,CAAC,IAAiB,EAAE,MAAc;QACzC,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;IACtC,CAAC;CACF;AAED,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,CAAC","sourcesContent":["import { CookieStorage } from \"@/shared/lib/storage.js\";\nimport type { OAuthTokens, TokensCookieConfig } from \"@/shared/lib/types.js\";\n\n// TODO move this into its own CookieStorage class that implements AuthStorage\n// and provides getters and a non-implemented setter\n// it should just return the string and let the user etc. be parsed by the caller\nconst getWindowCookieValue = (\n requests: {\n key: string;\n window: Window;\n parseJson?: boolean;\n }[],\n) => {\n const cookie = window.document.cookie;\n if (!cookie) return null;\n const cookies = cookie.split(\";\");\n const response: Record<string, string | Record<string, unknown>> = {};\n for (const c of cookies) {\n const [name, value] = c.trim().split(\"=\");\n const request = requests.find((r) => r.key === name);\n if (value && request) {\n try {\n const decodeURIComponentValue = decodeURIComponent(value);\n response[request.key] = request.parseJson\n ? JSON.parse(decodeURIComponentValue)\n : decodeURIComponentValue;\n } catch {\n response[request.key] = value;\n }\n }\n }\n return response;\n};\n\nclass BrowserCookieStorage extends CookieStorage {\n constructor(readonly config: Partial<TokensCookieConfig> = {}) {\n super({\n secure: true,\n httpOnly: false,\n });\n }\n\n async get(key: string): Promise<string | null> {\n const value = `; ${document.cookie}`;\n const parts = value.split(`; ${key}=`);\n if (parts && parts.length === 2) {\n return parts.pop()?.split(\";\").shift() ?? null;\n }\n return null;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n async set(_key: OAuthTokens, _value: string): Promise<void> {\n throw new Error(\"Not implemented.\");\n }\n}\n\nexport { BrowserCookieStorage, getWindowCookieValue };\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"cookies.test.d.ts","sourceRoot":"","sources":["../../../../test/unit/lib/cookies.test.ts"],"names":[],"mappings":""}
@@ -1,25 +0,0 @@
1
- import { BrowserCookieStorage } from "@/lib/cookies.js";
2
- import { describe, it } from "vitest";
3
- import { OAuthTokens } from "@/shared/lib/types.js";
4
- describe("cookies.ts", () => {
5
- describe("BrowserCookieStorage", () => {
6
- const originalCookieValue = document.cookie;
7
- afterAll(() => {
8
- document.cookie = originalCookieValue;
9
- });
10
- it("should get a cookie values", () => {
11
- const cookieStorage = new BrowserCookieStorage();
12
- document.cookie = "testCookie=testValue";
13
- document.cookie = "testCookie2=testValue2";
14
- document.cookie = "testCookie3=testValue3";
15
- expect(cookieStorage.get("testCookie")).resolves.toBe("testValue");
16
- expect(cookieStorage.get("testCookie2")).resolves.toBe("testValue2");
17
- expect(cookieStorage.get("testCookie3")).resolves.toBe("testValue3");
18
- });
19
- it("should throw an error when trying to set a value", () => {
20
- const cookieStorage = new BrowserCookieStorage();
21
- expect(() => cookieStorage.set(OAuthTokens.TIMESTAMP, "cookieValue")).rejects.toThrow("Not implemented.");
22
- });
23
- });
24
- });
25
- //# sourceMappingURL=cookies.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cookies.test.js","sourceRoot":"","sources":["../../../../test/unit/lib/cookies.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEpD,QAAQ,CAAC,YAAY,EAAE,GAAG,EAAE;IAC1B,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;QACpC,MAAM,mBAAmB,GAAG,QAAQ,CAAC,MAAM,CAAC;QAC5C,QAAQ,CAAC,GAAG,EAAE;YACZ,QAAQ,CAAC,MAAM,GAAG,mBAAmB,CAAC;QACxC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,4BAA4B,EAAE,GAAG,EAAE;YACpC,MAAM,aAAa,GAAG,IAAI,oBAAoB,EAAE,CAAC;YACjD,QAAQ,CAAC,MAAM,GAAG,sBAAsB,CAAC;YACzC,QAAQ,CAAC,MAAM,GAAG,wBAAwB,CAAC;YAC3C,QAAQ,CAAC,MAAM,GAAG,wBAAwB,CAAC;YAC3C,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YACnE,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YACrE,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACvE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;YAC1D,MAAM,aAAa,GAAG,IAAI,oBAAoB,EAAE,CAAC;YACjD,MAAM,CAAC,GAAG,EAAE,CACV,aAAa,CAAC,GAAG,CAAC,WAAW,CAAC,SAAS,EAAE,aAAa,CAAC,CACxD,CAAC,OAAO,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC;QACxC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { BrowserCookieStorage } from \"@/lib/cookies.js\";\nimport { describe, it } from \"vitest\";\nimport { OAuthTokens } from \"@/shared/lib/types.js\";\n\ndescribe(\"cookies.ts\", () => {\n describe(\"BrowserCookieStorage\", () => {\n const originalCookieValue = document.cookie;\n afterAll(() => {\n document.cookie = originalCookieValue;\n });\n\n it(\"should get a cookie values\", () => {\n const cookieStorage = new BrowserCookieStorage();\n document.cookie = \"testCookie=testValue\";\n document.cookie = \"testCookie2=testValue2\";\n document.cookie = \"testCookie3=testValue3\";\n expect(cookieStorage.get(\"testCookie\")).resolves.toBe(\"testValue\");\n expect(cookieStorage.get(\"testCookie2\")).resolves.toBe(\"testValue2\");\n expect(cookieStorage.get(\"testCookie3\")).resolves.toBe(\"testValue3\");\n });\n\n it(\"should throw an error when trying to set a value\", () => {\n const cookieStorage = new BrowserCookieStorage();\n expect(() =>\n cookieStorage.set(OAuthTokens.TIMESTAMP, \"cookieValue\"),\n ).rejects.toThrow(\"Not implemented.\");\n });\n });\n});\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"config.test.d.ts","sourceRoot":"","sources":["../../../../test/unit/nextjs/config.test.ts"],"names":[],"mappings":""}
@@ -1,203 +0,0 @@
1
- /* eslint-disable turbo/no-undeclared-env-vars */
2
- import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
3
- import { resolveAuthConfig, createCivicAuthPlugin, defaultAuthConfig, } from "@/nextjs/config.js";
4
- import { DEFAULT_AUTH_SERVER } from "@/constants.js";
5
- const defaultCookies = {
6
- id_token: {
7
- httpOnly: true,
8
- path: "/",
9
- sameSite: "strict",
10
- secure: false,
11
- },
12
- access_token: {
13
- httpOnly: true,
14
- path: "/",
15
- sameSite: "strict",
16
- secure: false,
17
- },
18
- refresh_token: {
19
- httpOnly: true,
20
- path: "/",
21
- sameSite: "strict",
22
- secure: false,
23
- },
24
- expires_in: {
25
- httpOnly: false,
26
- path: "/",
27
- sameSite: "strict",
28
- secure: false,
29
- },
30
- timestamp: {
31
- httpOnly: false,
32
- path: "/",
33
- sameSite: "strict",
34
- secure: false,
35
- },
36
- code_verifier: {
37
- httpOnly: true,
38
- path: "/",
39
- sameSite: "strict",
40
- secure: false,
41
- },
42
- app_url: {
43
- httpOnly: true,
44
- path: "/",
45
- sameSite: "strict",
46
- secure: false,
47
- },
48
- };
49
- describe("nextjs/config", () => {
50
- const originalEnv = process.env;
51
- beforeEach(() => {
52
- vi.resetModules();
53
- process.env = { ...originalEnv, NODE_ENV: "development" };
54
- });
55
- afterEach(() => {
56
- process.env = originalEnv;
57
- vi.restoreAllMocks();
58
- });
59
- describe("resolveAuthConfig", () => {
60
- it("should throw an error if clientId is not provided", () => {
61
- expect(() => resolveAuthConfig()).toThrowError("Civic Auth client ID is required");
62
- });
63
- it("should use default values when no config is provided", () => {
64
- // client id must be defined
65
- process.env._civic_auth_client_id = "clientId";
66
- const result = resolveAuthConfig();
67
- expect(result).toEqual({ ...defaultAuthConfig, clientId: "clientId" });
68
- });
69
- it("should override default values with provided config", () => {
70
- const config = {
71
- clientId: "clientId",
72
- callbackUrl: "/custom/callback",
73
- loginUrl: "/custom/login",
74
- include: ["/protected/*"],
75
- exclude: ["/public/*"],
76
- };
77
- const result = resolveAuthConfig(config);
78
- expect(result.callbackUrl).toBe("/custom/callback");
79
- expect(result.loginUrl).toBe("/custom/login");
80
- expect(result.include).toEqual(["/protected/*"]);
81
- expect(result.exclude).toEqual(["/public/*"]);
82
- });
83
- it("should use environment variables if set", () => {
84
- process.env._civic_auth_client_id = "clientId";
85
- process.env._civic_auth_callback_url = "/env/callback";
86
- process.env._civic_auth_login_url = "/env/login";
87
- process.env._civic_auth_includes = "/env/protected/*";
88
- process.env._civic_auth_excludes = "/env/public/*";
89
- const result = resolveAuthConfig();
90
- expect(result.callbackUrl).toBe("/env/callback");
91
- expect(result.loginUrl).toBe("/env/login");
92
- expect(result.include).toEqual(["/env/protected/*"]);
93
- expect(result.exclude).toEqual(["/env/public/*"]);
94
- });
95
- it("should prioritize provided config over environment variables", () => {
96
- process.env._civic_auth_callback_url = "/env/callback";
97
- const config = {
98
- clientId: "clientId",
99
- callbackUrl: "/config/callback",
100
- };
101
- const result = resolveAuthConfig(config);
102
- expect(result.callbackUrl).toBe("/config/callback");
103
- });
104
- it("should merge cookie configurations correctly", () => {
105
- const config = {
106
- clientId: "clientId",
107
- cookies: {
108
- tokens: {
109
- id_token: { ...defaultCookies.id_token, secure: false },
110
- },
111
- user: {
112
- httpOnly: false,
113
- secure: false,
114
- sameSite: "strict",
115
- },
116
- },
117
- };
118
- const result = resolveAuthConfig(config);
119
- expect(result.cookies.tokens).toEqual({
120
- ...defaultCookies,
121
- id_token: { ...defaultCookies.id_token, secure: false },
122
- });
123
- expect(result.cookies.user).toEqual({
124
- httpOnly: false,
125
- secure: false,
126
- sameSite: "strict",
127
- path: "/",
128
- maxAge: 3600,
129
- });
130
- });
131
- it("should set secure to true in the default cookie configs if NODE_ENV is not development", async () => {
132
- process.env = { ...originalEnv, NODE_ENV: "production" };
133
- // re-import to get the configs with the updated NODE_ENV
134
- const configs = await import("../../../src/nextjs/config.js");
135
- const result = configs.resolveAuthConfig({ clientId: "clientId" });
136
- Object.values(result.cookies.tokens).forEach((cookie) => {
137
- expect(cookie.secure).toBe(true);
138
- });
139
- });
140
- });
141
- describe("createCivicAuthPlugin", () => {
142
- it("should return a function", () => {
143
- const plugin = createCivicAuthPlugin({ clientId: "clientId" });
144
- expect(typeof plugin).toBe("function");
145
- });
146
- it("should set environment variables based on resolved config", () => {
147
- const config = {
148
- clientId: "clientId",
149
- callbackUrl: "/custom/callback",
150
- loginUrl: "/custom/login",
151
- logoutUrl: "/custom/logout",
152
- logoutCallbackUrl: "/custom/logoutcallback",
153
- include: ["/protected/*"],
154
- exclude: ["/public/*"],
155
- cookies: {
156
- tokens: defaultCookies,
157
- user: {
158
- secure: false,
159
- sameSite: "strict",
160
- maxAge: 3600,
161
- },
162
- },
163
- };
164
- const plugin = createCivicAuthPlugin(config);
165
- const nextConfig = plugin({});
166
- expect(nextConfig.env).toEqual({
167
- _civic_auth_client_id: "clientId",
168
- _civic_auth_callback_url: "/custom/callback",
169
- _civic_auth_challenge_url: "/api/auth/challenge",
170
- _civic_auth_login_url: "/custom/login",
171
- _civic_auth_logout_url: "/custom/logout",
172
- _civic_auth_logout_callback_url: "/custom/logoutcallback",
173
- _civic_auth_includes: "/protected/*",
174
- _civic_auth_excludes: "/public/*",
175
- _civic_oauth_server: DEFAULT_AUTH_SERVER,
176
- _civic_auth_cookie_config: JSON.stringify({
177
- tokens: defaultCookies,
178
- user: {
179
- secure: false,
180
- httpOnly: false,
181
- sameSite: "strict",
182
- path: "/",
183
- maxAge: 3600,
184
- },
185
- }),
186
- });
187
- });
188
- it("should merge with existing Next.js config", () => {
189
- const existingConfig = {
190
- reactStrictMode: true,
191
- env: {
192
- CUSTOM_VAR: "value",
193
- },
194
- };
195
- const plugin = createCivicAuthPlugin({ clientId: "clientId" });
196
- const nextConfig = plugin(existingConfig);
197
- expect(nextConfig.reactStrictMode).toBe(true);
198
- expect(nextConfig.env).toHaveProperty("CUSTOM_VAR", "value");
199
- expect(nextConfig.env).toHaveProperty("_civic_auth_callback_url");
200
- });
201
- });
202
- });
203
- //# sourceMappingURL=config.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"config.test.js","sourceRoot":"","sources":["../../../../test/unit/nextjs/config.test.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable turbo/no-undeclared-env-vars */\nimport { describe, it, expect, beforeEach, afterEach, vi } from \"vitest\";\nimport {\n resolveAuthConfig,\n createCivicAuthPlugin,\n type AuthConfig,\n defaultAuthConfig,\n} from \"@/nextjs/config.js\";\nimport type { TokensCookieConfig } from \"@/index.js\";\nimport { DEFAULT_AUTH_SERVER } from \"@/constants.js\";\n\nconst defaultCookies = {\n id_token: {\n httpOnly: true,\n path: \"/\",\n sameSite: \"strict\",\n secure: false,\n },\n access_token: {\n httpOnly: true,\n path: \"/\",\n sameSite: \"strict\",\n secure: false,\n },\n refresh_token: {\n httpOnly: true,\n path: \"/\",\n sameSite: \"strict\",\n secure: false,\n },\n expires_in: {\n httpOnly: false,\n path: \"/\",\n sameSite: \"strict\",\n secure: false,\n },\n timestamp: {\n httpOnly: false,\n path: \"/\",\n sameSite: \"strict\",\n secure: false,\n },\n code_verifier: {\n httpOnly: true,\n path: \"/\",\n sameSite: \"strict\",\n secure: false,\n },\n app_url: {\n httpOnly: true,\n path: \"/\",\n sameSite: \"strict\",\n secure: false,\n },\n} as TokensCookieConfig;\n\ndescribe(\"nextjs/config\", () => {\n const originalEnv = process.env;\n\n beforeEach(() => {\n vi.resetModules();\n process.env = { ...originalEnv, NODE_ENV: \"development\" };\n });\n\n afterEach(() => {\n process.env = originalEnv;\n vi.restoreAllMocks();\n });\n\n describe(\"resolveAuthConfig\", () => {\n it(\"should throw an error if clientId is not provided\", () => {\n expect(() => resolveAuthConfig()).toThrowError(\n \"Civic Auth client ID is required\",\n );\n });\n\n it(\"should use default values when no config is provided\", () => {\n // client id must be defined\n process.env._civic_auth_client_id = \"clientId\";\n const result = resolveAuthConfig();\n expect(result).toEqual({ ...defaultAuthConfig, clientId: \"clientId\" });\n });\n\n it(\"should override default values with provided config\", () => {\n const config: AuthConfig = {\n clientId: \"clientId\",\n callbackUrl: \"/custom/callback\",\n loginUrl: \"/custom/login\",\n include: [\"/protected/*\"],\n exclude: [\"/public/*\"],\n };\n const result = resolveAuthConfig(config);\n expect(result.callbackUrl).toBe(\"/custom/callback\");\n expect(result.loginUrl).toBe(\"/custom/login\");\n expect(result.include).toEqual([\"/protected/*\"]);\n expect(result.exclude).toEqual([\"/public/*\"]);\n });\n\n it(\"should use environment variables if set\", () => {\n process.env._civic_auth_client_id = \"clientId\";\n process.env._civic_auth_callback_url = \"/env/callback\";\n process.env._civic_auth_login_url = \"/env/login\";\n process.env._civic_auth_includes = \"/env/protected/*\";\n process.env._civic_auth_excludes = \"/env/public/*\";\n\n const result = resolveAuthConfig();\n expect(result.callbackUrl).toBe(\"/env/callback\");\n expect(result.loginUrl).toBe(\"/env/login\");\n expect(result.include).toEqual([\"/env/protected/*\"]);\n expect(result.exclude).toEqual([\"/env/public/*\"]);\n });\n\n it(\"should prioritize provided config over environment variables\", () => {\n process.env._civic_auth_callback_url = \"/env/callback\";\n const config: AuthConfig = {\n clientId: \"clientId\",\n callbackUrl: \"/config/callback\",\n };\n\n const result = resolveAuthConfig(config);\n expect(result.callbackUrl).toBe(\"/config/callback\");\n });\n\n it(\"should merge cookie configurations correctly\", () => {\n const config: AuthConfig = {\n clientId: \"clientId\",\n cookies: {\n tokens: {\n id_token: { ...defaultCookies.id_token, secure: false },\n } as TokensCookieConfig,\n user: {\n httpOnly: false,\n secure: false,\n sameSite: \"strict\",\n },\n },\n };\n\n const result = resolveAuthConfig(config);\n expect(result.cookies.tokens).toEqual({\n ...defaultCookies,\n id_token: { ...defaultCookies.id_token, secure: false },\n });\n\n expect(result.cookies.user).toEqual({\n httpOnly: false,\n secure: false,\n sameSite: \"strict\",\n path: \"/\",\n maxAge: 3600,\n });\n });\n\n it(\"should set secure to true in the default cookie configs if NODE_ENV is not development\", async () => {\n process.env = { ...originalEnv, NODE_ENV: \"production\" };\n // re-import to get the configs with the updated NODE_ENV\n const configs = await import(\"../../../src/nextjs/config.js\");\n const result = configs.resolveAuthConfig({ clientId: \"clientId\" });\n Object.values(result.cookies.tokens).forEach((cookie) => {\n expect(cookie.secure).toBe(true);\n });\n });\n });\n\n describe(\"createCivicAuthPlugin\", () => {\n it(\"should return a function\", () => {\n const plugin = createCivicAuthPlugin({ clientId: \"clientId\" });\n expect(typeof plugin).toBe(\"function\");\n });\n\n it(\"should set environment variables based on resolved config\", () => {\n const config = {\n clientId: \"clientId\",\n callbackUrl: \"/custom/callback\",\n loginUrl: \"/custom/login\",\n logoutUrl: \"/custom/logout\",\n logoutCallbackUrl: \"/custom/logoutcallback\",\n include: [\"/protected/*\"],\n exclude: [\"/public/*\"],\n cookies: {\n tokens: defaultCookies,\n user: {\n secure: false,\n sameSite: \"strict\",\n maxAge: 3600,\n } as const,\n },\n };\n\n const plugin = createCivicAuthPlugin(config);\n const nextConfig = plugin({});\n\n expect(nextConfig.env).toEqual({\n _civic_auth_client_id: \"clientId\",\n _civic_auth_callback_url: \"/custom/callback\",\n _civic_auth_challenge_url: \"/api/auth/challenge\",\n _civic_auth_login_url: \"/custom/login\",\n _civic_auth_logout_url: \"/custom/logout\",\n _civic_auth_logout_callback_url: \"/custom/logoutcallback\",\n _civic_auth_includes: \"/protected/*\",\n _civic_auth_excludes: \"/public/*\",\n _civic_oauth_server: DEFAULT_AUTH_SERVER,\n _civic_auth_cookie_config: JSON.stringify({\n tokens: defaultCookies,\n user: {\n secure: false,\n httpOnly: false,\n sameSite: \"strict\",\n path: \"/\",\n maxAge: 3600,\n },\n }),\n });\n });\n\n it(\"should merge with existing Next.js config\", () => {\n const existingConfig = {\n reactStrictMode: true,\n env: {\n CUSTOM_VAR: \"value\",\n },\n };\n\n const plugin = createCivicAuthPlugin({ clientId: \"clientId\" });\n const nextConfig = plugin(existingConfig);\n\n expect(nextConfig.reactStrictMode).toBe(true);\n expect(nextConfig.env).toHaveProperty(\"CUSTOM_VAR\", \"value\");\n expect(nextConfig.env).toHaveProperty(\"_civic_auth_callback_url\");\n });\n });\n});\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"refresh.test.d.ts","sourceRoot":"","sources":["../../../../test/unit/server/refresh.test.ts"],"names":[],"mappings":""}
@@ -1,55 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach } from "vitest";
2
- import { refreshTokens } from "@/server/refresh.js";
3
- import { GenericStandaloneAuthenticationRefresher } from "@/shared/lib/GenericStandaloneAuthenticationRefresher.js";
4
- import { DEFAULT_AUTH_SERVER } from "@/constants.js";
5
- // Mock the GenericStandaloneAuthenticationRefresher
6
- vi.mock("@/shared/lib/GenericStandaloneAuthenticationRefresher.js", () => ({
7
- GenericStandaloneAuthenticationRefresher: {
8
- build: vi.fn(),
9
- },
10
- }));
11
- describe("refresh.ts", () => {
12
- const mockStorage = {
13
- get: vi.fn(),
14
- set: vi.fn(),
15
- removeItem: vi.fn(),
16
- };
17
- const mockConfig = {
18
- clientId: "test-client-id",
19
- clientSecret: "test-client-secret",
20
- redirectUrl: "http://localhost:3000/redirect",
21
- };
22
- const mockRefreshResponse = {
23
- access_token: "new-access-token",
24
- refresh_token: "new-refresh-token",
25
- expires_in: 3600,
26
- };
27
- const mockRefresher = {
28
- refreshTokens: vi.fn().mockResolvedValue(mockRefreshResponse),
29
- setupAutorefresh: vi.fn(),
30
- };
31
- beforeEach(() => {
32
- vi.clearAllMocks();
33
- GenericStandaloneAuthenticationRefresher.build.mockResolvedValue(mockRefresher);
34
- });
35
- describe("refreshTokens", () => {
36
- it("should create refresher with correct config and call refreshTokens", async () => {
37
- const result = await refreshTokens(mockStorage, mockConfig);
38
- expect(GenericStandaloneAuthenticationRefresher.build).toHaveBeenCalledWith({
39
- ...mockConfig,
40
- oauthServer: DEFAULT_AUTH_SERVER,
41
- }, mockStorage, undefined);
42
- expect(mockRefresher.refreshTokens).toHaveBeenCalled();
43
- expect(result).toEqual(mockRefreshResponse);
44
- });
45
- it("should use custom oauthServer when provided", async () => {
46
- const customConfig = {
47
- ...mockConfig,
48
- oauthServer: "https://custom-server.com",
49
- };
50
- await refreshTokens(mockStorage, customConfig);
51
- expect(GenericStandaloneAuthenticationRefresher.build).toHaveBeenCalledWith(customConfig, mockStorage, undefined);
52
- });
53
- });
54
- });
55
- //# sourceMappingURL=refresh.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"refresh.test.js","sourceRoot":"","sources":["../../../../test/unit/server/refresh.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,wCAAwC,EAAE,MAAM,0DAA0D,CAAC;AACpH,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAErD,oDAAoD;AACpD,EAAE,CAAC,IAAI,CAAC,0DAA0D,EAAE,GAAG,EAAE,CAAC,CAAC;IACzE,wCAAwC,EAAE;QACxC,KAAK,EAAE,EAAE,CAAC,EAAE,EAAE;KACf;CACF,CAAC,CAAC,CAAC;AAEJ,QAAQ,CAAC,YAAY,EAAE,GAAG,EAAE;IAC1B,MAAM,WAAW,GAAG;QAClB,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE;QACZ,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE;QACZ,UAAU,EAAE,EAAE,CAAC,EAAE,EAAE;KACpB,CAAC;IAEF,MAAM,UAAU,GAAG;QACjB,QAAQ,EAAE,gBAAgB;QAC1B,YAAY,EAAE,oBAAoB;QAClC,WAAW,EAAE,gCAAgC;KAC9C,CAAC;IAEF,MAAM,mBAAmB,GAAG;QAC1B,YAAY,EAAE,kBAAkB;QAChC,aAAa,EAAE,mBAAmB;QAClC,UAAU,EAAE,IAAI;KACjB,CAAC;IAEF,MAAM,aAAa,GAAG;QACpB,aAAa,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,mBAAmB,CAAC;QAC7D,gBAAgB,EAAE,EAAE,CAAC,EAAE,EAAE;KAC1B,CAAC;IAEF,UAAU,CAAC,GAAG,EAAE;QACd,EAAE,CAAC,aAAa,EAAE,CAAC;QAClB,wCAAwC,CAAC,KAAa,CAAC,iBAAiB,CACvE,aAAa,CACd,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;QAC7B,EAAE,CAAC,oEAAoE,EAAE,KAAK,IAAI,EAAE;YAClF,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;YAE5D,MAAM,CACJ,wCAAwC,CAAC,KAAK,CAC/C,CAAC,oBAAoB,CACpB;gBACE,GAAG,UAAU;gBACb,WAAW,EAAE,mBAAmB;aACjC,EACD,WAAW,EACX,SAAS,CACV,CAAC;YACF,MAAM,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC,gBAAgB,EAAE,CAAC;YACvD,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC;QAC9C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6CAA6C,EAAE,KAAK,IAAI,EAAE;YAC3D,MAAM,YAAY,GAAG;gBACnB,GAAG,UAAU;gBACb,WAAW,EAAE,2BAA2B;aACzC,CAAC;YAEF,MAAM,aAAa,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;YAE/C,MAAM,CACJ,wCAAwC,CAAC,KAAK,CAC/C,CAAC,oBAAoB,CAAC,YAAY,EAAE,WAAW,EAAE,SAAS,CAAC,CAAC;QAC/D,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { describe, it, expect, vi, beforeEach } from \"vitest\";\nimport { refreshTokens } from \"@/server/refresh.js\";\nimport { GenericStandaloneAuthenticationRefresher } from \"@/shared/lib/GenericStandaloneAuthenticationRefresher.js\";\nimport { DEFAULT_AUTH_SERVER } from \"@/constants.js\";\n\n// Mock the GenericStandaloneAuthenticationRefresher\nvi.mock(\"@/shared/lib/GenericStandaloneAuthenticationRefresher.js\", () => ({\n GenericStandaloneAuthenticationRefresher: {\n build: vi.fn(),\n },\n}));\n\ndescribe(\"refresh.ts\", () => {\n const mockStorage = {\n get: vi.fn(),\n set: vi.fn(),\n removeItem: vi.fn(),\n };\n\n const mockConfig = {\n clientId: \"test-client-id\",\n clientSecret: \"test-client-secret\",\n redirectUrl: \"http://localhost:3000/redirect\",\n };\n\n const mockRefreshResponse = {\n access_token: \"new-access-token\",\n refresh_token: \"new-refresh-token\",\n expires_in: 3600,\n };\n\n const mockRefresher = {\n refreshTokens: vi.fn().mockResolvedValue(mockRefreshResponse),\n setupAutorefresh: vi.fn(),\n };\n\n beforeEach(() => {\n vi.clearAllMocks();\n (GenericStandaloneAuthenticationRefresher.build as any).mockResolvedValue(\n mockRefresher,\n );\n });\n\n describe(\"refreshTokens\", () => {\n it(\"should create refresher with correct config and call refreshTokens\", async () => {\n const result = await refreshTokens(mockStorage, mockConfig);\n\n expect(\n GenericStandaloneAuthenticationRefresher.build,\n ).toHaveBeenCalledWith(\n {\n ...mockConfig,\n oauthServer: DEFAULT_AUTH_SERVER,\n },\n mockStorage,\n undefined,\n );\n expect(mockRefresher.refreshTokens).toHaveBeenCalled();\n expect(result).toEqual(mockRefreshResponse);\n });\n\n it(\"should use custom oauthServer when provided\", async () => {\n const customConfig = {\n ...mockConfig,\n oauthServer: \"https://custom-server.com\",\n };\n\n await refreshTokens(mockStorage, customConfig);\n\n expect(\n GenericStandaloneAuthenticationRefresher.build,\n ).toHaveBeenCalledWith(customConfig, mockStorage, undefined);\n });\n });\n});\n"]}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=GenericStandaloneAuthenticationRefresher.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"GenericStandaloneAuthenticationRefresher.test.d.ts","sourceRoot":"","sources":["../../../../test/unit/shared/GenericStandaloneAuthenticationRefresher.test.ts"],"names":[],"mappings":""}
@@ -1,144 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach, } from "vitest";
2
- import { getEndpointsWithOverrides, retrieveTokens, storeTokens, } from "@/shared/lib/util.js";
3
- import { OAuth2Client } from "oslo/oauth2";
4
- import { GenericStandaloneAuthenticationRefresher } from "@/shared/lib/GenericStandaloneAuthenticationRefresher.js";
5
- vi.mock("@/shared/lib/util.js");
6
- vi.mock("oslo/oauth2");
7
- describe("GenericStandaloneAuthenticationRefresher", () => {
8
- const mockAuthConfig = {
9
- clientId: "mockClientId",
10
- oauthServer: "http://mockOauthServer",
11
- redirectUrl: "http://localhost/redirect",
12
- };
13
- const mockEndpoints = {
14
- auth: "http://mockAuthEndpoint",
15
- token: "http://mockTokenEndpoint",
16
- jwks: "http://mockJwksEndpoint",
17
- userinfo: "http://mockUserinfoEndpoint",
18
- endsession: "http://mockEndsessionEndpoint",
19
- };
20
- const mockTokens = {
21
- id_token: "mockIdToken",
22
- access_token: "mockAccessToken",
23
- refresh_token: "mockRefreshToken",
24
- };
25
- const mockStorage = {};
26
- let refresher;
27
- beforeEach(async () => {
28
- vi.clearAllMocks();
29
- vi.mocked(getEndpointsWithOverrides).mockResolvedValue(mockEndpoints);
30
- refresher = await GenericStandaloneAuthenticationRefresher.build(mockAuthConfig, mockStorage);
31
- });
32
- describe("init", () => {
33
- it("should initialize OAuth2 client with resolved endpoints", async () => {
34
- expect(getEndpointsWithOverrides).toHaveBeenCalledWith(mockAuthConfig.oauthServer, undefined);
35
- expect(refresher["endpoints"]).toEqual(mockEndpoints);
36
- expect(refresher["oauth2client"]).toBeInstanceOf(OAuth2Client);
37
- });
38
- });
39
- describe("refreshTokens", () => {
40
- it("should refresh tokens and store them", async () => {
41
- vi.mocked(retrieveTokens).mockResolvedValue(mockTokens);
42
- const refreshedTokens = {
43
- id_token: "newIdToken",
44
- access_token: "newAccessToken",
45
- refresh_token: "newRefreshToken",
46
- };
47
- vi.mocked(OAuth2Client.prototype.refreshAccessToken).mockResolvedValue(refreshedTokens);
48
- const result = await refresher.refreshTokens();
49
- expect(refresher["oauth2client"]?.refreshAccessToken).toHaveBeenCalledWith(mockTokens.refresh_token);
50
- expect(storeTokens).toHaveBeenCalledWith(mockStorage, refreshedTokens);
51
- expect(result).toEqual(refreshedTokens);
52
- });
53
- it("should throw an error if no refresh token is available", async () => {
54
- vi.mocked(retrieveTokens).mockResolvedValue({
55
- ...mockTokens,
56
- refresh_token: undefined,
57
- });
58
- await expect(refresher.refreshTokens()).rejects.toThrow("No refresh token available");
59
- });
60
- });
61
- describe("auto refresh", () => {
62
- let setTimeoutSpy;
63
- let clearTimeoutSpy;
64
- beforeEach(() => {
65
- vi.clearAllMocks(); // Ensure all mocks are reset
66
- vi.useFakeTimers();
67
- setTimeoutSpy = vi.spyOn(global, "setTimeout");
68
- clearTimeoutSpy = vi.spyOn(global, "clearTimeout");
69
- });
70
- afterEach(() => {
71
- vi.useRealTimers();
72
- setTimeoutSpy.mockRestore();
73
- clearTimeoutSpy.mockRestore();
74
- vi.clearAllTimers(); // Clear any pending timers
75
- });
76
- it("should setup auto refresh timer based on token expiry", async () => {
77
- const tokensWithExpiry = {
78
- ...mockTokens,
79
- expires_in: 3600, // 1 hour
80
- };
81
- vi.mocked(retrieveTokens).mockResolvedValue(tokensWithExpiry);
82
- await refresher.setupAutorefresh();
83
- // Should set timeout for (3600 - 30) seconds
84
- expect(setTimeout).toHaveBeenCalledTimes(1);
85
- expect(setTimeout).toHaveBeenCalledWith(expect.any(Function), 3570000);
86
- });
87
- it("should clear existing timeout when setting up new refresh", async () => {
88
- const tokensWithExpiry = {
89
- ...mockTokens,
90
- expires_in: 3600,
91
- };
92
- vi.mocked(retrieveTokens).mockResolvedValue(tokensWithExpiry);
93
- // Setup initial timeout
94
- await refresher.setupAutorefresh();
95
- // Setup another timeout
96
- await refresher.setupAutorefresh();
97
- expect(clearTimeout).toHaveBeenCalled();
98
- });
99
- it("should refresh tokens and setup new timer when timeout triggers", async () => {
100
- const tokensWithExpiry = {
101
- ...mockTokens,
102
- expires_in: 3600,
103
- };
104
- const refreshedTokens = {
105
- ...mockTokens,
106
- id_token: "newIdToken",
107
- access_token: "newAccessToken",
108
- refresh_token: "newRefreshToken",
109
- expires_in: 3600,
110
- };
111
- // Reset mock call history
112
- vi.mocked(retrieveTokens).mockReset();
113
- vi.mocked(OAuth2Client.prototype.refreshAccessToken).mockReset();
114
- vi.mocked(retrieveTokens)
115
- .mockResolvedValueOnce(tokensWithExpiry) // First call for initial setup
116
- .mockResolvedValueOnce(tokensWithExpiry) // Second call in refreshTokens
117
- .mockResolvedValueOnce(refreshedTokens); // Third call for next setup
118
- vi.mocked(OAuth2Client.prototype.refreshAccessToken).mockResolvedValue(refreshedTokens);
119
- await refresher.setupAutorefresh();
120
- // Fast-forward time to trigger the refresh
121
- await vi.advanceTimersByTimeAsync(3570000); // Use async version
122
- expect(OAuth2Client.prototype.refreshAccessToken).toHaveBeenCalled();
123
- expect(storeTokens).toHaveBeenCalledWith(mockStorage, refreshedTokens);
124
- expect(setTimeout).toHaveBeenCalledTimes(2);
125
- });
126
- it("should handle refresh failures gracefully", async () => {
127
- const tokensWithExpiry = {
128
- ...mockTokens,
129
- expires_in: 3600,
130
- };
131
- vi.mocked(retrieveTokens).mockResolvedValue(tokensWithExpiry);
132
- vi.mocked(OAuth2Client.prototype.refreshAccessToken).mockRejectedValue(new Error("Refresh failed"));
133
- const consoleSpy = vi
134
- .spyOn(console, "error")
135
- .mockImplementation(() => { });
136
- await refresher.setupAutorefresh();
137
- // Fast-forward time to trigger the refresh
138
- vi.advanceTimersByTime(3570000);
139
- await vi.runAllTimersAsync();
140
- expect(consoleSpy).toHaveBeenCalledWith("Failed to refresh tokens:", expect.any(Error));
141
- });
142
- });
143
- });
144
- //# sourceMappingURL=GenericStandaloneAuthenticationRefresher.test.js.map