@inrupt/solid-client-authn-browser 3.1.1 → 4.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.
Files changed (65) hide show
  1. package/README.md +9 -13
  2. package/dist/index.js +28 -38
  3. package/dist/index.js.map +1 -1
  4. package/dist/index.mjs +28 -38
  5. package/dist/index.mjs.map +1 -1
  6. package/dist/solid-client-authn.bundle.js +1 -31
  7. package/dist/solid-client-authn.bundle.js.map +1 -1
  8. package/package.json +4 -4
  9. package/rollup.config.mjs +0 -2
  10. package/src/ClientAuthentication.spec.ts +128 -2
  11. package/src/ClientAuthentication.ts +18 -4
  12. package/src/Session.spec.ts +69 -18
  13. package/src/Session.ts +0 -1
  14. package/src/__mocks__/ClientAuthentication.ts +1 -1
  15. package/src/constant.ts +0 -1
  16. package/src/defaultSession.spec.ts +0 -1
  17. package/src/defaultSession.ts +1 -2
  18. package/src/dependencies.node.spec.ts +0 -1
  19. package/src/dependencies.spec.ts +0 -1
  20. package/src/dependencies.ts +0 -1
  21. package/src/index.browser.spec.ts +0 -1
  22. package/src/index.browser.ts +0 -1
  23. package/src/index.spec.ts +0 -1
  24. package/src/index.ts +0 -1
  25. package/src/login/__mocks__/LoginHandler.ts +0 -1
  26. package/src/login/oidc/AggregateOidcHandler.spec.ts +1 -2
  27. package/src/login/oidc/AggregateOidcHandler.ts +0 -1
  28. package/src/login/oidc/AggregateRedirectHandler.ts +0 -1
  29. package/src/login/oidc/ClientRegistrar.spec.ts +1 -1
  30. package/src/login/oidc/ClientRegistrar.ts +0 -1
  31. package/src/login/oidc/IssuerConfigFetcher.spec.ts +7 -5
  32. package/src/login/oidc/IssuerConfigFetcher.ts +3 -3
  33. package/src/login/oidc/OidcLoginHandler.spec.ts +1 -1
  34. package/src/login/oidc/OidcLoginHandler.ts +0 -1
  35. package/src/login/oidc/Redirector.spec.ts +0 -1
  36. package/src/login/oidc/Redirector.ts +0 -1
  37. package/src/login/oidc/__mocks__/ClientRegistrar.ts +0 -1
  38. package/src/login/oidc/__mocks__/IOidcHandler.ts +1 -3
  39. package/src/login/oidc/__mocks__/IOidcOptions.ts +0 -1
  40. package/src/login/oidc/__mocks__/IssuerConfigFetcher.ts +0 -2
  41. package/src/login/oidc/__mocks__/Redirector.ts +0 -1
  42. package/src/login/oidc/incomingRedirectHandler/AuthCodeRedirectHandler.spec.ts +1 -1
  43. package/src/login/oidc/incomingRedirectHandler/AuthCodeRedirectHandler.ts +0 -1
  44. package/src/login/oidc/incomingRedirectHandler/ErrorOidcHandler.spec.ts +0 -1
  45. package/src/login/oidc/incomingRedirectHandler/ErrorOidcHandler.ts +0 -2
  46. package/src/login/oidc/incomingRedirectHandler/FallbackRedirectHandler.spec.ts +0 -1
  47. package/src/login/oidc/incomingRedirectHandler/FallbackRedirectHandler.ts +1 -2
  48. package/src/login/oidc/oidcHandlers/AuthorizationCodeWithPkceOidcHandler.spec.ts +1 -4
  49. package/src/login/oidc/oidcHandlers/AuthorizationCodeWithPkceOidcHandler.ts +10 -11
  50. package/src/login/oidc/oidcHandlers/OidcHandlerCanHandleTest.ts +0 -1
  51. package/src/login/oidc/refresh/TokenRefresher.spec.ts +1 -1
  52. package/src/login/oidc/refresh/TokenRefresher.ts +0 -2
  53. package/src/login/oidc/refresh/__mocks__/TokenRefresher.ts +0 -2
  54. package/src/logout/buildRpInitiatedLogout.ts +1 -1
  55. package/src/sessionInfo/SessionInfoManager.spec.ts +62 -1
  56. package/src/sessionInfo/SessionInfoManager.ts +6 -1
  57. package/src/sessionInfo/__mocks__/SessionInfoManager.ts +1 -2
  58. package/src/storage/BrowserStorage.spec.ts +0 -1
  59. package/src/storage/BrowserStorage.ts +0 -1
  60. package/src/storage/StorageUtility.ts +0 -1
  61. package/src/storage/__mocks__/LocalStorage.ts +0 -1
  62. package/src/util/UUIDGenerator.spec.ts +0 -1
  63. package/src/util/UuidGenerator.ts +0 -2
  64. package/src/util/__mocks__/UuidGenerator.ts +0 -1
  65. package/typedoc.config.mjs +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inrupt/solid-client-authn-browser",
