@inrupt/solid-client-authn-browser 4.0.0 → 5.0.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inrupt/solid-client-authn-browser",
3
- "version": "4.0.0",
3
+ "version": "5.0.0",
4
4
  "license": "MIT",
5
5
  "types": "dist/index.d.ts",
6
6
  "browser": "dist/index.js",
@@ -26,15 +26,15 @@
26
26
  "build-docs-preview-site": "npm run build-api-docs; cd docs/api; make html"
27
27
  },
28
28
  "devDependencies": {
29
- "@types/node": "^25.5.0",
30
- "@types/uuid": "^10.0.0"
29
+ "@types/node": "^25.9.1",
30
+ "@types/uuid": "^11.0.0"
31
31
  },
32
32
  "dependencies": {
33
- "@inrupt/oidc-client-ext": "^4.0.0",
34
- "@inrupt/solid-client-authn-core": "^4.0.0",
33
+ "@inrupt/oidc-client-ext": "^5.0.0",
34
+ "@inrupt/solid-client-authn-core": "^5.0.0",
35
35
  "events": "^3.3.0",
36
- "jose": "^5.1.3",
37
- "uuid": "^11.1.0"
36
+ "jose": "^6.2.3",
37
+ "uuid": "^14.0.0"
38
38
  },
39
39
  "publishConfig": {
40
40
  "access": "public"
@@ -22,6 +22,8 @@ import { jest, it, describe, expect, beforeEach } from "@jest/globals";
22
22
  import { EventEmitter } from "events";
23
23
  import type * as SolidClientAuthnCore from "@inrupt/solid-client-authn-core";
24
24
 
25
+ declare const __setTestUrl: (url: string) => void;
26
+
25
27
  import {
26
28
  StorageUtility,
27
29
  USER_SESSION_PREFIX,
@@ -108,11 +110,7 @@ describe("ClientAuthentication", () => {
108
110
 
109
111
  beforeEach(() => {
110
112
  jest.clearAllMocks();
111
-
112
- Object.defineProperty(window, "location", {
113
- writable: true,
114
- value: { assign: jest.fn() },
115
- });
113
+ __setTestUrl("http://localhost/");
116
114
  });
117
115
 
118
116
  describe("login", () => {
@@ -122,7 +120,7 @@ describe("ClientAuthentication", () => {
122
120
  it("calls login, and uses the window.location.href for the redirect if no redirectUrl is set", async () => {
123
121
  // Set a current window location which will be the expected URL to be
124
122
  // redirected back to, since we don't pass redirectUrl:
125
- window.location.href = "https://coolapp.test/some/redirect";
123
+ __setTestUrl("https://coolapp.test/some/redirect");
126
124
 
127
125
  const clientAuthn = getClientAuthentication();
128
126
  await clientAuthn.login(
@@ -353,11 +351,11 @@ describe("ClientAuthentication", () => {
353
351
  // TODO: add tests for events & errors
354
352
 
355
353
  it("reverts back to un-authenticated fetch on logout", async () => {
356
- window.history.replaceState = jest
357
- .fn<typeof window.history.replaceState>()
354
+ jest
355
+ .spyOn(window.history, "replaceState")
358
356
  .mockImplementationOnce((_data, _unused, url) => {
359
357
  // Pretend the current location is updated
360
- window.location.href = url as string;
358
+ __setTestUrl(url as string);
361
359
  });
362
360
  const clientAuthn = getClientAuthentication();
363
361
 
@@ -423,11 +421,11 @@ describe("ClientAuthentication", () => {
423
421
  mockEmitter.emit = jest.fn<typeof mockEmitter.emit>();
424
422
 
425
423
  it("calls handle redirect", async () => {
426
- window.history.replaceState = jest
427
- .fn<typeof window.history.replaceState>()
424
+ jest
425
+ .spyOn(window.history, "replaceState")
428
426
  .mockImplementationOnce((_data, _unused, url) => {
429
427
  // Pretend the current location is updated
430
- window.location.href = url as string;
428
+ __setTestUrl(url as string);
431
429
  });
432
430
  const expectedResult = SessionCreatorCreateResponse;
433
431
  const clientAuthn = getClientAuthentication();
@@ -462,11 +460,11 @@ describe("ClientAuthentication", () => {
462
460
  });
463
461
 
464
462
  it("clears the current IRI from OAuth query parameters in the auth code flow", async () => {
465
- window.history.replaceState = jest
466
- .fn<typeof window.history.replaceState>()
463
+ jest
464
+ .spyOn(window.history, "replaceState")
467
465
  .mockImplementationOnce((_data, _unused, url) => {
468
466
  // Pretend the current location is updated
469
- window.location.href = url as string;
467
+ __setTestUrl(url as string);
470
468
  });
471
469
  const clientAuthn = getClientAuthentication();
472
470
  const url =
@@ -482,11 +480,11 @@ describe("ClientAuthentication", () => {
482
480
  });
483
481
 
484
482
  it("clears the current IRI from OAuth query parameters even if auth flow fails", async () => {
485
- window.history.replaceState = jest
486
- .fn<typeof window.history.replaceState>()
483
+ jest
484
+ .spyOn(window.history, "replaceState")
487
485
  .mockImplementationOnce((_data, _unused, url) => {
488
486
  // Pretend the current location is updated
489
- window.location.href = url as string;
487
+ __setTestUrl(url as string);
490
488
  });
491
489
 
492
490
  mockHandleIncomingRedirect.mockImplementationOnce(() =>
@@ -512,11 +510,11 @@ describe("ClientAuthentication", () => {
512
510
  });
513
511
 
514
512
  it("preserves non-OAuth query strings", async () => {
515
- window.history.replaceState = jest
516
- .fn<typeof window.history.replaceState>()
513
+ jest
514
+ .spyOn(window.history, "replaceState")
517
515
  .mockImplementationOnce((_data, _unused, url) => {
518
516
  // Pretend the current location is updated
519
- window.location.href = url as string;
517
+ __setTestUrl(url as string);
520
518
  });
521
519
  const clientAuthn = getClientAuthentication();
522
520
  const url =
@@ -46,27 +46,11 @@ const mockLocalStorage = (stored: Record<string, string>) => {
46
46
  });
47
47
  };
48
48
 
49
+ declare const __setTestUrl: (url: string) => void;
50
+
49
51
  const mockLocation = (mockedLocation: string) => {
50
- // We can't simply do 'window.location.href = defaultLocation;', as that
51
- // causes our test environment to try to navigate to the new location (as
52
- // a browser would do). So instead we need to reset 'window.location' as a
53
- // whole, and reset it's value after our test. We also need to
54
- // replace the 'history' object, otherwise this error happens: "SecurityError:
55
- // replaceState cannot update history to a URL which differs in components other
56
- // than in path, query, or fragment.""
57
-
58
- // (window as any) is used to override the window type definition and
59
- // allow location to be written.
60
-
61
- delete (window as any).location;
62
-
63
- delete (window as any).history.replaceState;
64
-
65
- // Set our window's location to our test value.
66
- (window as any).location = {
67
- href: mockedLocation,
68
- } as Location;
69
- window.history.replaceState = jest.fn();
52
+ __setTestUrl(mockedLocation);
53
+ jest.spyOn(window.history, "replaceState").mockImplementation(() => {});
70
54
  };
71
55
 
72
56
  describe("Session", () => {
@@ -234,7 +218,7 @@ describe("Session", () => {
234
218
 
235
219
  describe("handleIncomingRedirect", () => {
236
220
  it("uses current window location as default redirect URL", async () => {
237
- mockLocation("https://some.url");
221
+ mockLocation("https://some.url/");
238
222
  const clientAuthentication = mockClientAuthentication();
239
223
  const incomingRedirectHandler = jest
240
224
  .spyOn(clientAuthentication, "handleIncomingRedirect")
@@ -243,13 +227,13 @@ describe("Session", () => {
243
227
  const mySession = new Session({ clientAuthentication });
244
228
  await mySession.handleIncomingRedirect();
245
229
  expect(incomingRedirectHandler).toHaveBeenCalledWith(
246
- "https://some.url",
230
+ "https://some.url/",
247
231
  mySession.events,
248
232
  );
249
233
  });
250
234
 
251
235
  it("wraps ClientAuthentication handleIncomingRedirect", async () => {
252
- mockLocation("https://some.url");
236
+ mockLocation("https://some.url/");
253
237
  const clientAuthentication = mockClientAuthentication();
254
238
  const incomingRedirectHandler = jest
255
239
  .spyOn(clientAuthentication, "handleIncomingRedirect")
@@ -31,39 +31,23 @@ import Redirector from "./Redirector";
31
31
  /**
32
32
  * Test for Redirector
33
33
  */
34
+ declare const __setTestUrl: (url: string) => void;
35
+
34
36
  describe("Redirector", () => {
35
37
  describe("redirect", () => {
36
- const {
37
- location,
38
- history: { replaceState },
39
- } = window;
40
-
41
38
  beforeEach(() => {
42
- // location and history aren't optional on window, which makes TS complain
43
- // (rightfully) when we delete them. However, they are deleted on purpose
44
- // here just for testing.
45
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
46
- // @ts-ignore
47
- delete window.location;
48
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
49
- // @ts-ignore
50
- delete window.history.replaceState;
51
- (window as any).location = {
52
- href: "https://coolSite.com",
53
- } as Location;
54
- window.history.replaceState = jest.fn();
39
+ __setTestUrl("https://coolSite.com");
40
+ jest.spyOn(window.history, "replaceState").mockImplementation(() => {});
55
41
  });
56
42
 
57
43
  afterEach(() => {
58
- (window as any).location = location;
59
- window.history.replaceState = replaceState;
44
+ jest.restoreAllMocks();
60
45
  });
61
46
 
62
47
  it("browser redirection defaults to using href", () => {
63
48
  const redirector = new Redirector();
64
49
  redirector.redirect("https://someUrl.com/redirect");
65
50
  expect(window.history.replaceState).not.toHaveBeenCalled();
66
- expect(window.location.href).toBe("https://someUrl.com/redirect");
67
51
  });
68
52
 
69
53
  it("browser redirection uses replaceState if specified", () => {
@@ -76,7 +60,6 @@ describe("Redirector", () => {
76
60
  "",
77
61
  "https://someUrl.com/redirect",
78
62
  );
79
- expect(window.location.href).toBe("https://coolSite.com");
80
63
  });
81
64
 
82
65
  it("calls redirect handler", () => {
@@ -34,9 +34,8 @@ import {
34
34
  } from "@inrupt/solid-client-authn-core/mocks";
35
35
  import { jest, it, describe, expect } from "@jest/globals";
36
36
  import type * as OidcClientExt from "@inrupt/oidc-client-ext";
37
- import type { JWK } from "jose";
37
+ import type { JWK, CryptoKey } from "jose";
38
38
  import { importJWK } from "jose";
39
- import type { KeyObject } from "crypto";
40
39
  import { AuthCodeRedirectHandler } from "./AuthCodeRedirectHandler";
41
40
  import { SessionInfoManagerMock } from "../../../sessionInfo/__mocks__/SessionInfoManager";
42
41
  import { LocalStorageMock } from "../../../storage/__mocks__/LocalStorage";
@@ -126,7 +125,7 @@ const mockTokenEndpointDpopResponse =
126
125
  webId: mockWebId(),
127
126
  clientId: "some client",
128
127
  dpopKey: {
129
- privateKey: (await importJWK(mockJwk())) as KeyObject,
128
+ privateKey: (await importJWK(mockJwk())) as CryptoKey,
130
129
  // Note that here for convenience the private key is also used as public key.
131
130
  // Obviously, this should never be done in non-test code.
132
131
  publicKey: mockJwk(),
@@ -29,11 +29,10 @@ import {
29
29
  mockStorageUtility,
30
30
  // eslint-disable-next-line import/no-unresolved
31
31
  } from "@inrupt/solid-client-authn-core/mocks";
32
- import type { JWK } from "jose";
32
+ import type { JWK, CryptoKey } from "jose";
33
33
  import { importJWK } from "jose";
34
34
  import type { refresh } from "@inrupt/oidc-client-ext";
35
35
  import { EventEmitter } from "events";
36
- import type { KeyObject } from "crypto";
37
36
  import TokenRefresher from "./TokenRefresher";
38
37
  import {
39
38
  mockDefaultIssuerConfigFetcher,
@@ -70,7 +69,7 @@ const mockJwk = (): JWK => {
70
69
 
71
70
  const mockKeyPair = async (): Promise<KeyPair> => {
72
71
  return {
73
- privateKey: (await importJWK(mockJwk())) as KeyObject,
72
+ privateKey: (await importJWK(mockJwk())) as CryptoKey,
74
73
  // Use the same JWK for public and private key out of convenience, don't do
75
74
  // this in real life.
76
75
  publicKey: mockJwk(),