Skip to content

Commit 7338321

Browse files
committed
fix: insecure token storage when using no non custom domain
1 parent 49c9d60 commit 7338321

File tree

2 files changed

+114
-7
lines changed

2 files changed

+114
-7
lines changed

lib/utils/token/refreshToken.test.ts

+99-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
storageSettings,
66
} from "../../sessionManager";
77
import * as tokenUtils from ".";
8+
import * as refreshTimer from "../refreshTimer";
89

910
describe("refreshToken", () => {
1011
const mockDomain = "https://example.com";
@@ -17,6 +18,8 @@ describe("refreshToken", () => {
1718
vi.resetAllMocks();
1819
vi.spyOn(tokenUtils, "getDecodedToken").mockResolvedValue(null);
1920
vi.spyOn(memoryStorage, "setSessionItem");
21+
vi.spyOn(refreshTimer, "setRefreshTimer");
22+
vi.spyOn(tokenUtils, "refreshToken");
2023
tokenUtils.setActiveStorage(memoryStorage);
2124
global.fetch = vi.fn();
2225
vi.spyOn(console, "error").mockImplementation(() => {});
@@ -192,10 +195,19 @@ describe("refreshToken", () => {
192195
refresh_token: "new-refresh-token",
193196
};
194197
storageSettings.useInsecureForRefreshToken = true;
198+
199+
const insecureStorage = new MemoryStorage();
200+
201+
tokenUtils.setInsecureStorage(insecureStorage);
202+
await insecureStorage.setSessionItem(
203+
StorageKeys.refreshToken,
204+
mockRefreshTokenValue,
205+
);
206+
vi.spyOn(insecureStorage, "setSessionItem");
195207
memoryStorage.getSessionItem = vi
196208
.fn()
197209
.mockResolvedValue(mockRefreshTokenValue);
198-
vi.mocked(global.fetch).mockResolvedValue({
210+
vi.mocked(global.fetch).mockResolvedValueOnce({
199211
ok: true,
200212
json: () => Promise.resolve(mockResponse),
201213
} as Response);
@@ -219,9 +231,94 @@ describe("refreshToken", () => {
219231
StorageKeys.idToken,
220232
"new-id-token",
221233
);
222-
expect(memoryStorage.setSessionItem).toHaveBeenCalledWith(
234+
expect(insecureStorage.setSessionItem).toHaveBeenCalledWith(
235+
StorageKeys.refreshToken,
236+
"new-refresh-token",
237+
);
238+
expect(memoryStorage.setSessionItem).not.toHaveBeenCalledWith(
223239
StorageKeys.refreshToken,
224240
"new-refresh-token",
225241
);
242+
243+
// reset storageSettings to default
244+
storageSettings.useInsecureForRefreshToken = false;
245+
});
246+
247+
it("raise error when no session storage is found when useInsecureForRefreshToken", async () => {
248+
const mockResponse = {
249+
access_token: "new-access-token",
250+
id_token: "new-id-token",
251+
refresh_token: "new-refresh-token",
252+
};
253+
storageSettings.useInsecureForRefreshToken = true;
254+
255+
tokenUtils.clearActiveStorage();
256+
257+
const insecureStorage = new MemoryStorage();
258+
tokenUtils.setInsecureStorage(insecureStorage);
259+
await insecureStorage.setSessionItem(
260+
StorageKeys.refreshToken,
261+
mockRefreshTokenValue,
262+
);
263+
264+
vi.mocked(global.fetch).mockResolvedValueOnce({
265+
ok: true,
266+
json: () => Promise.resolve(mockResponse),
267+
} as Response);
268+
269+
const result = await tokenUtils.refreshToken({
270+
domain: mockDomain,
271+
clientId: mockClientId,
272+
});
273+
274+
expect(result).toStrictEqual({
275+
error: "No active storage found",
276+
success: false,
277+
});
278+
279+
storageSettings.useInsecureForRefreshToken = false;
280+
});
281+
282+
it("triggers new timer when expires_in supplied and calls refreshToken", async () => {
283+
vi.useFakeTimers();
284+
const mockResponse = {
285+
access_token: "new-access-token",
286+
id_token: "new-id-token",
287+
refresh_token: "new-refresh-token",
288+
expires_in: 1000,
289+
};
290+
291+
const insecureStorage = new MemoryStorage();
292+
tokenUtils.setInsecureStorage(insecureStorage);
293+
await insecureStorage.setSessionItem(
294+
StorageKeys.refreshToken,
295+
mockRefreshTokenValue,
296+
);
297+
298+
vi.mocked(global.fetch).mockResolvedValueOnce({
299+
ok: true,
300+
json: () => Promise.resolve(mockResponse),
301+
} as Response);
302+
303+
const result = await tokenUtils.refreshToken({
304+
domain: mockKindeDomain,
305+
clientId: mockClientId,
306+
});
307+
308+
expect(refreshTimer.setRefreshTimer).toHaveBeenCalledWith(
309+
1000,
310+
expect.any(Function),
311+
);
312+
vi.runAllTimers();
313+
expect(tokenUtils.refreshToken).toHaveBeenCalledWith({
314+
domain: mockKindeDomain,
315+
clientId: mockClientId,
316+
});
317+
expect(result).toStrictEqual({
318+
accessToken: "new-access-token",
319+
idToken: "new-id-token",
320+
refreshToken: "new-refresh-token",
321+
success: true,
322+
});
226323
});
227324
});

lib/utils/token/refreshToken.ts

+15-5
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import {
44
StorageKeys,
55
storageSettings,
66
} from "../../sessionManager";
7-
import { sanitizeUrl } from "..";
7+
import { isCustomDomain, sanitizeUrl } from "..";
88
import { clearRefreshTimer, setRefreshTimer } from "../refreshTimer";
99

1010
export interface RefreshTokenResult {
@@ -51,7 +51,7 @@ export const refreshToken = async ({
5151
let refreshTokenValue: string = "";
5252

5353
let storage: SessionManager | null;
54-
if (storageSettings.useInsecureForRefreshToken) {
54+
if (storageSettings.useInsecureForRefreshToken || !isCustomDomain(domain)) {
5555
storage = getInsecureStorage();
5656
} else {
5757
storage = getActiveStorage();
@@ -102,17 +102,27 @@ export const refreshToken = async ({
102102
}
103103
const data = await response.json();
104104
if (data.access_token) {
105+
const secureStore = getActiveStorage();
106+
if (!secureStore) {
107+
return {
108+
success: false,
109+
error: "No active storage found",
110+
};
111+
}
105112
setRefreshTimer(data.expires_in, async () => {
106113
refreshToken({ domain, clientId });
107114
});
108115

109116
if (storage) {
110-
await storage.setSessionItem(
117+
await secureStore.setSessionItem(
111118
StorageKeys.accessToken,
112119
data.access_token,
113120
);
114121
if (data.id_token) {
115-
await storage.setSessionItem(StorageKeys.idToken, data.id_token);
122+
await secureStore.setSessionItem(
123+
StorageKeys.idToken,
124+
data.id_token,
125+
);
116126
}
117127
if (data.refresh_token) {
118128
await storage.setSessionItem(
@@ -142,7 +152,7 @@ export const refreshToken = async ({
142152
} catch (error) {
143153
return {
144154
success: false,
145-
error: `Error refreshing token: ${error}`,
155+
error: `Error refreshing token: ${(error as Error).message}`,
146156
};
147157
}
148158
};

0 commit comments

Comments
 (0)