3
- "version": "3.1.1",
3
+ "version": "4.0.0",
4
4
  "license": "MIT",
5
5
  "types": "dist/index.d.ts",
6
6
  "browser": "dist/index.js",
@@ -26,12 +26,12 @@
26
26
  "build-docs-preview-site": "npm run build-api-docs; cd docs/api; make html"
27
27
  },
28
28
  "devDependencies": {
29
- "@types/node": "^24.9.1",
29
+ "@types/node": "^25.5.0",
30
30
  "@types/uuid": "^10.0.0"
31
31
  },
32
32
  "dependencies": {
33
- "@inrupt/oidc-client-ext": "^3.1.1",
34
- "@inrupt/solid-client-authn-core": "^3.1.1",
33
+ "@inrupt/oidc-client-ext": "^4.0.0",
34
+ "@inrupt/solid-client-authn-core": "^4.0.0",
35
35
  "events": "^3.3.0",
36
36
  "jose": "^5.1.3",
37
37
  "uuid": "^11.1.0"
package/rollup.config.mjs CHANGED
@@ -1,4 +1,3 @@
1
- //
2
1
  // Copyright Inrupt Inc.
3
2
  //
4
3
  // Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -23,7 +22,6 @@ import { nodeResolve } from "@rollup/plugin-node-resolve";
23
22
  import commonjs from "@rollup/plugin-commonjs";
24
23
  import terser from "@rollup/plugin-terser";
25
24
  import createConfig, { createSharedConfig } from "@inrupt/base-rollup-config";
26
- // eslint-disable-next-line import/extensions
27
25
  import pkg from "./package.json" with { type: "json" };
28
26
 
29
27
  export default [
@@ -1,4 +1,3 @@
1
- //
2
1
  // Copyright Inrupt Inc.
3
2
  //
4
3
  // Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -35,6 +34,7 @@ import {
35
34
  mockIncomingRedirectHandler,
36
35
  mockHandleIncomingRedirect,
37
36
  mockLogoutHandler,
37
+ // eslint-disable-next-line import/no-unresolved
38
38
  } from "@inrupt/solid-client-authn-core/mocks";
39
39
 
40
40
  import { mockLoginHandler } from "./login/__mocks__/LoginHandler";
@@ -472,7 +472,7 @@ describe("ClientAuthentication", () => {
472
472
  const url =
473
473
  "https://coolapp.com/redirect?state=someState&code=someAuthCode&iss=someIssuer";
474
474
  await clientAuthn.handleIncomingRedirect(url, mockEmitter);
475
- // eslint-disable-next-line no-restricted-globals
475
+
476
476
  expect(history.replaceState).toHaveBeenCalledWith(
477
477
  null,
478
478
  "",
@@ -601,4 +601,130 @@ describe("ClientAuthentication", () => {
601
601
  );
602
602
  });
603
603
  });
604
+
605
+ describe("validateCurrentSession", () => {
606
+ it("returns clientExpiresAt when expiresAt is in storage", async () => {
607
+ const sessionId = "mySession";
608
+ const expiresAt = Math.floor(Date.now() / 1000) + 10000;
609
+ const mockedStorage = new StorageUtility(
610
+ mockStorage({
611
+ [`${USER_SESSION_PREFIX}:${sessionId}`]: {
612
+ isLoggedIn: "true",
613
+ webId: "https://my.pod/profile#me",
614
+ },
615
+ }),
616
+ mockStorage({
617
+ [`${USER_SESSION_PREFIX}:${sessionId}`]: {
618
+ clientId: "https://some.app/registration",
619
+ clientSecret: "some-secret",
620
+ issuer: "https://some.issuer",
621
+ expiresAt: String(expiresAt),
622
+ },
623
+ }),
624
+ );
625
+ const clientAuthn = getClientAuthentication({
626
+ sessionInfoManager: mockSessionInfoManager(mockedStorage),
627
+ });
628
+
629
+ const result = await clientAuthn.validateCurrentSession(sessionId);
630
+ expect(result).toStrictEqual(
631
+ expect.objectContaining({
632
+ clientExpiresAt: expiresAt,
633
+ }),
634
+ );
635
+ });
636
+
637
+ it("returns null when client has expired", async () => {
638
+ const sessionId = "mySession";
639
+ const expiredAt = Math.floor(Date.now() / 1000) - 1000;
640
+ const mockedStorage = new StorageUtility(
641
+ mockStorage({
642
+ [`${USER_SESSION_PREFIX}:${sessionId}`]: {
643
+ isLoggedIn: "true",
644
+ webId: "https://my.pod/profile#me",
645
+ },
646
+ }),
647
+ mockStorage({
648
+ [`${USER_SESSION_PREFIX}:${sessionId}`]: {
649
+ clientId: "https://some.app/registration",
650
+ clientSecret: "some-secret",
651
+ issuer: "https://some.issuer",
652
+ expiresAt: String(expiredAt),
653
+ },
654
+ }),
655
+ );
656
+ const clientAuthn = getClientAuthentication({
657
+ sessionInfoManager: mockSessionInfoManager(mockedStorage),
658
+ });
659
+
660
+ await expect(
661
+ clientAuthn.validateCurrentSession(sessionId),
662
+ ).resolves.toBeNull();
663
+ });
664
+
665
+ it("returns session when client has not expired", async () => {
666
+ const sessionId = "mySession";
667
+ const futureExpiry = Math.floor(Date.now() / 1000) + 10000;
668
+ const mockedStorage = new StorageUtility(
669
+ mockStorage({
670
+ [`${USER_SESSION_PREFIX}:${sessionId}`]: {
671
+ isLoggedIn: "true",
672
+ webId: "https://my.pod/profile#me",
673
+ },
674
+ }),
675
+ mockStorage({
676
+ [`${USER_SESSION_PREFIX}:${sessionId}`]: {
677
+ clientId: "https://some.app/registration",
678
+ clientSecret: "some-secret",
679
+ issuer: "https://some.issuer",
680
+ expiresAt: String(futureExpiry),
681
+ },
682
+ }),
683
+ );
684
+ const clientAuthn = getClientAuthentication({
685
+ sessionInfoManager: mockSessionInfoManager(mockedStorage),
686
+ });
687
+
688
+ const result = await clientAuthn.validateCurrentSession(sessionId);
689
+ expect(result).not.toBeNull();
690
+ expect(result).toStrictEqual(
691
+ expect.objectContaining({
692
+ clientAppId: "https://some.app/registration",
693
+ issuer: "https://some.issuer",
694
+ }),
695
+ );
696
+ });
697
+
698
+ it("returns session when clientExpiresAt is 0 (never expires per OIDC DCR spec)", async () => {
699
+ const sessionId = "mySession";
700
+ const mockedStorage = new StorageUtility(
701
+ mockStorage({
702
+ [`${USER_SESSION_PREFIX}:${sessionId}`]: {
703
+ isLoggedIn: "true",
704
+ webId: "https://my.pod/profile#me",
705
+ },
706
+ }),
707
+ mockStorage({
708
+ [`${USER_SESSION_PREFIX}:${sessionId}`]: {
709
+ clientId: "https://some.app/registration",
710
+ clientSecret: "some-secret",
711
+ issuer: "https://some.issuer",
712
+ expiresAt: "0",
713
+ },
714
+ }),
715
+ );
716
+ const clientAuthn = getClientAuthentication({
717
+ sessionInfoManager: mockSessionInfoManager(mockedStorage),
718
+ });
719
+
720
+ const result = await clientAuthn.validateCurrentSession(sessionId);
721
+ expect(result).not.toBeNull();
722
+ expect(result).toStrictEqual(
723
+ expect.objectContaining({
724
+ clientAppId: "https://some.app/registration",
725
+ clientExpiresAt: 0,
726
+ }),
727
+ );
728
+ });
729
+ });
604
730
  });
