@inrupt/solid-client-authn-browser 1.17.1 → 1.17.3

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 (58) hide show
  1. package/dist/ClientAuthentication.d.ts +7 -0
  2. package/dist/Session.d.ts +174 -0
  3. package/dist/constant.d.ts +2 -2
  4. package/dist/defaultSession.d.ts +70 -0
  5. package/dist/dependencies.d.ts +12 -0
  6. package/dist/index.js +833 -34
  7. package/dist/index.js.map +1 -1
  8. package/dist/index.mjs +833 -34
  9. package/dist/index.mjs.map +1 -1
  10. package/dist/login/oidc/AggregateOidcHandler.d.ts +10 -0
  11. package/dist/login/oidc/AggregateRedirectHandler.d.ts +10 -0
  12. package/dist/login/oidc/ClientRegistrar.d.ts +7 -0
  13. package/dist/login/oidc/IssuerConfigFetcher.d.ts +10 -0
  14. package/dist/login/oidc/OidcLoginHandler.d.ts +10 -0
  15. package/dist/login/oidc/Redirector.d.ts +7 -0
  16. package/dist/login/oidc/incomingRedirectHandler/AuthCodeRedirectHandler.d.ts +3 -0
  17. package/dist/login/oidc/incomingRedirectHandler/ErrorOidcHandler.d.ts +10 -0
  18. package/dist/login/oidc/incomingRedirectHandler/FallbackRedirectHandler.d.ts +10 -0
  19. package/dist/login/oidc/oidcHandlers/AuthorizationCodeWithPkceOidcHandler.d.ts +12 -0
  20. package/dist/login/oidc/refresh/TokenRefresher.d.ts +7 -0
  21. package/dist/logout/buildRpInitiatedLogout.d.ts +7 -0
  22. package/dist/sessionInfo/SessionInfoManager.d.ts +18 -0
  23. package/dist/solid-client-authn.bundle.js +7 -7
  24. package/dist/solid-client-authn.bundle.js.map +1 -1
  25. package/dist/storage/BrowserStorage.d.ts +7 -0
  26. package/dist/storage/StorageUtility.d.ts +14 -0
  27. package/dist/util/UuidGenerator.d.ts +6 -0
  28. package/package.json +8 -8
  29. package/rollup.config.mjs +1 -1
  30. package/src/ClientAuthentication.spec.ts +106 -57
  31. package/src/ClientAuthentication.ts +18 -7
  32. package/src/Session.spec.ts +51 -54
  33. package/src/Session.ts +24 -18
  34. package/src/__mocks__/ClientAuthentication.ts +2 -2
  35. package/src/defaultSession.ts +4 -3
  36. package/src/dependencies.ts +5 -5
  37. package/src/login/oidc/ClientRegistrar.spec.ts +22 -22
  38. package/src/login/oidc/ClientRegistrar.ts +4 -2
  39. package/src/login/oidc/IssuerConfigFetcher.spec.ts +25 -25
  40. package/src/login/oidc/IssuerConfigFetcher.ts +8 -6
  41. package/src/login/oidc/OidcLoginHandler.spec.ts +15 -15
  42. package/src/login/oidc/OidcLoginHandler.ts +14 -9
  43. package/src/login/oidc/Redirector.spec.ts +1 -1
  44. package/src/login/oidc/__mocks__/ClientRegistrar.ts +3 -3
  45. package/src/login/oidc/__mocks__/IssuerConfigFetcher.ts +3 -3
  46. package/src/login/oidc/incomingRedirectHandler/AuthCodeRedirectHandler.spec.ts +42 -42
  47. package/src/login/oidc/incomingRedirectHandler/AuthCodeRedirectHandler.ts +19 -13
  48. package/src/login/oidc/incomingRedirectHandler/ErrorOidcHandler.spec.ts +12 -12
  49. package/src/login/oidc/incomingRedirectHandler/ErrorOidcHandler.ts +2 -2
  50. package/src/login/oidc/incomingRedirectHandler/FallbackRedirectHandler.spec.ts +7 -7
  51. package/src/login/oidc/incomingRedirectHandler/FallbackRedirectHandler.ts +2 -2
  52. package/src/login/oidc/oidcHandlers/AuthorizationCodeWithPkceOidcHandler.spec.ts +17 -17
  53. package/src/login/oidc/refresh/TokenRefresher.spec.ts +14 -14
  54. package/src/login/oidc/refresh/TokenRefresher.ts +12 -8
  55. package/src/login/oidc/refresh/__mocks__/TokenRefresher.ts +1 -1
  56. package/src/sessionInfo/SessionInfoManager.spec.ts +37 -15
  57. package/src/sessionInfo/SessionInfoManager.ts +46 -50
  58. package/src/sessionInfo/__mocks__/SessionInfoManager.ts +3 -3
