@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
@@ -1 +0,0 @@
1
- {"version":3,"file":"GenericStandaloneAuthenticationRefresher.test.js","sourceRoot":"","sources":["../../../../test/unit/shared/GenericStandaloneAuthenticationRefresher.test.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n describe,\n it,\n expect,\n vi,\n beforeEach,\n type MockInstance,\n} from \"vitest\";\nimport {\n getEndpointsWithOverrides,\n retrieveTokens,\n storeTokens,\n} from \"@/shared/lib/util.js\";\nimport type { AuthStorage, Endpoints, OIDCTokenResponseBody } from \"@/types.js\";\nimport { OAuth2Client } from \"oslo/oauth2\";\nimport type { AuthConfig } from \"@/server/config.ts\";\nimport { GenericStandaloneAuthenticationRefresher } from \"@/shared/lib/GenericStandaloneAuthenticationRefresher.js\";\n\nvi.mock(\"@/shared/lib/util.js\");\nvi.mock(\"oslo/oauth2\");\n\ndescribe(\"GenericStandaloneAuthenticationRefresher\", () => {\n const mockAuthConfig: AuthConfig = {\n clientId: \"mockClientId\",\n oauthServer: \"http://mockOauthServer\",\n redirectUrl: \"http://localhost/redirect\",\n };\n const mockEndpoints: Endpoints = {\n auth: \"http://mockAuthEndpoint\",\n token: \"http://mockTokenEndpoint\",\n jwks: \"http://mockJwksEndpoint\",\n userinfo: \"http://mockUserinfoEndpoint\",\n endsession: \"http://mockEndsessionEndpoint\",\n };\n const mockTokens: OIDCTokenResponseBody = {\n id_token: \"mockIdToken\",\n access_token: \"mockAccessToken\",\n refresh_token: \"mockRefreshToken\",\n };\n const mockStorage = {} as AuthStorage;\n\n let refresher: GenericStandaloneAuthenticationRefresher;\n\n beforeEach(async () => {\n vi.clearAllMocks();\n vi.mocked(getEndpointsWithOverrides).mockResolvedValue(mockEndpoints);\n refresher = await GenericStandaloneAuthenticationRefresher.build(\n mockAuthConfig,\n mockStorage,\n );\n });\n\n describe(\"init\", () => {\n it(\"should initialize OAuth2 client with resolved endpoints\", async () => {\n expect(getEndpointsWithOverrides).toHaveBeenCalledWith(\n mockAuthConfig.oauthServer,\n undefined,\n );\n expect(refresher[\"endpoints\"]).toEqual(mockEndpoints);\n expect(refresher[\"oauth2client\"]).toBeInstanceOf(OAuth2Client);\n });\n });\n\n describe(\"refreshTokens\", () => {\n it(\"should refresh tokens and store them\", async () => {\n vi.mocked(retrieveTokens).mockResolvedValue(mockTokens);\n const refreshedTokens: OIDCTokenResponseBody = {\n id_token: \"newIdToken\",\n access_token: \"newAccessToken\",\n refresh_token: \"newRefreshToken\",\n };\n\n vi.mocked(OAuth2Client.prototype.refreshAccessToken).mockResolvedValue(\n refreshedTokens,\n );\n\n const result = await refresher.refreshTokens();\n\n expect(\n refresher[\"oauth2client\"]?.refreshAccessToken,\n ).toHaveBeenCalledWith(mockTokens.refresh_token);\n expect(storeTokens).toHaveBeenCalledWith(mockStorage, refreshedTokens);\n expect(result).toEqual(refreshedTokens);\n });\n\n it(\"should throw an error if no refresh token is available\", async () => {\n vi.mocked(retrieveTokens).mockResolvedValue({\n ...mockTokens,\n refresh_token: undefined,\n });\n\n await expect(refresher.refreshTokens()).rejects.toThrow(\n \"No refresh token available\",\n );\n });\n });\n\n describe(\"auto refresh\", () => {\n let setTimeoutSpy: MockInstance<typeof setTimeout>;\n let clearTimeoutSpy: MockInstance<typeof clearTimeout>;\n\n beforeEach(() => {\n vi.clearAllMocks(); // Ensure all mocks are reset\n vi.useFakeTimers();\n setTimeoutSpy = vi.spyOn(global, \"setTimeout\");\n clearTimeoutSpy = vi.spyOn(global, \"clearTimeout\");\n });\n\n afterEach(() => {\n vi.useRealTimers();\n setTimeoutSpy.mockRestore();\n clearTimeoutSpy.mockRestore();\n vi.clearAllTimers(); // Clear any pending timers\n });\n\n it(\"should setup auto refresh timer based on token expiry\", async () => {\n const tokensWithExpiry = {\n ...mockTokens,\n expires_in: 3600, // 1 hour\n };\n vi.mocked(retrieveTokens).mockResolvedValue(tokensWithExpiry);\n\n await refresher.setupAutorefresh();\n\n // Should set timeout for (3600 - 30) seconds\n expect(setTimeout).toHaveBeenCalledTimes(1);\n expect(setTimeout).toHaveBeenCalledWith(expect.any(Function), 3570000);\n });\n\n it(\"should clear existing timeout when setting up new refresh\", async () => {\n const tokensWithExpiry = {\n ...mockTokens,\n expires_in: 3600,\n };\n vi.mocked(retrieveTokens).mockResolvedValue(tokensWithExpiry);\n\n // Setup initial timeout\n await refresher.setupAutorefresh();\n\n // Setup another timeout\n await refresher.setupAutorefresh();\n\n expect(clearTimeout).toHaveBeenCalled();\n });\n\n it(\"should refresh tokens and setup new timer when timeout triggers\", async () => {\n const tokensWithExpiry = {\n ...mockTokens,\n expires_in: 3600,\n };\n const refreshedTokens = {\n ...mockTokens,\n id_token: \"newIdToken\",\n access_token: \"newAccessToken\",\n refresh_token: \"newRefreshToken\",\n expires_in: 3600,\n };\n\n // Reset mock call history\n vi.mocked(retrieveTokens).mockReset();\n vi.mocked(OAuth2Client.prototype.refreshAccessToken).mockReset();\n\n vi.mocked(retrieveTokens)\n .mockResolvedValueOnce(tokensWithExpiry) // First call for initial setup\n .mockResolvedValueOnce(tokensWithExpiry) // Second call in refreshTokens\n .mockResolvedValueOnce(refreshedTokens); // Third call for next setup\n\n vi.mocked(OAuth2Client.prototype.refreshAccessToken).mockResolvedValue(\n refreshedTokens,\n );\n\n await refresher.setupAutorefresh();\n\n // Fast-forward time to trigger the refresh\n await vi.advanceTimersByTimeAsync(3570000); // Use async version\n\n expect(OAuth2Client.prototype.refreshAccessToken).toHaveBeenCalled();\n expect(storeTokens).toHaveBeenCalledWith(mockStorage, refreshedTokens);\n expect(setTimeout).toHaveBeenCalledTimes(2);\n });\n\n it(\"should handle refresh failures gracefully\", async () => {\n const tokensWithExpiry = {\n ...mockTokens,\n expires_in: 3600,\n };\n\n vi.mocked(retrieveTokens).mockResolvedValue(tokensWithExpiry);\n vi.mocked(OAuth2Client.prototype.refreshAccessToken).mockRejectedValue(\n new Error(\"Refresh failed\"),\n );\n\n const consoleSpy = vi\n .spyOn(console, \"error\")\n .mockImplementation(() => {});\n\n await refresher.setupAutorefresh();\n\n // Fast-forward time to trigger the refresh\n vi.advanceTimersByTime(3570000);\n await vi.runAllTimersAsync();\n\n expect(consoleSpy).toHaveBeenCalledWith(\n \"Failed to refresh tokens:\",\n expect.any(Error),\n );\n });\n });\n});\n"]}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=GenericStandaloneAuthenticationRefresher.text.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"GenericStandaloneAuthenticationRefresher.text.d.ts","sourceRoot":"","sources":["../../../../test/unit/shared/GenericStandaloneAuthenticationRefresher.text.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("GenericAuthenticationRefresher", () => {
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(mockTokens);
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.text.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"GenericStandaloneAuthenticationRefresher.text.js","sourceRoot":"","sources":["../../../../test/unit/shared/GenericStandaloneAuthenticationRefresher.text.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n describe,\n it,\n expect,\n vi,\n beforeEach,\n type MockInstance,\n} from \"vitest\";\nimport {\n getEndpointsWithOverrides,\n retrieveTokens,\n storeTokens,\n} from \"@/shared/lib/util.js\";\nimport type { AuthStorage, Endpoints, OIDCTokenResponseBody } from \"@/types.js\";\nimport { OAuth2Client } from \"oslo/oauth2\";\nimport type { AuthConfig } from \"@/server/config.ts\";\nimport { GenericStandaloneAuthenticationRefresher } from \"@/shared/lib/GenericStandaloneAuthenticationRefresher.js\";\n\nvi.mock(\"@/shared/lib/util.js\");\nvi.mock(\"oslo/oauth2\");\n\ndescribe(\"GenericAuthenticationRefresher\", () => {\n const mockAuthConfig: AuthConfig = {\n clientId: \"mockClientId\",\n oauthServer: \"http://mockOauthServer\",\n redirectUrl: \"http://localhost/redirect\",\n };\n const mockEndpoints: Endpoints = {\n auth: \"http://mockAuthEndpoint\",\n token: \"http://mockTokenEndpoint\",\n jwks: \"http://mockJwksEndpoint\",\n userinfo: \"http://mockUserinfoEndpoint\",\n endsession: \"http://mockEndsessionEndpoint\",\n };\n const mockTokens: OIDCTokenResponseBody = {\n id_token: \"mockIdToken\",\n access_token: \"mockAccessToken\",\n refresh_token: \"mockRefreshToken\",\n };\n const mockStorage = {} as AuthStorage;\n\n let refresher: GenericStandaloneAuthenticationRefresher;\n\n beforeEach(async () => {\n vi.clearAllMocks();\n vi.mocked(getEndpointsWithOverrides).mockResolvedValue(mockEndpoints);\n refresher = await GenericStandaloneAuthenticationRefresher.build(\n mockAuthConfig,\n mockStorage,\n );\n });\n\n describe(\"init\", () => {\n it(\"should initialize OAuth2 client with resolved endpoints\", async () => {\n expect(getEndpointsWithOverrides).toHaveBeenCalledWith(\n mockAuthConfig.oauthServer,\n undefined,\n );\n expect(refresher[\"endpoints\"]).toEqual(mockEndpoints);\n expect(refresher[\"oauth2client\"]).toBeInstanceOf(OAuth2Client);\n });\n });\n\n describe(\"refreshTokens\", () => {\n it(\"should refresh tokens and store them\", async () => {\n vi.mocked(retrieveTokens).mockResolvedValue(mockTokens);\n const refreshedTokens: OIDCTokenResponseBody = {\n id_token: \"newIdToken\",\n access_token: \"newAccessToken\",\n refresh_token: \"newRefreshToken\",\n };\n\n vi.mocked(OAuth2Client.prototype.refreshAccessToken).mockResolvedValue(\n refreshedTokens,\n );\n\n const result = await refresher.refreshTokens();\n\n expect(\n refresher[\"oauth2client\"]?.refreshAccessToken,\n ).toHaveBeenCalledWith(mockTokens.refresh_token);\n expect(storeTokens).toHaveBeenCalledWith(mockStorage, refreshedTokens);\n expect(result).toEqual(mockTokens);\n });\n\n it(\"should throw an error if no refresh token is available\", async () => {\n vi.mocked(retrieveTokens).mockResolvedValue({\n ...mockTokens,\n refresh_token: undefined,\n });\n\n await expect(refresher.refreshTokens()).rejects.toThrow(\n \"No refresh token available\",\n );\n });\n });\n\n describe(\"auto refresh\", () => {\n let setTimeoutSpy: MockInstance<typeof setTimeout>;\n let clearTimeoutSpy: MockInstance<typeof clearTimeout>;\n\n beforeEach(() => {\n vi.clearAllMocks(); // Ensure all mocks are reset\n vi.useFakeTimers();\n setTimeoutSpy = vi.spyOn(global, \"setTimeout\");\n clearTimeoutSpy = vi.spyOn(global, \"clearTimeout\");\n });\n\n afterEach(() => {\n vi.useRealTimers();\n setTimeoutSpy.mockRestore();\n clearTimeoutSpy.mockRestore();\n vi.clearAllTimers(); // Clear any pending timers\n });\n\n it(\"should setup auto refresh timer based on token expiry\", async () => {\n const tokensWithExpiry = {\n ...mockTokens,\n expires_in: 3600, // 1 hour\n };\n vi.mocked(retrieveTokens).mockResolvedValue(tokensWithExpiry);\n\n await refresher.setupAutorefresh();\n\n // Should set timeout for (3600 - 30) seconds\n expect(setTimeout).toHaveBeenCalledTimes(1);\n expect(setTimeout).toHaveBeenCalledWith(expect.any(Function), 3570000);\n });\n\n it(\"should clear existing timeout when setting up new refresh\", async () => {\n const tokensWithExpiry = {\n ...mockTokens,\n expires_in: 3600,\n };\n vi.mocked(retrieveTokens).mockResolvedValue(tokensWithExpiry);\n\n // Setup initial timeout\n await refresher.setupAutorefresh();\n\n // Setup another timeout\n await refresher.setupAutorefresh();\n\n expect(clearTimeout).toHaveBeenCalled();\n });\n\n it(\"should refresh tokens and setup new timer when timeout triggers\", async () => {\n const tokensWithExpiry = {\n ...mockTokens,\n expires_in: 3600,\n };\n const refreshedTokens = {\n ...mockTokens,\n id_token: \"newIdToken\",\n access_token: \"newAccessToken\",\n refresh_token: \"newRefreshToken\",\n expires_in: 3600,\n };\n\n // Reset mock call history\n vi.mocked(retrieveTokens).mockReset();\n vi.mocked(OAuth2Client.prototype.refreshAccessToken).mockReset();\n\n vi.mocked(retrieveTokens)\n .mockResolvedValueOnce(tokensWithExpiry) // First call for initial setup\n .mockResolvedValueOnce(tokensWithExpiry) // Second call in refreshTokens\n .mockResolvedValueOnce(refreshedTokens); // Third call for next setup\n\n vi.mocked(OAuth2Client.prototype.refreshAccessToken).mockResolvedValue(\n refreshedTokens,\n );\n\n await refresher.setupAutorefresh();\n\n // Fast-forward time to trigger the refresh\n await vi.advanceTimersByTimeAsync(3570000); // Use async version\n\n expect(OAuth2Client.prototype.refreshAccessToken).toHaveBeenCalled();\n expect(storeTokens).toHaveBeenCalledWith(mockStorage, refreshedTokens);\n expect(setTimeout).toHaveBeenCalledTimes(2);\n });\n\n it(\"should handle refresh failures gracefully\", async () => {\n const tokensWithExpiry = {\n ...mockTokens,\n expires_in: 3600,\n };\n\n vi.mocked(retrieveTokens).mockResolvedValue(tokensWithExpiry);\n vi.mocked(OAuth2Client.prototype.refreshAccessToken).mockRejectedValue(\n new Error(\"Refresh failed\"),\n );\n\n const consoleSpy = vi\n .spyOn(console, \"error\")\n .mockImplementation(() => {});\n\n await refresher.setupAutorefresh();\n\n // Fast-forward time to trigger the refresh\n vi.advanceTimersByTime(3570000);\n await vi.runAllTimersAsync();\n\n expect(consoleSpy).toHaveBeenCalledWith(\n \"Failed to refresh tokens:\",\n expect.any(Error),\n );\n });\n });\n});\n"]}