@@ -1,4 +1,3 @@
1
- //
2
1
  // Copyright Inrupt Inc.
3
2
  //
4
3
  // Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -38,6 +37,20 @@ import {
38
37
  import { normalizeCallbackUrl } from "@inrupt/oidc-client-ext";
39
38
  import type { EventEmitter } from "events";
40
39
 
40
+ /**
41
+ * Checks if a client's registration has expired.
42
+ */
43
+ function isClientExpired(sessionInfo: { clientExpiresAt?: number }): boolean {
44
+ // clientExpiresAt === 0 means the client never expires (per OIDC DCR spec)
45
+ if (
46
+ sessionInfo.clientExpiresAt === undefined ||
47
+ sessionInfo.clientExpiresAt === 0
48
+ ) {
49
+ return false;
50
+ }
51
+ return sessionInfo.clientExpiresAt < Math.floor(Date.now() / 1000);
52
+ }
53
+
41
54
  /**
42
55
  * @hidden
43
56
  */
@@ -78,7 +91,7 @@ export default class ClientAuthentication extends ClientAuthenticationBase {
78
91
  };
79
92
 
80
93
  // Collects session information from storage, and returns them. Returns null
81
- // if the expected information cannot be found.
94
+ // if the expected information cannot be found or if the client has expired.
82
95
  // Note that the ID token is not stored, which means the session information