@@ -40,7 +40,7 @@ import type ClientAuthentication from "./ClientAuthentication";
40
40
 
41
41
  jest.mock("@inrupt/universal-fetch", () => {
42
42
  const fetchModule = jest.requireActual(
43
- "@inrupt/universal-fetch"
43
+ "@inrupt/universal-fetch",
44
44
  ) as typeof UniversalFetch;
45
45
  return {
46
46
  ...fetchModule,
@@ -164,7 +164,7 @@ describe("Session", () => {
164
164
  expect.objectContaining({
165
165
  tokenType: "Bearer",
166
166
  }),
167
- mySession
167
+ mySession,
168
168
  );
169
169
  });
170
170
 
@@ -246,26 +246,24 @@ describe("Session", () => {
246
246
  it("uses current window location as default redirect URL", async () => {
247
247
  mockLocation("https://some.url");
248
248
  const clientAuthentication = mockClientAuthentication();
249
- const incomingRedirectHandler = jest.spyOn(
250
- clientAuthentication,
251
- "handleIncomingRedirect"
252
- );
249
+ const incomingRedirectHandler = jest
250
+ .spyOn(clientAuthentication, "handleIncomingRedirect")
251
+ .mockResolvedValue(undefined);
253
252
 
254
253
  const mySession = new Session({ clientAuthentication });
255
254
  await mySession.handleIncomingRedirect();
256
255
  expect(incomingRedirectHandler).toHaveBeenCalledWith(
257
256
  "https://some.url",
258
- mySession
257
+ mySession,
259
258
  );
260
259
  });
261
260
 
262
- it("wraps up ClientAuthentication handleIncomingRedirect", async () => {
261
+ it("wraps ClientAuthentication handleIncomingRedirect", async () => {
263
262
  mockLocation("https://some.url");
264
263
  const clientAuthentication = mockClientAuthentication();
265
- const incomingRedirectHandler = jest.spyOn(
266
- clientAuthentication,
267
- "handleIncomingRedirect"
268
- );
264
+ const incomingRedirectHandler = jest
265
+ .spyOn(clientAuthentication, "handleIncomingRedirect")
266
+ .mockResolvedValue(undefined);
269
267
  const mySession = new Session({ clientAuthentication });
270
268
  await mySession.handleIncomingRedirect("https://some.url");
271
269
  expect(incomingRedirectHandler).toHaveBeenCalled();
@@ -299,12 +297,12 @@ describe("Session", () => {
299
297
  sessionId: "a session ID",
300
298
  webId: "https://some.webid#them",
301
299
  };
302
- }
300
+ },
303
301
  );
304
302
  const mySession = new Session({ clientAuthentication });
305
303
  await mySession.handleIncomingRedirect("https://some.url");
306
304
  expect(window.localStorage.getItem(KEY_CURRENT_SESSION)).toBe(
307
- mySession.info.sessionId
305
+ mySession.info.sessionId,
308
306
  );
309
307
  });
310
308
 
@@ -317,7 +315,7 @@ describe("Session", () => {
317
315
  sessionId: "a session ID",
318
316
  webId: "https://some.webid#them",
319
317
  };
320
- }
318
+ },
321
319
  );
322
320
  const mySession = new Session({ clientAuthentication });
323
321
  await mySession.handleIncomingRedirect("https://some.url");
@@ -325,7 +323,7 @@ describe("Session", () => {
325
323
  await mySession.handleIncomingRedirect("https://some.url");
326
324
  // The second request should not hit the wrapped function
327
325
  expect(clientAuthentication.handleIncomingRedirect).toHaveBeenCalledTimes(
328
- 1
326
+ 1,
329
327
  );
330
328
  });
331
329
 
@@ -336,7 +334,7 @@ describe("Session", () => {
336
334
  const clientAuthentication = mockClientAuthentication();
337
335
  const incomingRedirectHandler = jest.spyOn(
338
336
  clientAuthentication,
339
- "handleIncomingRedirect"
337
+ "handleIncomingRedirect",
340
338
  );
341
339
  incomingRedirectHandler.mockResolvedValueOnce({
342
340
  isLoggedIn: true,
@@ -348,14 +346,14 @@ describe("Session", () => {
348
346
  expect(mySession.info.expirationDate).toBe(MOCK_TIMESTAMP + 1337);
349
347
  mySession.emit(EVENTS.SESSION_EXTENDED, 1337 * 2);
350
348
  expect(mySession.info.expirationDate).toBe(
351
- MOCK_TIMESTAMP + 1337 * 2 * 1000
349
+ MOCK_TIMESTAMP + 1337 * 2 * 1000,
352
350
  );
353
351
  });
354
352
 
355
353
  it("leaves the session's info unchanged if no session is obtained after redirect", async () => {
356
354
  const clientAuthentication = mockClientAuthentication();
357
355
  clientAuthentication.handleIncomingRedirect = jest.fn(
358
- async (_url: string) => undefined
356
+ async (_url: string) => undefined,
359
357
  );
360
358
  const mySession = new Session({ clientAuthentication }, "mySession");
361
359
  await mySession.handleIncomingRedirect("https://some.url");
@@ -382,10 +380,10 @@ describe("Session", () => {
382
380
  clientAuthentication.handleIncomingRedirect = jest.fn(blockingRequest);
383
381
  const mySession = new Session({ clientAuthentication });
384
382
  const firstTokenRequest = mySession.handleIncomingRedirect(
385
- "https://my.app/?code=someCode&state=arizona"
383
+ "https://my.app/?code=someCode&state=arizona",
386
384
  );
387
385
  const secondTokenRequest = mySession.handleIncomingRedirect(
388
- "https://my.app/?code=someCode&state=arizona"
386
+ "https://my.app/?code=someCode&state=arizona",
389
387
  );
390
388
  // We know that it has been set by the call to `blockingRequest`.
391
389
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
@@ -401,16 +399,15 @@ describe("Session", () => {
401
399
 
402
400
  it("preserves a binding to its Session instance", async () => {
403
401
  const clientAuthentication = mockClientAuthentication();
404
- const incomingRedirectHandler = jest.spyOn(
405
- clientAuthentication,
406
- "handleIncomingRedirect"
407
- );
402
+ const incomingRedirectHandler = jest
403
+ .spyOn(clientAuthentication, "handleIncomingRedirect")
404
+ .mockResolvedValue(undefined);
408
405
  const mySession = new Session({ clientAuthentication });
409
406
  const objectWithHandleIncomingRedirect = {
410
407
  handleIncomingRedirect: mySession.handleIncomingRedirect,
411
408
  };
412
409
  await objectWithHandleIncomingRedirect.handleIncomingRedirect(
413
- "https://some.url"
410
+ "https://some.url",
414
411
  );
415
412
  expect(incomingRedirectHandler).toHaveBeenCalled();
416
413
  });
@@ -422,7 +419,7 @@ describe("Session", () => {
422
419
  mockLocation("https://mock.current/location");
423
420
  const mockedStorage = new StorageUtility(
424
421
  mockStorage({}),
425
- mockStorage({})
422
+ mockStorage({}),
426
423
  );
427
424
  const clientAuthentication = mockClientAuthentication({
428
425
  sessionInfoManager: mockSessionInfoManager(mockedStorage),
@@ -431,7 +428,7 @@ describe("Session", () => {
431
428
  clientAuthentication.handleIncomingRedirect = jest
432
429
  .fn()
433
430
  .mockReturnValue(
434
- incomingRedirectPromise
431
+ incomingRedirectPromise,
435
432
  ) as typeof clientAuthentication.handleIncomingRedirect;
436
433
  const mySession = new Session({ clientAuthentication });
437
434
  // eslint-disable-next-line no-void
@@ -456,7 +453,7 @@ describe("Session", () => {
456
453
  }),
457
454
  // No session information need to be mocked, because `validateCurrentSession`
458
455
  // itself is mocked.
459
- mockStorage({})
456
+ mockStorage({}),
460
457
  );
461
458
  const clientAuthentication = mockClientAuthentication({
462
459
  sessionInfoManager: mockSessionInfoManager(mockedStorage),
@@ -465,15 +462,15 @@ describe("Session", () => {
465
462
  clientAuthentication.handleIncomingRedirect = jest
466
463
  .fn()
467
464
  .mockReturnValueOnce(
468
- incomingRedirectPromise
465
+ incomingRedirectPromise,
469
466
  ) as typeof clientAuthentication.handleIncomingRedirect;
470
467
  const validateCurrentSessionPromise = Promise.resolve(
471
- "https://some.issuer/"
468
+ "https://some.issuer/",
472
469
  );
473
470
  clientAuthentication.validateCurrentSession = jest
474
471
  .fn()
475
472
  .mockReturnValue(
476
- validateCurrentSessionPromise
473
+ validateCurrentSessionPromise,
477
474
  ) as typeof clientAuthentication.validateCurrentSession;
478
475
 
479
476
  const mySession = new Session({ clientAuthentication });
@@ -485,7 +482,7 @@ describe("Session", () => {
485
482
  await incomingRedirectPromise;
486
483
  await validateCurrentSessionPromise;
487
484
  expect(window.localStorage.getItem(KEY_CURRENT_URL)).toBe(
488
- "https://mock.current/location"
485
+ "https://mock.current/location",
489
486
  );
490
487
  });
491
488
 
@@ -505,7 +502,7 @@ describe("Session", () => {
505
502
  [`${USER_SESSION_PREFIX}:${sessionId}`]: {
506
503
  clientId: "value doesn't matter",
507
504
  },
508
- })
505
+ }),
509
506
  );
510
507
  const clientAuthentication = mockClientAuthentication({
511
508
  sessionInfoManager: mockSessionInfoManager(mockedStorage),
@@ -513,7 +510,7 @@ describe("Session", () => {
513
510
  clientAuthentication.handleIncomingRedirect = (
514
511
  jest.fn() as any
515
512
  ).mockResolvedValue(
516
- undefined
513
+ undefined,
517
514
  ) as typeof clientAuthentication.handleIncomingRedirect;
518
515
  const mySession = new Session({ clientAuthentication });
519
516
  // eslint-disable-next-line no-void
@@ -536,7 +533,7 @@ describe("Session", () => {
536
533
  isLoggedIn: "true",
537
534
  },
538
535
  }),
539
- mockStorage({})
536
+ mockStorage({}),
540
537
  );
541
538
  const clientAuthentication = mockClientAuthentication({
542
539
  sessionInfoManager: mockSessionInfoManager(mockedStorage),
@@ -551,13 +548,13 @@ describe("Session", () => {
551
548
  clientAuthentication.validateCurrentSession = jest
552
549
  .fn()
553
550
  .mockReturnValue(
554
- validateCurrentSessionPromise
551
+ validateCurrentSessionPromise,
555
552
  ) as typeof clientAuthentication.validateCurrentSession;
556
553
  const incomingRedirectPromise = Promise.resolve();
557
554
  clientAuthentication.handleIncomingRedirect = jest
558
555
  .fn()
559
556
  .mockReturnValueOnce(
560
- incomingRedirectPromise
557
+ incomingRedirectPromise,
561
558
  ) as typeof clientAuthentication.handleIncomingRedirect;
562
559
  clientAuthentication.login = jest.fn<typeof clientAuthentication.login>();
563
560
 
@@ -579,11 +576,11 @@ describe("Session", () => {
579
576
  clientSecret: "some client secret",
580
577
  redirectUrl: "https://some.redirect/url",
581
578
  },
582
- expect.anything()
579
+ expect.anything(),
583
580
  );
584
581
  // Check that second parameter is of type session
585
582
  expect(
586
- (clientAuthentication.login as any).mock.calls[0][1]
583
+ (clientAuthentication.login as any).mock.calls[0][1],
587
584
  ).toBeInstanceOf(Session);
588
585
  });
589
586
 
@@ -599,7 +596,7 @@ describe("Session", () => {
599
596
  isLoggedIn: "true",
600
597
  },
601
598
  }),
602
- mockStorage({})
599
+ mockStorage({}),
603
600
  );
604
601
  const clientAuthentication = mockClientAuthentication({
605
602
  sessionInfoManager: mockSessionInfoManager(mockedStorage),
@@ -608,13 +605,13 @@ describe("Session", () => {
608
605
  clientAuthentication.validateCurrentSession = jest
609
606
  .fn()
610
607
  .mockReturnValue(
611
- validateCurrentSessionPromise
608
+ validateCurrentSessionPromise,
612
609
  ) as typeof clientAuthentication.validateCurrentSession;
613
610
  const incomingRedirectPromise = Promise.resolve();
614
611
  clientAuthentication.handleIncomingRedirect = jest
615
612
  .fn()
616
613
  .mockReturnValueOnce(
617
- incomingRedirectPromise
614
+ incomingRedirectPromise,
618
615
  ) as typeof clientAuthentication.handleIncomingRedirect;
619
616
  clientAuthentication.login = jest.fn<typeof clientAuthentication.login>();
620
617
 
@@ -640,7 +637,7 @@ describe("Session", () => {
640
637
  isLoggedIn: "true",
641
638
  },
642
639
  }),
643
- mockStorage({})
640
+ mockStorage({}),
644
641
  );
645
642
  const clientAuthentication = mockClientAuthentication({
646
643
  sessionInfoManager: mockSessionInfoManager(mockedStorage),
@@ -656,7 +653,7 @@ describe("Session", () => {
656
653
  clientAuthentication.handleIncomingRedirect = (
657
654
  jest.fn() as any
658
655
  ).mockResolvedValue(
659
- undefined
656
+ undefined,
660
657
  ) as typeof clientAuthentication.handleIncomingRedirect;
661
658
  clientAuthentication.login = jest.fn<typeof clientAuthentication.login>();
662
659
 
@@ -679,7 +676,7 @@ describe("Session", () => {
679
676
  isLoggedIn: "true",
680
677
  },
681
678
  }),
682
- mockStorage({})
679
+ mockStorage({}),
683
680
  );
684
681
  const clientAuthentication = mockClientAuthentication({
685
682
  sessionInfoManager: mockSessionInfoManager(mockedStorage),
@@ -720,7 +717,7 @@ describe("Session", () => {
720
717
  isLoggedIn: "true",
721
718
  },
722
719
  }),
723
- mockStorage({})
720
+ mockStorage({}),
724
721
  );
725
722
  const clientAuthentication = mockClientAuthentication({
726
723
  sessionInfoManager: mockSessionInfoManager(mockedStorage),
@@ -759,7 +756,7 @@ describe("Session", () => {
759
756
  isLoggedIn: "true",
760
757
  },
761
758
  }),
762
- mockStorage({})
759
+ mockStorage({}),
763
760
  );
764
761
  const clientAuthentication = mockClientAuthentication({
765
762
  sessionInfoManager: mockSessionInfoManager(mockedStorage),
@@ -781,7 +778,7 @@ describe("Session", () => {
781
778
  mySession.emit(EVENTS.ERROR, "error", "error_description");
782
779
  expect(onErrorCallback).toHaveBeenCalledWith(
783
780
  "error",
784
- "error_description"
781
+ "error_description",
785
782
  );
786
783
  });
787
784
  });
@@ -807,7 +804,7 @@ describe("Session", () => {
807
804
  it("does not call the registered callback if login isn't successful", async () => {
808
805
  const failCallback = (): void => {
809
806
  throw new Error(
810
- "Should *NOT* call callback - this means test has failed!"
807
+ "Should *NOT* call callback - this means test has failed!",
811
808
  );
812
809
  };
813
810
  const clientAuthentication = mockClientAuthentication();
@@ -818,12 +815,12 @@ describe("Session", () => {
818
815
  sessionId: "a session ID",
819
816
  webId: "https://some.webid#them",
820
817
  };
821
- }
818
+ },
822
819
  );
823
820
  const mySession = new Session({ clientAuthentication });
824
821
  mySession.onLogin(failCallback);
825
822
  await expect(
826
- mySession.handleIncomingRedirect("https://some.url")
823
+ mySession.handleIncomingRedirect("https://some.url"),
827
824
  ).resolves.not.toThrow();
828
825
  });
829
826
 
@@ -836,7 +833,7 @@ describe("Session", () => {
836
833
  sessionId: "a session ID",
837
834
  webId: "https://some.webid#them",
838
835
  };
839
- }
836
+ },
840
837
  );
841
838
  const mySession = new Session({ clientAuthentication });
842
839
  const myCallback = jest.fn((): void => {
@@ -1035,7 +1032,7 @@ describe("Session", () => {
1035
1032
  const mySession = new Session();
1036
1033
  // @ts-expect-error onLogin is a function on Session, and not SessionEventEmitter
1037
1034
  expect(() => mySession.events.onLogin(jest.fn())).toThrow(
1038
- "[onLogin] is not supported"
1035
+ "[onLogin] is not supported",
1039
1036
  );
1040
1037
  });
1041
1038
  });
package/src/Session.ts CHANGED
@@ -101,7 +101,7 @@ export interface IHandleIncomingRedirectOptions {
101
101
  export async function silentlyAuthenticate(
102
102
  sessionId: string,
103
103
  clientAuthn: ClientAuthentication,
104
- session: Session
104
+ session: Session,
105
105
  ): Promise<boolean> {
106
106
  const storedSessionInfo = await clientAuthn.validateCurrentSession(sessionId);
107
107
  if (storedSessionInfo !== null) {
@@ -120,7 +120,7 @@ export async function silentlyAuthenticate(
120
120
  clientSecret: storedSessionInfo.clientAppSecret,
121
121
  tokenType: storedSessionInfo.tokenType ?? "DPoP",
122
122
  },
123
- session.events
123
+ session.events,
124
124
  );
125
125
  return true;
126
126
  }
@@ -128,7 +128,7 @@ export async function silentlyAuthenticate(
128
128
  }
129
129
 
130
130
  function isLoggedIn(
131
- sessionInfo?: ISessionInfo
131
+ sessionInfo?: ISessionInfo,
132
132
  ): sessionInfo is ISessionInfo & { isLoggedIn: true } {
133
133
  return !!sessionInfo?.isLoggedIn;
134
134
  }
@@ -170,7 +170,7 @@ export class Session extends EventEmitter implements IHasSessionEventListener {
170
170
  */
171
171
  constructor(
172
172
  sessionOptions: Partial<ISessionOptions> = {},
173
- sessionId: string | undefined = undefined
173
+ sessionId: string | undefined = undefined,
174
174
  ) {
175
175
  super();
176
176
  // Until Session no longer implements EventEmitter, this.events is just a proxy
@@ -181,8 +181,8 @@ export class Session extends EventEmitter implements IHasSessionEventListener {
181
181
  this,
182
182
  buildProxyHandler(
183
183
  Session.prototype,
184
- "events only implements ISessionEventListener"
185
- )
184
+ "events only implements ISessionEventListener",
185
+ ),
186
186
  );
187
187
  if (sessionOptions.clientAuthentication) {
188
188
  this.clientAuthentication = sessionOptions.clientAuthentication;
@@ -213,7 +213,7 @@ export class Session extends EventEmitter implements IHasSessionEventListener {
213
213
  // (as opposed to using our storage abstraction layer) because it is only
214
214
  // used in a browser-specific mechanism.
215
215
  this.events.on(EVENTS.LOGIN, () =>
216
- window.localStorage.setItem(KEY_CURRENT_SESSION, this.info.sessionId)
216
+ window.localStorage.setItem(KEY_CURRENT_SESSION, this.info.sessionId),
217
217
  );
218
218
 
219
219
  this.events.on(EVENTS.SESSION_EXPIRED, () => this.internalLogout(false));
@@ -237,7 +237,7 @@ export class Session extends EventEmitter implements IHasSessionEventListener {
237
237
  // Defaults the token type to DPoP
238
238
  tokenType: options.tokenType ?? "DPoP",
239
239
  },
240
- this.events
240
+ this.events,
241
241
  );
242
242
  // `login` redirects the user away from the app,
243
243
  // so unless it throws an error, there is no code that should run afterwards
@@ -264,7 +264,7 @@ export class Session extends EventEmitter implements IHasSessionEventListener {
264
264
  */
265
265
  private internalLogout = async (
266
266
  emitSignal: boolean,
267
- options?: ILogoutOptions
267
+ options?: ILogoutOptions,
268
268
  ): Promise<void> => {
269
269
  // Clearing this value means that silent refresh will no longer be attempted.
270
270
  // In particular, in the case of a silent authentication error it prevents
@@ -293,14 +293,20 @@ export class Session extends EventEmitter implements IHasSessionEventListener {
293
293
  * ```
294
294
  *
295
295
  * IDP logout will log the user out of their Solid identity provider,
296
- * and will redirect the user away from the application to do so.
296
+ * and will redirect the user away from the application to do so. In order
297
+ * for users to be redirected back to `postLogoutUrl` you MUST include the
298
+ * `postLogoutUrl` value in the `post_logout_redirect_uris` field in the
299
+ * [Client ID Document](https://docs.inrupt.com/ess/latest/security/authentication/#client-identifier-client-id).
297
300
  * IDP logout can be performed as follows:
298
301
  * ```typescript
299
302
  * await session.logout({
300
303
  * logoutType: 'idp',
301
304
  * // An optional URL to redirect to after logout has completed;
302
- * // this MUST match a logout URL listed in the clientId of
303
- * // the application that is logged in.
305
+ * // this MUST match a logout URL listed in the Client ID Document
306
+ * // of the application that is logged in.
307
+ * // If the application is logged in with a Client ID that is not
308
+ * // a URI dereferencing to a Client ID Document then users will
309
+ * // not be redirected back to the `postLogoutUrl` after logout.
304
310
  * postLogoutUrl: 'https://example.com/logout',
305
311
  * // An optional value to be included in the query parameters
306
312
  * // when the IDP provider redirects the user to the postLogoutRedirectUrl.
@@ -318,7 +324,7 @@ export class Session extends EventEmitter implements IHasSessionEventListener {
318
324
  * @param options See {@see IHandleIncomingRedirectOptions}.
319
325
  */
320
326
  handleIncomingRedirect = async (
321
- inputOptions: string | IHandleIncomingRedirectOptions = {}
327
+ inputOptions: string | IHandleIncomingRedirectOptions = {},
322
328
  ): Promise<ISessionInfo | undefined> => {
323
329
  if (this.info.isLoggedIn) {
324
330
  return this.info;
@@ -334,7 +340,7 @@ export class Session extends EventEmitter implements IHasSessionEventListener {
334
340
  this.tokenRequestInProgress = true;
335
341
  const sessionInfo = await this.clientAuthentication.handleIncomingRedirect(
336
342
  url,
337
- this.events
343
+ this.events,
338
344
  );
339
345
  if (isLoggedIn(sessionInfo)) {
340
346
  this.setSessionInfo(sessionInfo);
@@ -363,7 +369,7 @@ export class Session extends EventEmitter implements IHasSessionEventListener {
363
369
  const attemptedSilentAuthentication = await silentlyAuthenticate(
364
370
  storedSessionId,
365
371
  this.clientAuthentication,
366
- this
372
+ this,
367
373
  );
368
374
  // At this point, we know that the main window will imminently be redirected.
369
375
  // However, this redirect is asynchronous and there is no way to halt execution
@@ -410,8 +416,8 @@ export class Session extends EventEmitter implements IHasSessionEventListener {
410
416
  onError(
411
417
  callback: (
412
418
  error: string | null,
413
- errorDescription?: string | null
414
- ) => unknown
419
+ errorDescription?: string | null,
420
+ ) => unknown,
415
421
  ): void {
416
422
  this.events.on(EVENTS.ERROR, callback);
417
423
  }
@@ -441,7 +447,7 @@ export class Session extends EventEmitter implements IHasSessionEventListener {
441
447
  }
442
448
 
443
449
  private setSessionInfo(
444
- sessionInfo: ISessionInfo & { isLoggedIn: true }
450
+ sessionInfo: ISessionInfo & { isLoggedIn: true },
445
451
  ): void {
446
452
  this.info.isLoggedIn = sessionInfo.isLoggedIn;
447
453
  this.info.webId = sessionInfo.webId;
@@ -48,7 +48,7 @@ type ClientAuthnDependencies = {
48
48
  };
49
49
 
50
50
  export const mockClientAuthentication = (
51
- mocks?: Partial<ClientAuthnDependencies>
51
+ mocks?: Partial<ClientAuthnDependencies>,
52
52
  ): ClientAuthentication => {
53
53
  const storage = mocks?.storage ?? mockStorageUtility({});
54
54
  return new ClientAuthentication(
@@ -56,6 +56,6 @@ export const mockClientAuthentication = (
56
56
  mocks?.redirectHandler ?? mockIncomingRedirectHandler(),
57
57
  mocks?.logoutHandler ?? mockLogoutHandler(storage),
58
58
  mocks?.sessionInfoManager ?? mockSessionInfoManager(storage),
59
- mocks?.issuerConfigFetcher ?? IssuerConfigFetcherMock
59
+ mocks?.issuerConfigFetcher ?? IssuerConfigFetcherMock,
60
60
  );
61
61
  };
@@ -70,7 +70,8 @@ export const login: Session["login"] = (...args) => {
70
70
  * Logs the user out of the application.
71
71
  *
72
72
  * By default this does not log the user out of their Solid identity provider.
73
- * In order to do so, you must set the logoutType to `idp`.
73
+ * In order to do so, you must set the logoutType to `idp`. For usage details
74
+ * see {@link Session.logout}.
74
75
  *
75
76
  * @since 1.3.0
76
77
  */
@@ -113,7 +114,7 @@ export const onLogin: Session["onLogin"] = (...args) => {
113
114
  * @param callback The function called when a user completes logout.
114
115
  * @since 1.3.0
115
116
  * @deprecated Prefer events.on(EVENTS.LOGOUT, callback)
116
-
117
+ *
117
118
  */
118
119
  export const onLogout: Session["onLogout"] = (...args) => {
119
120
  const session = getDefaultSession();
@@ -135,7 +136,7 @@ export const onSessionRestore: Session["onSessionRestore"] = (...args) => {
135
136
  /**
136
137
  * {@link SessionEventEmitter} instance to subscribe to events by the default session.
137
138
  *
138
- * @since Unreleased
139
+ * @since 1.14.0
139
140
  */
140
141
  export const events = (): Session["events"] => {
141
142
  return getDefaultSession().events;
@@ -62,7 +62,7 @@ export function getClientAuthenticationWithDependencies(dependencies: {
62
62
 
63
63
  const storageUtility = new StorageUtilityBrowser(
64
64
  secureStorage,
65
- insecureStorage
65
+ insecureStorage,
66
66
  );
67
67
 
68
68
  const issuerConfigFetcher = new IssuerConfigFetcher(storageUtility);
@@ -73,7 +73,7 @@ export function getClientAuthenticationWithDependencies(dependencies: {
73
73
  const tokenRefresher = new TokenRefresher(
74
74
  storageUtility,
75
75
  issuerConfigFetcher,
76
- clientRegistrar
76
+ clientRegistrar,
77
77
  );
78
78
 
79
79
  const redirector = new Redirector();
@@ -83,7 +83,7 @@ export function getClientAuthenticationWithDependencies(dependencies: {
83
83
  storageUtility,
84
84
  new AuthorizationCodeWithPkceOidcHandler(storageUtility, redirector),
85
85
  issuerConfigFetcher,
86
- clientRegistrar
86
+ clientRegistrar,
87
87
  );
88
88
 
89
89
  const redirectHandler = new AggregateRedirectHandler([
@@ -93,7 +93,7 @@ export function getClientAuthenticationWithDependencies(dependencies: {
93
93
  sessionInfoManager,
94
94
  issuerConfigFetcher,
95
95
  clientRegistrar,
96
- tokenRefresher
96
+ tokenRefresher,
97
97
  ),
98
98
  // This catch-all class will always be able to handle the
99
99
  // redirect IRI, so it must be registered last.
@@ -105,6 +105,6 @@ export function getClientAuthenticationWithDependencies(dependencies: {
105
105
  redirectHandler,
106
106
  new IWaterfallLogoutHandler(sessionInfoManager, redirector),
107
107
  sessionInfoManager,
108
- issuerConfigFetcher
108
+ issuerConfigFetcher,
109
109
  );
110
110
  }