83
96
  // cannot be validated at this point.
84
97
  validateCurrentSession = async (
@@ -88,7 +101,8 @@ export default class ClientAuthentication extends ClientAuthenticationBase {
88
101
  if (
89
102
  sessionInfo === undefined ||
90
103
  sessionInfo.clientAppId === undefined ||
91
- sessionInfo.issuer === undefined
104
+ sessionInfo.issuer === undefined ||
105
+ isClientExpired(sessionInfo)
92
106
  ) {
93
107
  return null;
94
108
  }
@@ -152,7 +166,7 @@ export default class ClientAuthentication extends ClientAuthenticationBase {
152
166
  // 'popstate' event which should be listened to is only sent on active
153
167
  // navigation, which we will not have here.
154
168
  // See https://developer.mozilla.org/en-US/docs/Web/API/Window/popstate_event#when_popstate_is_sent
155
- // eslint-disable-next-line no-await-in-loop
169
+
156
170
  await new Promise<void>((resolve) => {
157
171
  setTimeout(() => resolve(), 1);
158
172
  });
@@ -1,4 +1,3 @@
1
- //
2
1
  // Copyright Inrupt Inc.
3
2
  //
4
3
  // Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -26,6 +25,7 @@ import {
26
25
  StorageUtility,
27
26
  USER_SESSION_PREFIX,
28
27
  } from "@inrupt/solid-client-authn-core";
28
+ // eslint-disable-next-line import/no-unresolved
29
29
  import { mockStorage } from "@inrupt/solid-client-authn-core/mocks";
30
30
  import { EventEmitter } from "stream";
31
31
  import { mockClientAuthentication } from "./__mocks__/ClientAuthentication";
@@ -57,9 +57,9 @@ const mockLocation = (mockedLocation: string) => {
57
57
 
58
58
  // (window as any) is used to override the window type definition and
59
59
  // allow location to be written.
60
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
60
+
61
61
  delete (window as any).location;
62
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
62
+
63
63
  delete (window as any).history.replaceState;
64
64
 
65
65
  // Set our window's location to our test value.
@@ -119,11 +119,10 @@ describe("Session", () => {
119
119
  // Let's make TypeScript and eslint angry! We'll set our window mock to
120
120
  // undefined so that any references to its properties or methods explode.
121
121
  // @ts-ignore-start
122
- // eslint-disable-next-line no-global-assign
122
+
123
123
  window = undefined;
124
124
  // @ts-ignore-end
125
125
  expect(() => {
126
- // eslint-disable-next-line no-new
127
126
  new Session({});
128
127
  }).not.toThrow();
129
128
  });
@@ -136,7 +135,7 @@ describe("Session", () => {
136
135
  const mySession = new Session({ clientAuthentication });
137
136
  // login never resolves if there are no errors,
138
137
  // because a login redirects the user away from the page:
139
- // eslint-disable-next-line no-void
138
+
140
139
  void mySession.login({});
141
140
  expect(clientAuthnLogin).toHaveBeenCalled();
142
141
  });
@@ -147,7 +146,7 @@ describe("Session", () => {
147
146
  const mySession = new Session({ clientAuthentication });
148
147
  // login never resolves if there are no errors,
149
148
  // because a login redirects the user away from the page:
150
- // eslint-disable-next-line no-void
149
+
151
150
  void mySession.login({
152
151
  tokenType: "Bearer",
153
152
  });
@@ -168,7 +167,7 @@ describe("Session", () => {
168
167
  };
169
168
  // login never resolves if there are no errors,
170
169
  // because a login redirects the user away from the page:
171
- // eslint-disable-next-line no-void
170
+
172
171
  void objectWithLogin.login({});
173
172
  expect(clientAuthnLogin).toHaveBeenCalled();
174
173
  });
@@ -380,6 +379,7 @@ describe("Session", () => {
380
379
  "https://my.app/?code=someCode&state=arizona",
381
380
  );
382
381
  // We know that it has been set by the call to `blockingRequest`.
382
+ // FIXME: This can be fixed when we drop support for Node 20 by using Promise.withResolvers.
383
383
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
384
384
  continueAfterSecondRequest!();
385
385
  const tokenRequests = await Promise.all([
@@ -425,7 +425,7 @@ describe("Session", () => {
425
425
  incomingRedirectPromise,
426
426
  ) as typeof clientAuthentication.handleIncomingRedirect;
427
427
  const mySession = new Session({ clientAuthentication });
428
- // eslint-disable-next-line no-void
428
+
429
429
  void mySession.handleIncomingRedirect({
430
430
  url: "https://some.redirect/url",
431
431
  restorePreviousSession: true,
@@ -458,9 +458,12 @@ describe("Session", () => {
458
458
  .mockReturnValueOnce(
459
459
  incomingRedirectPromise,
460
460
  ) as typeof clientAuthentication.handleIncomingRedirect;
461
- const validateCurrentSessionPromise = Promise.resolve(
462
- "https://some.issuer/",
463
- );
461
+ const validateCurrentSessionPromise = Promise.resolve({
462
+ issuer: "https://some.issuer/",
463
+ clientAppId: "some client ID",
464
+ redirectUrl: "https://some.redirect/url",
465
+ tokenType: "DPoP",
466
+ });
464
467
  clientAuthentication.validateCurrentSession = jest
465
468
  .fn()
466
469
  .mockReturnValue(
@@ -468,7 +471,7 @@ describe("Session", () => {
468
471
  ) as typeof clientAuthentication.validateCurrentSession;
469
472
 
470
473
  const mySession = new Session({ clientAuthentication });
471
- // eslint-disable-next-line no-void
474
+
472
475
  void mySession.handleIncomingRedirect({
473
476
  url: "https://some.redirect/url",
474
477
  restorePreviousSession: true,
@@ -507,7 +510,7 @@ describe("Session", () => {
507
510
  undefined,
508
511
  ) as typeof clientAuthentication.handleIncomingRedirect;
509
512
  const mySession = new Session({ clientAuthentication });
510
- // eslint-disable-next-line no-void
513
+
511
514
  void mySession.handleIncomingRedirect({
512
515
  url: "https://some.redirect/url",
513
516
  restorePreviousSession: true,
@@ -536,6 +539,7 @@ describe("Session", () => {
536
539
  issuer: "https://some.issuer",
537
540
  clientAppId: "some client ID",
538
541
  clientAppSecret: "some client secret",
542
+ clientExpiresAt: Math.floor(Date.now() / 1000) + 10000,
539
543
  redirectUrl: "https://some.redirect/url",
540
544
  tokenType: "DPoP",
541
545
  });
@@ -553,7 +557,7 @@ describe("Session", () => {
553
557
  clientAuthentication.login = jest.fn<typeof clientAuthentication.login>();
554
558
 
555
559
  const mySession = new Session({ clientAuthentication });
556
- // eslint-disable-next-line no-void
560
+
557
561
  void mySession.handleIncomingRedirect({
558
562
  url: "https://some.redirect/url",
559
563
  restorePreviousSession: true,
@@ -652,7 +656,7 @@ describe("Session", () => {
652
656
  clientAuthentication.login = jest.fn<typeof clientAuthentication.login>();
653
657
 
654
658
  const mySession = new Session({ clientAuthentication });
655
- // eslint-disable-next-line no-void
659
+
656
660
  void mySession.handleIncomingRedirect("https://some.redirect/url");
657
661
  expect(window.localStorage.getItem(KEY_CURRENT_URL)).toBeNull();
658
662
  expect(clientAuthentication.login).not.toHaveBeenCalled();
@@ -689,7 +693,7 @@ describe("Session", () => {
689
693
  clientAuthentication.login = jest.fn<typeof clientAuthentication.login>();
690
694
 
691
695
  const mySession = new Session({ clientAuthentication });
692
- // eslint-disable-next-line no-void
696
+
693
697
  void mySession.handleIncomingRedirect({
694
698
  url: "https://some.redirect/url",
695
699
  restorePreviousSession: false,
@@ -728,7 +732,7 @@ describe("Session", () => {
728
732
  clientAuthentication.login = jest.fn<typeof clientAuthentication.login>();
729
733
 
730
734
  const mySession = new Session({ clientAuthentication });
731
- // eslint-disable-next-line no-void
735
+
732
736
  void mySession.handleIncomingRedirect("https://some.redirect/url");
733
737
  expect(mySession.info.isLoggedIn).toBe(false);
734
738
  // The local storage should have been cleared by the auth error
@@ -761,6 +765,53 @@ describe("Session", () => {
761
765
  // The local storage should have been cleared by the auth error
762
766
  expect(window.localStorage.getItem(KEY_CURRENT_SESSION)).toBeNull();
763
767
  });
768
+
769
+ it("does not attempt silent authentication if the stored client has expired", async () => {
770
+ const sessionId = "mySession";
771
+ mockLocalStorage({
772
+ [KEY_CURRENT_SESSION]: sessionId,
773
+ });
774
+ mockLocation("https://mock.current/location");
775
+
776
+ // Set up storage with an expired client (expiresAt in the past)
777
+ const expiredAt = Math.floor(Date.now() / 1000) - 1000;
778
+ const mockedStorage = new StorageUtility(
779
+ mockStorage({
780
+ [`${USER_SESSION_PREFIX}:${sessionId}`]: {
781
+ isLoggedIn: "true",
782
+ webId: "https://my.pod/profile#me",
783
+ },
784
+ }),
785
+ mockStorage({
786
+ [`${USER_SESSION_PREFIX}:${sessionId}`]: {
787
+ clientId: "https://some.app/registration",
788
+ clientSecret: "some-secret",
789
+ issuer: "https://some.issuer",
790
+ expiresAt: String(expiredAt),
791
+ },
792
+ }),
793
+ );
794
+ const clientAuthentication = mockClientAuthentication({
795
+ sessionInfoManager: mockSessionInfoManager(mockedStorage),
796
+ });
797
+
798
+ // Mock handleIncomingRedirect to return undefined (no OAuth params in URL)
799
+ clientAuthentication.handleIncomingRedirect = jest
800
+ .fn<typeof clientAuthentication.handleIncomingRedirect>()
801
+ .mockResolvedValue(undefined);
802
+ clientAuthentication.login = jest.fn<typeof clientAuthentication.login>();
803
+
804
+ const mySession = new Session({ clientAuthentication });
805
+ const result = await mySession.handleIncomingRedirect({
806
+ url: "https://some.redirect/url",
807
+ restorePreviousSession: true,
808
+ });
809
+
810
+ // Silent auth should NOT have been attempted because client is expired
811
+ expect(clientAuthentication.login).not.toHaveBeenCalled();
812
+ // The function should resolve (not hang)
813
+ expect(result).toBeUndefined();
814
+ });
764
815
  });
765
816
 
766
817
  describe("events.on", () => {
package/src/Session.ts CHANGED
@@ -1,4 +1,3 @@
1
- //
2
1
  // Copyright Inrupt Inc.
3
2
  //
4
3
  // Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -1,4 +1,3 @@
1
- //
2
1
  // Copyright Inrupt Inc.
3
2
  //
4
3
  // Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -31,6 +30,7 @@ import {
31
30
  mockStorageUtility,
32
31
  mockIncomingRedirectHandler,
33
32
  mockLogoutHandler,
33
+ // eslint-disable-next-line import/no-unresolved
34
34
  } from "@inrupt/solid-client-authn-core/mocks";
35
35
 
36
36
  import ClientAuthentication from "../ClientAuthentication";
package/src/constant.ts CHANGED
@@ -1,4 +1,3 @@
1
- //
2
1
  // Copyright Inrupt Inc.
3
2
  //
4
3
  // Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -1,4 +1,3 @@
1
- //
2
1
  // Copyright Inrupt Inc.
3
2
  //
4
3
  // Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -1,4 +1,3 @@
1
- //
2
1
  // Copyright Inrupt Inc.
3
2
  //
4
3
  // Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -48,7 +47,7 @@ export function getDefaultSession(): Session {
48
47
  * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch}
49
48
  * @since 1.3.0
50
49
  */
51
- /* eslint-disable-next-line no-shadow */
50
+
52
51
  export function fetch(
53
52
  ...args: Parameters<Session["fetch"]>
54
53
  ): ReturnType<Session["fetch"]> {
@@ -1,4 +1,3 @@
1
- //
2
1
  // Copyright Inrupt Inc.
3
2
  //
4
3
  // Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -1,4 +1,3 @@
1
- //
2
1
  // Copyright Inrupt Inc.
3
2
  //
4
3
  // Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -1,4 +1,3 @@
1
- //
2
1
  // Copyright Inrupt Inc.
3
2
  //
4
3
  // Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -1,4 +1,3 @@
1
- //
2
1
  // Copyright Inrupt Inc.
3
2
  //
4
3
  // Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -1,4 +1,3 @@
1
- //
2
1
  // Copyright Inrupt Inc.
3
2
  //
4
3
  // Permission is hereby granted, free of charge, to any person obtaining a copy
package/src/index.spec.ts CHANGED
@@ -1,4 +1,3 @@
1
- //
2
1
  // Copyright Inrupt Inc.
3
2
  //
4
3
  // Permission is hereby granted, free of charge, to any person obtaining a copy
package/src/index.ts CHANGED
@@ -1,4 +1,3 @@
1
- //
2
1
  // Copyright Inrupt Inc.
3
2
  //
4
3
  // Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -1,4 +1,3 @@
1
- //
2
1
  // Copyright Inrupt Inc.
3
2
  //
4
3
  // Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -1,4 +1,3 @@
1
- //
2
1
  // Copyright Inrupt Inc.
3
2
  //
4
3
  // Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -29,7 +28,7 @@ jest.mock("@inrupt/solid-client-authn-core");
29
28
  describe("AggregateOidcHandler", () => {
30
29
  it("should pass injected handlers to its superclass", () => {
31
30
  // We just test if the parent is called.
32
- // eslint-disable-next-line no-new
31
+
33
32
  new AggregateOidcHandler(["Some handler"] as unknown as IOidcHandler[]);
34
33
 
35
34
  expect((AggregateHandler as jest.Mock).mock.calls).toEqual([
@@ -1,4 +1,3 @@
1
- //
2
1
  // Copyright Inrupt Inc.
3
2
  //
4
3
  // Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -1,4 +1,3 @@
1
- //
2
1
  // Copyright Inrupt Inc.
3
2
  //
4
3
  // Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -1,4 +1,3 @@
1
- //
2
1
  // Copyright Inrupt Inc.
3
2
  //
4
3
  // Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -22,6 +21,7 @@
22
21
  import {
23
22
  StorageUtilityMock,
24
23
  mockStorageUtility,
24
+ // eslint-disable-next-line import/no-unresolved
25
25
  } from "@inrupt/solid-client-authn-core/mocks";
26
26
  import { jest, it, describe, expect } from "@jest/globals";
27
27
  import { randomUUID } from "crypto";
@@ -1,4 +1,3 @@
1
- //
2
1
  // Copyright Inrupt Inc.
3
2
  //
4
3
  // Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -1,4 +1,3 @@
1
- //
2
1
  // Copyright Inrupt Inc.
3
2
  //
4
3
  // Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -23,6 +22,9 @@ import { jest, it, describe, expect } from "@jest/globals";
23
22
  import { mockStorageUtility } from "@inrupt/solid-client-authn-core";
24
23
  import IssuerConfigFetcher from "./IssuerConfigFetcher";
25
24
 
25
+ // Camelcase identifiers are required in the OIDC specification.
26
+ /* eslint-disable camelcase*/
27
+
26
28
  /**
27
29
  * Test for IssuerConfigFetcher
28
30
  */
@@ -58,7 +60,7 @@ describe("IssuerConfigFetcher", () => {
58
60
  new Response(
59
61
  JSON.stringify({
60
62
  issuer: "https://example.com",
61
- // eslint-disable-next-line camelcase
63
+
62
64
  claim_types_supported: "oidc",
63
65
  bleepBloop: "Meep Moop",
64
66
  end_session_endpoint: "https://example.com/endSessionEndpoint",
@@ -92,7 +94,7 @@ describe("IssuerConfigFetcher", () => {
92
94
  new Response(
93
95
  JSON.stringify({
94
96
  issuer: "https://example.com",
95
- // eslint-disable-next-line camelcase
97
+
96
98
  claim_types_supported: "oidc",
97
99
  scopes_supported: ["openid", "offline_access", "webid"],
98
100
  }),
@@ -114,7 +116,7 @@ describe("IssuerConfigFetcher", () => {
114
116
  new Response(
115
117
  JSON.stringify({
116
118
  issuer: "https://example.com",
117
- // eslint-disable-next-line camelcase
119
+
118
120
  claim_types_supported: "oidc",
119
121
  }),
120
122
  ),
@@ -136,7 +138,7 @@ describe("IssuerConfigFetcher", () => {
136
138
  new Response(
137
139
  JSON.stringify({
138
140
  issuer: "https://example.com",
139
- // eslint-disable-next-line camelcase
141
+
140
142
  claim_types_supported: "oidc",
141
143
  scopes_supported: ["openid", "offline_access", "webid"],
142
144
  }),
@@ -1,4 +1,3 @@
1
- //
2
1
  // Copyright Inrupt Inc.
3
2
  //
4
3
  // Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -34,9 +33,11 @@ import type {
34
33
  } from "@inrupt/solid-client-authn-core";
35
34
  import { ConfigurationError } from "@inrupt/solid-client-authn-core";
36
35
 
36
+ // Camelcase identifiers are required in the OIDC specification.
37
+ /* eslint-disable camelcase*/
38
+
37
39
  export const WELL_KNOWN_OPENID_CONFIG = ".well-known/openid-configuration";
38
40
 
39
- /* eslint-disable camelcase */
40
41
  const issuerConfigKeyMap: Record<
41
42
  string,
42
43
  { toKey: string; convertToUrl?: boolean }
@@ -127,7 +128,6 @@ const issuerConfigKeyMap: Record<
127
128
  convertToUrl: true,
128
129
  },
129
130
  };
130
- /* eslint-enable camelcase */
131
131
 
132
132
  function processConfig(
133
133
  config: Record<string, string | string[]>,