@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
package/dist/index.js CHANGED
@@ -6,29 +6,98 @@ var EventEmitter = require('events');
6
6
  var oidcClientExt = require('@inrupt/oidc-client-ext');
7
7
  var universalFetch = require('@inrupt/universal-fetch');
8
8
 
9
+ //
10
+ // Copyright Inrupt Inc.
11
+ //
12
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
13
+ // of this software and associated documentation files (the "Software"), to deal in
14
+ // the Software without restriction, including without limitation the rights to use,
15
+ // copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
16
+ // Software, and to permit persons to whom the Software is furnished to do so,
17
+ // subject to the following conditions:
18
+ //
19
+ // The above copyright notice and this permission notice shall be included in
20
+ // all copies or substantial portions of the Software.
21
+ //
22
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
23
+ // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
24
+ // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25
+ // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26
+ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
27
+ // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
+ //
29
+ /**
30
+ * This class in a no-value-added extension of StorageUtility from the core module.
31
+ * The reason it has to be declared is for TSyringe to find the decorators in the
32
+ * same modules as where the dependency container is declared (in this case,
33
+ * the browser module, with the dependancy container in dependencies.ts).
34
+ * @hidden
35
+ */
9
36
  class StorageUtilityBrowser extends solidClientAuthnCore.StorageUtility {
10
37
  constructor(secureStorage, insecureStorage) {
11
38
  super(secureStorage, insecureStorage);
12
39
  }
13
40
  }
14
41
 
42
+ //
43
+ // Copyright Inrupt Inc.
44
+ //
45
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
46
+ // of this software and associated documentation files (the "Software"), to deal in
47
+ // the Software without restriction, including without limitation the rights to use,
48
+ // copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
49
+ // Software, and to permit persons to whom the Software is furnished to do so,
50
+ // subject to the following conditions:
51
+ //
52
+ // The above copyright notice and this permission notice shall be included in
53
+ // all copies or substantial portions of the Software.
54
+ //
55
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
56
+ // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
57
+ // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
58
+ // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
59
+ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
60
+ // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
61
+ //
62
+ /**
63
+ * @hidden
64
+ */
15
65
  class ClientAuthentication extends solidClientAuthnCore.ClientAuthentication {
16
66
  constructor() {
17
67
  super(...arguments);
68
+ // Define these functions as properties so that they don't get accidentally re-bound.
69
+ // Isn't Javascript fun?
18
70
  this.login = async (options, eventEmitter) => {
19
71
  var _a, _b;
72
+ // In order to get a clean start, make sure that the session is logged out
73
+ // on login.
74
+ // But we may want to preserve our client application info, particularly if
75
+ // we used Dynamic Client Registration to register (since we don't
76
+ // necessarily want the user to have to register this app each time they
77
+ // login).
20
78
  await this.sessionInfoManager.clear(options.sessionId);
79
+ // In the case of the user hitting the 'back' button in their browser, they
80
+ // could return to a previous redirect URL that contains OIDC params that
81
+ // are now longer valid. To be safe, strip relevant params now.
82
+ // If the user is providing a redirect IRI, it should not be modified, so
83
+ // normalization only applies if we default to the current location (which is
84
+ // a bad practice and should be discouraged).
21
85
  const redirectUrl = (_a = options.redirectUrl) !== null && _a !== void 0 ? _a : oidcClientExt.removeOidcQueryParam(window.location.href);
22
86
  if (!solidClientAuthnCore.isValidRedirectUrl(redirectUrl)) {
23
- throw new Error(`${redirectUrl} is not a valid redirect URL, it is either a malformed IRI or it includes a hash fragment.`);
87
+ throw new Error(`${redirectUrl} is not a valid redirect URL, it is either a malformed IRI, includes a hash fragment, or reserved query parameters ('code' or 'state').`);
24
88
  }
25
89
  await this.loginHandler.handle({
26
90
  ...options,
27
91
  redirectUrl,
92
+ // If no clientName is provided, the clientId may be used instead.
28
93
  clientName: (_b = options.clientName) !== null && _b !== void 0 ? _b : options.clientId,
29
94
  eventEmitter,
30
95
  });
31
96
  };
97
+ // Collects session information from storage, and returns them. Returns null
98
+ // if the expected information cannot be found.
99
+ // Note that the ID token is not stored, which means the session information
100
+ // cannot be validated at this point.
32
101
  this.validateCurrentSession = async (currentSessionId) => {
33
102
  const sessionInfo = await this.sessionInfoManager.get(currentSessionId);
34
103
  if (sessionInfo === undefined ||
@@ -41,9 +110,14 @@ class ClientAuthentication extends solidClientAuthnCore.ClientAuthentication {
41
110
  this.handleIncomingRedirect = async (url, eventEmitter) => {
42
111
  try {
43
112
  const redirectInfo = await this.redirectHandler.handle(url, eventEmitter);
113
+ // The `FallbackRedirectHandler` directly returns the global `fetch` for
114
+ // his value, so we should ensure it's bound to `window` rather than to
115
+ // ClientAuthentication, to avoid the following error:
116
+ // > 'fetch' called on an object that does not implement interface Window.
44
117
  this.fetch = redirectInfo.fetch.bind(window);
45
118
  this.boundLogout = redirectInfo.getLogoutUrl;
46
- this.cleanUrlAfterRedirect(url);
119
+ // Strip the oauth params:
120
+ await this.cleanUrlAfterRedirect(url);
47
121
  return {
48
122
  isLoggedIn: redirectInfo.isLoggedIn,
49
123
  webId: redirectInfo.webId,
@@ -52,37 +126,89 @@ class ClientAuthentication extends solidClientAuthnCore.ClientAuthentication {
52
126
  };
53
127
  }
54
128
  catch (err) {
55
- this.cleanUrlAfterRedirect(url);
129
+ // Strip the oauth params:
130
+ await this.cleanUrlAfterRedirect(url);
131
+ // FIXME: EVENTS.ERROR should be errorCode, errorDescription
132
+ //
133
+ // I'm not sure if "redirect" is a good error code, and in theory `err`
134
+ // maybe an Error object and not a string; Maybe we want to just hardcode
135
+ // a description instead?
56
136
  eventEmitter.emit(solidClientAuthnCore.EVENTS.ERROR, "redirect", err);
57
137
  return undefined;
58
138
  }
59
139
  };
60
140
  }
61
- cleanUrlAfterRedirect(url) {
141
+ async cleanUrlAfterRedirect(url) {
62
142
  const cleanedUpUrl = new URL(url);
63
143
  cleanedUpUrl.searchParams.delete("state");
144
+ // For auth code flow
64
145
  cleanedUpUrl.searchParams.delete("code");
146
+ // For implicit flow
65
147
  cleanedUpUrl.searchParams.delete("id_token");
66
148
  cleanedUpUrl.searchParams.delete("access_token");
149
+ // For login error
67
150
  cleanedUpUrl.searchParams.delete("error");
68
151
  cleanedUpUrl.searchParams.delete("error_description");
69
152
  cleanedUpUrl.searchParams.delete("iss");
153
+ // Remove OAuth-specific query params (since the login flow finishes with
154
+ // the browser being redirected back with OAuth2 query params (e.g. for
155
+ // 'code' and 'state'), and so if the user simply refreshes this page our
156
+ // authentication library will be called again with what are now invalid
157
+ // query parameters!).
70
158
  window.history.replaceState(null, "", cleanedUpUrl.toString());
159
+ while (window.location.href !== cleanedUpUrl.href) {
160
+ // Poll the current URL every ms. Active polling is required because
161
+ // window.history.replaceState is asynchronous, but the associated
162
+ // 'popstate' event which should be listened to is only sent on active
163
+ // navigation, which we will not have here.
164
+ // See https://developer.mozilla.org/en-US/docs/Web/API/Window/popstate_event#when_popstate_is_sent
165
+ // eslint-disable-next-line no-await-in-loop
166
+ await new Promise((resolve) => {
167
+ setTimeout(() => resolve(), 1);
168
+ });
169
+ }
71
170
  }
72
171
  }
73
172
 
173
+ //
174
+ // Copyright Inrupt Inc.
175
+ //
176
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
177
+ // of this software and associated documentation files (the "Software"), to deal in
178
+ // the Software without restriction, including without limitation the rights to use,
179
+ // copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
180
+ // Software, and to permit persons to whom the Software is furnished to do so,
181
+ // subject to the following conditions:
182
+ //
183
+ // The above copyright notice and this permission notice shall be included in
184
+ // all copies or substantial portions of the Software.
185
+ //
186
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
187
+ // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
188
+ // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
189
+ // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
190
+ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
191
+ // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
192
+ //
74
193
  function hasIssuer(options) {
75
194
  return typeof options.oidcIssuer === "string";
76
195
  }
77
196
  function hasRedirectUrl(options) {
78
197
  return typeof options.redirectUrl === "string";
79
198
  }
199
+ /**
200
+ * @hidden
201
+ */
80
202
  class OidcLoginHandler {
81
203
  constructor(storageUtility, oidcHandler, issuerConfigFetcher, clientRegistrar) {
82
204
  this.storageUtility = storageUtility;
83
205
  this.oidcHandler = oidcHandler;
84
206
  this.issuerConfigFetcher = issuerConfigFetcher;
85
207
  this.clientRegistrar = clientRegistrar;
208
+ this.storageUtility = storageUtility;
209
+ this.oidcHandler = oidcHandler;
210
+ this.issuerConfigFetcher = issuerConfigFetcher;
211
+ this.clientRegistrar = clientRegistrar;
86
212
  }
87
213
  async canHandle(options) {
88
214
  return hasIssuer(options) && hasRedirectUrl(options);
@@ -94,22 +220,57 @@ class OidcLoginHandler {
94
220
  if (!hasRedirectUrl(options)) {
95
221
  throw new solidClientAuthnCore.ConfigurationError(`OidcLoginHandler requires a redirect URL: missing property 'redirectUrl' in ${JSON.stringify(options)}`);
96
222
  }
223
+ // Fetch issuer config.
97
224
  const issuerConfig = await this.issuerConfigFetcher.fetchConfig(options.oidcIssuer);
98
225
  const clientRegistration = await solidClientAuthnCore.handleRegistration(options, issuerConfig, this.storageUtility, this.clientRegistrar);
226
+ // Construct OIDC Options
99
227
  const OidcOptions = {
228
+ // Note that here, the issuer is not the one from the received options, but
229
+ // from the issuer's config. This enforces the canonical URL is used and stored,
230
+ // which is also the one present in the ID token, so storing a technically
231
+ // valid, but different issuer URL (e.g. using a trailing slash or not) now
232
+ // could prevent from validating the ID token later.
100
233
  issuer: issuerConfig.issuer,
234
+ // TODO: differentiate if DPoP should be true
101
235
  dpop: options.tokenType.toLowerCase() === "dpop",
102
236
  ...options,
103
237
  issuerConfiguration: issuerConfig,
104
238
  client: clientRegistration,
105
239
  };
240
+ // Call proper OIDC Handler
106
241
  return this.oidcHandler.handle(OidcOptions);
107
242
  }
108
243
  }
109
244
 
245
+ //
246
+ // Copyright Inrupt Inc.
247
+ //
248
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
249
+ // of this software and associated documentation files (the "Software"), to deal in
250
+ // the Software without restriction, including without limitation the rights to use,
251
+ // copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
252
+ // Software, and to permit persons to whom the Software is furnished to do so,
253
+ // subject to the following conditions:
254
+ //
255
+ // The above copyright notice and this permission notice shall be included in
256
+ // all copies or substantial portions of the Software.
257
+ //
258
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
259
+ // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
260
+ // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
261
+ // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
262
+ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
263
+ // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
264
+ //
265
+ /**
266
+ * @hidden
267
+ * Authorization code flow spec: https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth
268
+ * PKCE: https://tools.ietf.org/html/rfc7636
269
+ */
110
270
  class AuthorizationCodeWithPkceOidcHandler extends solidClientAuthnCore.AuthorizationCodeWithPkceOidcHandlerBase {
111
271
  async handle(oidcLoginOptions) {
112
272
  var _a;
273
+ /* eslint-disable camelcase */
113
274
  const oidcOptions = {
114
275
  authority: oidcLoginOptions.issuer.toString(),
115
276
  client_id: oidcLoginOptions.client.clientId,
@@ -119,28 +280,58 @@ class AuthorizationCodeWithPkceOidcHandler extends solidClientAuthnCore.Authoriz
119
280
  response_type: "code",
120
281
  scope: solidClientAuthnCore.DEFAULT_SCOPES,
121
282
  filterProtocolClaims: true,
283
+ // The userinfo endpoint on NSS fails, so disable this for now
284
+ // Note that in Solid, information should be retrieved from the
285
+ // profile referenced by the WebId.
122
286
  loadUserInfo: false,
123
287
  code_verifier: true,
124
288
  prompt: (_a = oidcLoginOptions.prompt) !== null && _a !== void 0 ? _a : "consent",
125
289
  };
290
+ /* eslint-enable camelcase */
126
291
  const oidcClientLibrary = new oidcClientExt.OidcClient(oidcOptions);
127
292
  try {
128
293
  const signingRequest = await oidcClientLibrary.createSigninRequest();
294
+ // Make sure to await the promise before returning so that the error is caught.
129
295
  return await this.handleRedirect({
130
296
  oidcLoginOptions,
297
+ // eslint-disable-next-line no-underscore-dangle
131
298
  state: signingRequest.state._id,
299
+ // eslint-disable-next-line no-underscore-dangle
132
300
  codeVerifier: signingRequest.state._code_verifier,
133
301
  targetUrl: signingRequest.url.toString(),
134
302
  });
135
303
  }
136
304
  catch (err) {
305
+ // eslint-disable-next-line no-console
137
306
  console.error(err);
138
307
  }
308
+ // The login is only completed AFTER redirect, so nothing to return here.
139
309
  return undefined;
140
310
  }
141
311
  }
142
312
 
313
+ //
314
+ // Copyright Inrupt Inc.
315
+ //
316
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
317
+ // of this software and associated documentation files (the "Software"), to deal in
318
+ // the Software without restriction, including without limitation the rights to use,
319
+ // copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
320
+ // Software, and to permit persons to whom the Software is furnished to do so,
321
+ // subject to the following conditions:
322
+ //
323
+ // The above copyright notice and this permission notice shall be included in
324
+ // all copies or substantial portions of the Software.
325
+ //
326
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
327
+ // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
328
+ // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
329
+ // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
330
+ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
331
+ // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
332
+ //
143
333
  const WELL_KNOWN_OPENID_CONFIG = ".well-known/openid-configuration";
334
+ /* eslint-disable camelcase */
144
335
  const issuerConfigKeyMap = {
145
336
  issuer: {
146
337
  toKey: "issuer",
@@ -228,10 +419,15 @@ const issuerConfigKeyMap = {
228
419
  convertToUrl: true,
229
420
  },
230
421
  };
422
+ /* eslint-enable camelcase */
231
423
  function processConfig(config) {
232
424
  const parsedConfig = {};
233
425
  Object.keys(config).forEach((key) => {
234
426
  if (issuerConfigKeyMap[key]) {
427
+ // TODO: PMcB55: Validate URL if "issuerConfigKeyMap[key].convertToUrl"
428
+ // if (issuerConfigKeyMap[key].convertToUrl) {
429
+ // validateUrl(config[key]);
430
+ // }
235
431
  parsedConfig[issuerConfigKeyMap[key].toKey] = config[key];
236
432
  }
237
433
  });
@@ -240,60 +436,110 @@ function processConfig(config) {
240
436
  }
241
437
  return parsedConfig;
242
438
  }
439
+ /**
440
+ * @hidden
441
+ */
243
442
  class IssuerConfigFetcher {
244
443
  constructor(storageUtility) {
245
444
  this.storageUtility = storageUtility;
445
+ this.storageUtility = storageUtility;
246
446
  }
447
+ // This method needs no state (so can be static), and can be exposed to allow
448
+ // callers to know where this implementation puts state it needs.
247
449
  static getLocalStorageKey(issuer) {
248
450
  return `issuerConfig:${issuer}`;
249
451
  }
250
452
  async fetchConfig(issuer) {
251
453
  let issuerConfig;
252
- const openIdConfigUrl = new URL(WELL_KNOWN_OPENID_CONFIG, issuer.endsWith("/") ? issuer : `${issuer}/`).href;
454
+ const openIdConfigUrl = new URL(WELL_KNOWN_OPENID_CONFIG,
455
+ // Make sure to append a slash at issuer URL, so that the .well-known URL
456
+ // includes the full issuer path. See https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig.
457
+ issuer.endsWith("/") ? issuer : `${issuer}/`).href;
253
458
  const issuerConfigRequestBody = await universalFetch.fetch.call(globalThis, openIdConfigUrl);
459
+ // Check the validity of the fetched config
254
460
  try {
255
461
  issuerConfig = processConfig(await issuerConfigRequestBody.json());
256
462
  }
257
463
  catch (err) {
258
464
  throw new solidClientAuthnCore.ConfigurationError(`[${issuer.toString()}] has an invalid configuration: ${err.message}`);
259
465
  }
466
+ // Update store with fetched config
260
467
  await this.storageUtility.set(IssuerConfigFetcher.getLocalStorageKey(issuer), JSON.stringify(issuerConfig));
261
468
  return issuerConfig;
262
469
  }
263
470
  }
264
471
 
472
+ //
473
+ // Copyright Inrupt Inc.
474
+ //
475
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
476
+ // of this software and associated documentation files (the "Software"), to deal in
477
+ // the Software without restriction, including without limitation the rights to use,
478
+ // copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
479
+ // Software, and to permit persons to whom the Software is furnished to do so,
480
+ // subject to the following conditions:
481
+ //
482
+ // The above copyright notice and this permission notice shall be included in
483
+ // all copies or substantial portions of the Software.
484
+ //
485
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
486
+ // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
487
+ // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
488
+ // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
489
+ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
490
+ // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
491
+ //
492
+ /**
493
+ * @param sessionId
494
+ * @param storage
495
+ * @hidden
496
+ */
265
497
  async function clear(sessionId, storage) {
266
498
  await solidClientAuthnCore.clear(sessionId, storage);
267
499
  await oidcClientExt.clearOidcPersistentStorage();
268
500
  }
501
+ /**
502
+ * @hidden
503
+ */
269
504
  class SessionInfoManager extends solidClientAuthnCore.SessionInfoManagerBase {
270
505
  async get(sessionId) {
271
- var _a;
272
- const isLoggedIn = await this.storageUtility.getForUser(sessionId, "isLoggedIn", {
273
- secure: true,
274
- });
275
- const webId = await this.storageUtility.getForUser(sessionId, "webId", {
276
- secure: true,
277
- });
278
- const clientId = await this.storageUtility.getForUser(sessionId, "clientId", {
279
- secure: false,
280
- });
281
- const clientSecret = await this.storageUtility.getForUser(sessionId, "clientSecret", {
282
- secure: false,
283
- });
284
- const redirectUrl = await this.storageUtility.getForUser(sessionId, "redirectUrl", {
285
- secure: false,
286
- });
287
- const refreshToken = await this.storageUtility.getForUser(sessionId, "refreshToken", {
288
- secure: true,
289
- });
290
- const issuer = await this.storageUtility.getForUser(sessionId, "issuer", {
291
- secure: false,
292
- });
293
- const tokenType = (_a = (await this.storageUtility.getForUser(sessionId, "tokenType", {
294
- secure: false,
295
- }))) !== null && _a !== void 0 ? _a : "DPoP";
296
- if (!solidClientAuthnCore.isSupportedTokenType(tokenType)) {
506
+ const [isLoggedIn, webId, clientId, clientSecret, redirectUrl, refreshToken, issuer, tokenType,] = await Promise.all([
507
+ this.storageUtility.getForUser(sessionId, "isLoggedIn", {
508
+ secure: true,
509
+ }),
510
+ this.storageUtility.getForUser(sessionId, "webId", {
511
+ secure: true,
512
+ }),
513
+ this.storageUtility.getForUser(sessionId, "clientId", {
514
+ secure: false,
515
+ }),
516
+ this.storageUtility.getForUser(sessionId, "clientSecret", {
517
+ secure: false,
518
+ }),
519
+ this.storageUtility.getForUser(sessionId, "redirectUrl", {
520
+ secure: false,
521
+ }),
522
+ this.storageUtility.getForUser(sessionId, "refreshToken", {
523
+ secure: true,
524
+ }),
525
+ this.storageUtility.getForUser(sessionId, "issuer", {
526
+ secure: false,
527
+ }),
528
+ this.storageUtility.getForUser(sessionId, "tokenType", {
529
+ secure: false,
530
+ }),
531
+ ]);
532
+ if (typeof redirectUrl === "string" && !solidClientAuthnCore.isValidRedirectUrl(redirectUrl)) {
533
+ // This resolves the issue for people experiencing https://github.com/inrupt/solid-client-authn-js/issues/2891.
534
+ // An invalid redirect URL is present in the storage, and the session should
535
+ // be cleared to get a fresh start. This will require the user to log back in.
536
+ await Promise.all([
537
+ this.storageUtility.deleteAllUserData(sessionId, { secure: false }),
538
+ this.storageUtility.deleteAllUserData(sessionId, { secure: true }),
539
+ ]);
540
+ return undefined;
541
+ }
542
+ if (tokenType !== undefined && !solidClientAuthnCore.isSupportedTokenType(tokenType)) {
297
543
  throw new Error(`Tokens of type [${tokenType}] are not supported.`);
298
544
  }
299
545
  if (clientId === undefined &&
@@ -311,17 +557,52 @@ class SessionInfoManager extends solidClientAuthnCore.SessionInfoManagerBase {
311
557
  issuer,
312
558
  clientAppId: clientId,
313
559
  clientAppSecret: clientSecret,
314
- tokenType,
560
+ // Default the token type to DPoP if unspecified.
561
+ tokenType: tokenType !== null && tokenType !== void 0 ? tokenType : "DPoP",
315
562
  };
316
563
  }
564
+ /**
565
+ * This function removes all session-related information from storage.
566
+ * @param sessionId the session identifier
567
+ * @param storage the storage where session info is stored
568
+ * @hidden
569
+ */
317
570
  async clear(sessionId) {
318
571
  return clear(sessionId, this.storageUtility);
319
572
  }
320
573
  }
321
574
 
575
+ //
576
+ // Copyright Inrupt Inc.
577
+ //
578
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
579
+ // of this software and associated documentation files (the "Software"), to deal in
580
+ // the Software without restriction, including without limitation the rights to use,
581
+ // copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
582
+ // Software, and to permit persons to whom the Software is furnished to do so,
583
+ // subject to the following conditions:
584
+ //
585
+ // The above copyright notice and this permission notice shall be included in
586
+ // all copies or substantial portions of the Software.
587
+ //
588
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
589
+ // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
590
+ // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
591
+ // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
592
+ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
593
+ // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
594
+ //
595
+ /**
596
+ * This class handles redirect IRIs without any query params, and returns an unauthenticated
597
+ * session. It serves as a fallback so that consuming libraries don't have to test
598
+ * for the query params themselves, and can always try to use them as a redirect IRI.
599
+ * @hidden
600
+ */
322
601
  class FallbackRedirectHandler {
323
602
  async canHandle(redirectUrl) {
324
603
  try {
604
+ // The next URL object is built for validating it.
605
+ // eslint-disable-next-line no-new
325
606
  new URL(redirectUrl);
326
607
  return true;
327
608
  }
@@ -329,12 +610,44 @@ class FallbackRedirectHandler {
329
610
  throw new Error(`[${redirectUrl}] is not a valid URL, and cannot be used as a redirect URL: ${e}`);
330
611
  }
331
612
  }
332
- async handle(_redirectUrl) {
613
+ async handle(
614
+ // The argument is ignored, but must be present to implement the interface
615
+ _redirectUrl) {
333
616
  return solidClientAuthnCore.getUnauthenticatedSession();
334
617
  }
335
618
  }
336
619
 
620
+ //
621
+ // Copyright Inrupt Inc.
622
+ //
623
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
624
+ // of this software and associated documentation files (the "Software"), to deal in
625
+ // the Software without restriction, including without limitation the rights to use,
626
+ // copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
627
+ // Software, and to permit persons to whom the Software is furnished to do so,
628
+ // subject to the following conditions:
629
+ //
630
+ // The above copyright notice and this permission notice shall be included in
631
+ // all copies or substantial portions of the Software.
632
+ //
633
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
634
+ // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
635
+ // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
636
+ // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
637
+ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
638
+ // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
639
+ //
640
+ /**
641
+ * @hidden
642
+ * @packageDocumentation
643
+ */
644
+ // FIXME: The following doesn't work in the browser, it results in all the fetches
645
+ // being unauthenticated. This should be looked into when migrating to universal-fetch.
646
+ // import { fetch } from "cross-fetch";
337
647
  const globalFetch = (...args) => universalFetch.fetch.call(globalThis, ...args);
648
+ /**
649
+ * @hidden
650
+ */
338
651
  class AuthCodeRedirectHandler {
339
652
  constructor(storageUtility, sessionInfoManager, issuerConfigFetcher, clientRegistrar, tokerRefresher) {
340
653
  this.storageUtility = storageUtility;
@@ -342,6 +655,11 @@ class AuthCodeRedirectHandler {
342
655
  this.issuerConfigFetcher = issuerConfigFetcher;
343
656
  this.clientRegistrar = clientRegistrar;
344
657
  this.tokerRefresher = tokerRefresher;
658
+ this.storageUtility = storageUtility;
659
+ this.sessionInfoManager = sessionInfoManager;
660
+ this.issuerConfigFetcher = issuerConfigFetcher;
661
+ this.clientRegistrar = clientRegistrar;
662
+ this.tokerRefresher = tokerRefresher;
345
663
  }
346
664
  async canHandle(redirectUrl) {
347
665
  try {
@@ -379,10 +697,15 @@ class AuthCodeRedirectHandler {
379
697
  if (isDpop) {
380
698
  tokens = await oidcClientExt.getDpopToken(issuerConfig, client, {
381
699
  grantType: "authorization_code",
700
+ // We rely on our 'canHandle' function checking that the OAuth 'code'
701
+ // parameter is present in our query string.
382
702
  code: url.searchParams.get("code"),
383
703
  codeVerifier,
384
704
  redirectUrl: storedRedirectIri,
385
705
  });
706
+ // Delete oidc-client-specific session information from storage. This is
707
+ // done automatically when retrieving a bearer token, but since the DPoP
708
+ // binding uses our custom code, this needs to be done manually.
386
709
  window.localStorage.removeItem(`oidc.${oauthState}`);
387
710
  }
388
711
  else {
@@ -423,12 +746,58 @@ class AuthCodeRedirectHandler {
423
746
  }
424
747
  }
425
748
 
749
+ //
750
+ // Copyright Inrupt Inc.
751
+ //
752
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
753
+ // of this software and associated documentation files (the "Software"), to deal in
754
+ // the Software without restriction, including without limitation the rights to use,
755
+ // copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
756
+ // Software, and to permit persons to whom the Software is furnished to do so,
757
+ // subject to the following conditions:
758
+ //
759
+ // The above copyright notice and this permission notice shall be included in
760
+ // all copies or substantial portions of the Software.
761
+ //
762
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
763
+ // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
764
+ // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
765
+ // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
766
+ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
767
+ // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
768
+ //
769
+ /**
770
+ * @hidden
771
+ */
426
772
  class AggregateRedirectHandler extends solidClientAuthnCore.AggregateHandler {
427
773
  constructor(redirectHandlers) {
428
774
  super(redirectHandlers);
429
775
  }
430
776
  }
431
777
 
778
+ //
779
+ // Copyright Inrupt Inc.
780
+ //
781
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
782
+ // of this software and associated documentation files (the "Software"), to deal in
783
+ // the Software without restriction, including without limitation the rights to use,
784
+ // copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
785
+ // Software, and to permit persons to whom the Software is furnished to do so,
786
+ // subject to the following conditions:
787
+ //
788
+ // The above copyright notice and this permission notice shall be included in
789
+ // all copies or substantial portions of the Software.
790
+ //
791
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
792
+ // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
793
+ // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
794
+ // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
795
+ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
796
+ // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
797
+ //
798
+ /**
799
+ * @hidden
800
+ */
432
801
  class BrowserStorage {
433
802
  get storage() {
434
803
  return window.localStorage;
@@ -444,6 +813,29 @@ class BrowserStorage {
444
813
  }
445
814
  }
446
815
 
816
+ //
817
+ // Copyright Inrupt Inc.
818
+ //
819
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
820
+ // of this software and associated documentation files (the "Software"), to deal in
821
+ // the Software without restriction, including without limitation the rights to use,
822
+ // copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
823
+ // Software, and to permit persons to whom the Software is furnished to do so,
824
+ // subject to the following conditions:
825
+ //
826
+ // The above copyright notice and this permission notice shall be included in
827
+ // all copies or substantial portions of the Software.
828
+ //
829
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
830
+ // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
831
+ // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
832
+ // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
833
+ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
834
+ // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
835
+ //
836
+ /**
837
+ * @hidden
838
+ */
447
839
  class Redirector {
448
840
  redirect(redirectUrl, options) {
449
841
  if (options && options.handleRedirect) {
@@ -458,18 +850,49 @@ class Redirector {
458
850
  }
459
851
  }
460
852
 
853
+ //
854
+ // Copyright Inrupt Inc.
855
+ //
856
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
857
+ // of this software and associated documentation files (the "Software"), to deal in
858
+ // the Software without restriction, including without limitation the rights to use,
859
+ // copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
860
+ // Software, and to permit persons to whom the Software is furnished to do so,
861
+ // subject to the following conditions:
862
+ //
863
+ // The above copyright notice and this permission notice shall be included in
864
+ // all copies or substantial portions of the Software.
865
+ //
866
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
867
+ // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
868
+ // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
869
+ // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
870
+ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
871
+ // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
872
+ //
873
+ /**
874
+ * @hidden
875
+ */
461
876
  class ClientRegistrar {
462
877
  constructor(storageUtility) {
463
878
  this.storageUtility = storageUtility;
879
+ this.storageUtility = storageUtility;
464
880
  }
465
881
  async getClient(options, issuerConfig) {
466
- const [storedClientId, storedClientSecret,] = await Promise.all([
882
+ // If client secret and/or client id are stored in storage, use those.
883
+ const [storedClientId, storedClientSecret,
884
+ // storedClientName,
885
+ ] = await Promise.all([
467
886
  this.storageUtility.getForUser(options.sessionId, "clientId", {
468
887
  secure: false,
469
888
  }),
470
889
  this.storageUtility.getForUser(options.sessionId, "clientSecret", {
471
890
  secure: false,
472
891
  }),
892
+ // this.storageUtility.getForUser(options.sessionId, "clientName", {
893
+ // // FIXME: figure out how to persist secure storage at reload
894
+ // secure: false,
895
+ // }),
473
896
  ]);
474
897
  if (storedClientId) {
475
898
  return {
@@ -480,6 +903,7 @@ class ClientRegistrar {
480
903
  }
481
904
  try {
482
905
  const registeredClient = await oidcClientExt.registerClient(options, issuerConfig);
906
+ // Save info
483
907
  const infoToSave = {
484
908
  clientId: registeredClient.clientId,
485
909
  };
@@ -491,6 +915,9 @@ class ClientRegistrar {
491
915
  registeredClient.idTokenSignedResponseAlg;
492
916
  }
493
917
  await this.storageUtility.setForUser(options.sessionId, infoToSave, {
918
+ // FIXME: figure out how to persist secure storage at reload
919
+ // Otherwise, the client info cannot be retrieved from storage, and
920
+ // the lib tries to re-register the client on each fetch
494
921
  secure: false,
495
922
  });
496
923
  return registeredClient;
@@ -501,9 +928,36 @@ class ClientRegistrar {
501
928
  }
502
929
  }
503
930
 
931
+ //
932
+ // Copyright Inrupt Inc.
933
+ //
934
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
935
+ // of this software and associated documentation files (the "Software"), to deal in
936
+ // the Software without restriction, including without limitation the rights to use,
937
+ // copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
938
+ // Software, and to permit persons to whom the Software is furnished to do so,
939
+ // subject to the following conditions:
940
+ //
941
+ // The above copyright notice and this permission notice shall be included in
942
+ // all copies or substantial portions of the Software.
943
+ //
944
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
945
+ // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
946
+ // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
947
+ // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
948
+ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
949
+ // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
950
+ //
951
+ /**
952
+ * This class handles redirect IRIs without any query params, and returns an unauthenticated
953
+ * session. It serves as a fallback so that consuming libraries don't have to test
954
+ * for the query params themselves, and can always try to use them as a redirect IRI.
955
+ * @hidden
956
+ */
504
957
  class ErrorOidcHandler {
505
958
  async canHandle(redirectUrl) {
506
959
  try {
960
+ // eslint-disable-next-line no-new
507
961
  return new URL(redirectUrl).searchParams.has("error");
508
962
  }
509
963
  catch (e) {
@@ -521,16 +975,47 @@ class ErrorOidcHandler {
521
975
  }
522
976
  }
523
977
 
978
+ //
979
+ // Copyright Inrupt Inc.
980
+ //
981
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
982
+ // of this software and associated documentation files (the "Software"), to deal in
983
+ // the Software without restriction, including without limitation the rights to use,
984
+ // copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
985
+ // Software, and to permit persons to whom the Software is furnished to do so,
986
+ // subject to the following conditions:
987
+ //
988
+ // The above copyright notice and this permission notice shall be included in
989
+ // all copies or substantial portions of the Software.
990
+ //
991
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
992
+ // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
993
+ // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
994
+ // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
995
+ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
996
+ // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
997
+ //
998
+ // Some identifiers are not in camelcase on purpose, as they are named using the
999
+ // official names from the OIDC/OAuth2 specifications.
1000
+ /* eslint-disable camelcase */
1001
+ /**
1002
+ * @hidden
1003
+ */
524
1004
  class TokenRefresher {
525
1005
  constructor(storageUtility, issuerConfigFetcher, clientRegistrar) {
526
1006
  this.storageUtility = storageUtility;
527
1007
  this.issuerConfigFetcher = issuerConfigFetcher;
528
1008
  this.clientRegistrar = clientRegistrar;
1009
+ this.storageUtility = storageUtility;
1010
+ this.issuerConfigFetcher = issuerConfigFetcher;
1011
+ this.clientRegistrar = clientRegistrar;
529
1012
  }
530
1013
  async refresh(sessionId, refreshToken, dpopKey, eventEmitter) {
531
1014
  const oidcContext = await solidClientAuthnCore.loadOidcContextFromStorage(sessionId, this.storageUtility, this.issuerConfigFetcher);
1015
+ // This should also retrieve the client from storage
532
1016
  const clientInfo = await this.clientRegistrar.getClient({ sessionId }, oidcContext.issuerConfig);
533
1017
  if (refreshToken === undefined) {
1018
+ // TODO: in a next PR, look up storage for a refresh token
534
1019
  throw new Error(`Session [${sessionId}] has no refresh token to allow it to refresh its access token.`);
535
1020
  }
536
1021
  if (oidcContext.dpop && dpopKey === undefined) {
@@ -547,6 +1032,31 @@ class TokenRefresher {
547
1032
  }
548
1033
  }
549
1034
 
1035
+ //
1036
+ // Copyright Inrupt Inc.
1037
+ //
1038
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
1039
+ // of this software and associated documentation files (the "Software"), to deal in
1040
+ // the Software without restriction, including without limitation the rights to use,
1041
+ // copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
1042
+ // Software, and to permit persons to whom the Software is furnished to do so,
1043
+ // subject to the following conditions:
1044
+ //
1045
+ // The above copyright notice and this permission notice shall be included in
1046
+ // all copies or substantial portions of the Software.
1047
+ //
1048
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
1049
+ // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
1050
+ // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
1051
+ // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
1052
+ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
1053
+ // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1054
+ //
1055
+ /**
1056
+ *
1057
+ * @param dependencies
1058
+ * @deprecated This function will be removed from the external API in an upcoming release.
1059
+ */
550
1060
  function getClientAuthenticationWithDependencies(dependencies) {
551
1061
  const inMemoryStorage = new solidClientAuthnCore.InMemoryStorage();
552
1062
  const secureStorage = dependencies.secureStorage || inMemoryStorage;
@@ -557,22 +1067,69 @@ function getClientAuthenticationWithDependencies(dependencies) {
557
1067
  const sessionInfoManager = new SessionInfoManager(storageUtility);
558
1068
  const tokenRefresher = new TokenRefresher(storageUtility, issuerConfigFetcher, clientRegistrar);
559
1069
  const redirector = new Redirector();
1070
+ // make new handler for redirect and login
560
1071
  const loginHandler = new OidcLoginHandler(storageUtility, new AuthorizationCodeWithPkceOidcHandler(storageUtility, redirector), issuerConfigFetcher, clientRegistrar);
561
1072
  const redirectHandler = new AggregateRedirectHandler([
562
1073
  new ErrorOidcHandler(),
563
1074
  new AuthCodeRedirectHandler(storageUtility, sessionInfoManager, issuerConfigFetcher, clientRegistrar, tokenRefresher),
1075
+ // This catch-all class will always be able to handle the
1076
+ // redirect IRI, so it must be registered last.
564
1077
  new FallbackRedirectHandler(),
565
1078
  ]);
566
1079
  return new ClientAuthentication(loginHandler, redirectHandler, new solidClientAuthnCore.IWaterfallLogoutHandler(sessionInfoManager, redirector), sessionInfoManager, issuerConfigFetcher);
567
1080
  }
568
1081
 
1082
+ //
1083
+ // Copyright Inrupt Inc.
1084
+ //
1085
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
1086
+ // of this software and associated documentation files (the "Software"), to deal in
1087
+ // the Software without restriction, including without limitation the rights to use,
1088
+ // copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
1089
+ // Software, and to permit persons to whom the Software is furnished to do so,
1090
+ // subject to the following conditions:
1091
+ //
1092
+ // The above copyright notice and this permission notice shall be included in
1093
+ // all copies or substantial portions of the Software.
1094
+ //
1095
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
1096
+ // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
1097
+ // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
1098
+ // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
1099
+ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
1100
+ // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1101
+ //
569
1102
  const KEY_CURRENT_SESSION = `${solidClientAuthnCore.SOLID_CLIENT_AUTHN_KEY_PREFIX}currentSession`;
570
1103
  const KEY_CURRENT_URL = `${solidClientAuthnCore.SOLID_CLIENT_AUTHN_KEY_PREFIX}currentUrl`;
571
1104
 
1105
+ //
1106
+ // Copyright Inrupt Inc.
1107
+ //
1108
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
1109
+ // of this software and associated documentation files (the "Software"), to deal in
1110
+ // the Software without restriction, including without limitation the rights to use,
1111
+ // copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
1112
+ // Software, and to permit persons to whom the Software is furnished to do so,
1113
+ // subject to the following conditions:
1114
+ //
1115
+ // The above copyright notice and this permission notice shall be included in
1116
+ // all copies or substantial portions of the Software.
1117
+ //
1118
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
1119
+ // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
1120
+ // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
1121
+ // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
1122
+ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
1123
+ // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1124
+ //
572
1125
  async function silentlyAuthenticate(sessionId, clientAuthn, session) {
573
1126
  var _a;
574
1127
  const storedSessionInfo = await clientAuthn.validateCurrentSession(sessionId);
575
1128
  if (storedSessionInfo !== null) {
1129
+ // It can be really useful to save the user's current browser location,
1130
+ // so that we can restore it after completing the silent authentication
1131
+ // on incoming redirect. This way, the user is eventually redirected back
1132
+ // to the page they were on and not to the app's redirect page.
576
1133
  window.localStorage.setItem(KEY_CURRENT_URL, window.location.href);
577
1134
  await clientAuthn.login({
578
1135
  sessionId,
@@ -590,21 +1147,68 @@ async function silentlyAuthenticate(sessionId, clientAuthn, session) {
590
1147
  function isLoggedIn(sessionInfo) {
591
1148
  return !!(sessionInfo === null || sessionInfo === void 0 ? void 0 : sessionInfo.isLoggedIn);
592
1149
  }
1150
+ /**
1151
+ * A {@link Session} object represents a user's session on an application. The session holds state, as it stores information enabling acces to private resources after login for instance.
1152
+ */
593
1153
  class Session extends EventEmitter {
1154
+ /**
1155
+ * Session object constructor. Typically called as follows:
1156
+ *
1157
+ * ```typescript
1158
+ * const session = new Session();
1159
+ * ```
1160
+ *
1161
+ * See also [getDefaultSession](https://docs.inrupt.com/developer-tools/api/javascript/solid-client-authn-browser/functions.html#getdefaultsession).
1162
+ *
1163
+ * @param sessionOptions The options enabling the correct instantiation of
1164
+ * the session. Either both storages or clientAuthentication are required. For
1165
+ * more information, see {@link ISessionOptions}.
1166
+ * @param sessionId A string uniquely identifying the session.
1167
+ *
1168
+ */
594
1169
  constructor(sessionOptions = {}, sessionId = undefined) {
595
1170
  super();
596
1171
  this.tokenRequestInProgress = false;
1172
+ /**
1173
+ * Triggers the login process. Note that this method will redirect the user away from your app.
1174
+ *
1175
+ * @param options Parameter to customize the login behaviour. In particular, two options are mandatory: `options.oidcIssuer`, the user's identity provider, and `options.redirectUrl`, the URL to which the user will be redirected after logging in their identity provider.
1176
+ * @returns This method should redirect the user away from the app: it does not return anything. The login process is completed by {@linkcode handleIncomingRedirect}.
1177
+ */
1178
+ // Define these functions as properties so that they don't get accidentally re-bound.
1179
+ // Isn't Javascript fun?
597
1180
  this.login = async (options) => {
598
1181
  var _a;
599
1182
  await this.clientAuthentication.login({
600
1183
  sessionId: this.info.sessionId,
601
1184
  ...options,
1185
+ // Defaults the token type to DPoP
602
1186
  tokenType: (_a = options.tokenType) !== null && _a !== void 0 ? _a : "DPoP",
603
1187
  }, this.events);
1188
+ // `login` redirects the user away from the app,
1189
+ // so unless it throws an error, there is no code that should run afterwards
1190
+ // (since there is no "after" in the lifetime of the script).
1191
+ // Hence, this Promise never resolves:
604
1192
  return new Promise(() => { });
605
1193
  };
1194
+ /**
1195
+ * Fetches data using available login information. If the user is not logged in, this will behave as a regular `fetch`. The signature of this method is identical to the [canonical `fetch`](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API).
1196
+ *
1197
+ * @param url The URL from which data should be fetched.
1198
+ * @param init Optional parameters customizing the request, by specifying an HTTP method, headers, a body, etc. Follows the [WHATWG Fetch Standard](https://fetch.spec.whatwg.org/).
1199
+ */
606
1200
  this.fetch = (url, init) => this.clientAuthentication.fetch(url, init);
1201
+ /**
1202
+ * An internal logout function, to control whether or not the logout signal
1203
+ * should be sent, i.e. if the logout was user-initiated or is the result of
1204
+ * an external event.
1205
+ *
1206
+ * @hidden
1207
+ */
607
1208
  this.internalLogout = async (emitSignal, options) => {
1209
+ // Clearing this value means that silent refresh will no longer be attempted.
1210
+ // In particular, in the case of a silent authentication error it prevents
1211
+ // from getting stuck in an authentication retries loop.
608
1212
  window.localStorage.removeItem(KEY_CURRENT_SESSION);
609
1213
  await this.clientAuthentication.logout(this.info.sessionId, options);
610
1214
  this.info.isLoggedIn = false;
@@ -612,7 +1216,50 @@ class Session extends EventEmitter {
612
1216
  this.events.emit(solidClientAuthnCore.EVENTS.LOGOUT);
613
1217
  }
614
1218
  };
1219
+ /**
1220
+ * Logs the user out of the application.
1221
+ *
1222
+ * There are 2 types of logout supported by this library,
1223
+ * `app` logout and `idp` logout.
1224
+ *
1225
+ * App logout will log the user out within the application
1226
+ * by clearing any session data from the browser. It does
1227
+ * not log the user out of their Solid identity provider,
1228
+ * and should not redirect the user away.
1229
+ * App logout can be performed as follows:
1230
+ * ```typescript
1231
+ * await session.logout({ logoutType: 'app' });
1232
+ * ```
1233
+ *
1234
+ * IDP logout will log the user out of their Solid identity provider,
1235
+ * and will redirect the user away from the application to do so. In order
1236
+ * for users to be redirected back to `postLogoutUrl` you MUST include the
1237
+ * `postLogoutUrl` value in the `post_logout_redirect_uris` field in the
1238
+ * [Client ID Document](https://docs.inrupt.com/ess/latest/security/authentication/#client-identifier-client-id).
1239
+ * IDP logout can be performed as follows:
1240
+ * ```typescript
1241
+ * await session.logout({
1242
+ * logoutType: 'idp',
1243
+ * // An optional URL to redirect to after logout has completed;
1244
+ * // this MUST match a logout URL listed in the Client ID Document
1245
+ * // of the application that is logged in.
1246
+ * // If the application is logged in with a Client ID that is not
1247
+ * // a URI dereferencing to a Client ID Document then users will
1248
+ * // not be redirected back to the `postLogoutUrl` after logout.
1249
+ * postLogoutUrl: 'https://example.com/logout',
1250
+ * // An optional value to be included in the query parameters
1251
+ * // when the IDP provider redirects the user to the postLogoutRedirectUrl.
1252
+ * state: "my-state"
1253
+ * });
1254
+ * ```
1255
+ */
615
1256
  this.logout = async (options) => this.internalLogout(true, options);
1257
+ /**
1258
+ * Completes the login process by processing the information provided by the
1259
+ * Solid identity provider through redirect.
1260
+ *
1261
+ * @param options See {@see IHandleIncomingRedirectOptions}.
1262
+ */
616
1263
  this.handleIncomingRedirect = async (inputOptions = {}) => {
617
1264
  var _a;
618
1265
  if (this.info.isLoggedIn) {
@@ -629,17 +1276,33 @@ class Session extends EventEmitter {
629
1276
  this.setSessionInfo(sessionInfo);
630
1277
  const currentUrl = window.localStorage.getItem(KEY_CURRENT_URL);
631
1278
  if (currentUrl === null) {
1279
+ // The login event can only be triggered **after** the user has been
1280
+ // redirected from the IdP with access and ID tokens.
632
1281
  this.events.emit(solidClientAuthnCore.EVENTS.LOGIN);
633
1282
  }
634
1283
  else {
1284
+ // If an URL is stored in local storage, we are being logged in after a
1285
+ // silent authentication, so remove our currently stored URL location
1286
+ // to clean up our state now that we are completing the re-login process.
635
1287
  window.localStorage.removeItem(KEY_CURRENT_URL);
636
1288
  this.events.emit(solidClientAuthnCore.EVENTS.SESSION_RESTORED, currentUrl);
637
1289
  }
638
1290
  }
639
1291
  else if (options.restorePreviousSession === true) {
1292
+ // Silent authentication happens after a refresh, which means there are no
1293
+ // OAuth params in the current location IRI. It can only succeed if a session
1294
+ // was previously logged in, in which case its ID will be present with a known
1295
+ // identifier in local storage.
1296
+ // Check if we have a locally stored session ID...
640
1297
  const storedSessionId = window.localStorage.getItem(KEY_CURRENT_SESSION);
1298
+ // ...if not, then there is no ID token, and so silent authentication cannot happen, but
1299
+ // if we do have a stored session ID, attempt to re-authenticate now silently.
641
1300
  if (storedSessionId !== null) {
642
1301
  const attemptedSilentAuthentication = await silentlyAuthenticate(storedSessionId, this.clientAuthentication, this);
1302
+ // At this point, we know that the main window will imminently be redirected.
1303
+ // However, this redirect is asynchronous and there is no way to halt execution
1304
+ // until it happens precisely. That's why the current Promise simply does not
1305
+ // resolve.
643
1306
  if (attemptedSilentAuthentication) {
644
1307
  return new Promise(() => { });
645
1308
  }
@@ -648,6 +1311,10 @@ class Session extends EventEmitter {
648
1311
  this.tokenRequestInProgress = false;
649
1312
  return sessionInfo;
650
1313
  };
1314
+ // Until Session no longer implements EventEmitter, this.events is just a proxy
1315
+ // to this (with some interface filtering). When we make the breaking change,
1316
+ // this.events will be a regular EventEmitter (implementing ISessionEventEmitter):
1317
+ // this.events = new EventEmitter();
651
1318
  this.events = new Proxy(this, solidClientAuthnCore.buildProxyHandler(Session.prototype, "events only implements ISessionEventListener"));
652
1319
  if (sessionOptions.clientAuthentication) {
653
1320
  this.clientAuthentication = sessionOptions.clientAuthentication;
@@ -674,22 +1341,63 @@ class Session extends EventEmitter {
674
1341
  isLoggedIn: false,
675
1342
  };
676
1343
  }
1344
+ // When a session is logged in, we want to track its ID in local storage to
1345
+ // enable silent refresh. The current session ID specifically stored in 'localStorage'
1346
+ // (as opposed to using our storage abstraction layer) because it is only
1347
+ // used in a browser-specific mechanism.
677
1348
  this.events.on(solidClientAuthnCore.EVENTS.LOGIN, () => window.localStorage.setItem(KEY_CURRENT_SESSION, this.info.sessionId));
678
1349
  this.events.on(solidClientAuthnCore.EVENTS.SESSION_EXPIRED, () => this.internalLogout(false));
679
1350
  this.events.on(solidClientAuthnCore.EVENTS.ERROR, () => this.internalLogout(false));
680
1351
  }
1352
+ /**
1353
+ * Register a callback function to be called when a user completes login.
1354
+ *
1355
+ * The callback is called when {@link handleIncomingRedirect} completes successfully.
1356
+ *
1357
+ * @param callback The function called when a user completes login.
1358
+ * @deprecated Prefer session.events.on(EVENTS.LOGIN, callback)
1359
+ */
681
1360
  onLogin(callback) {
682
1361
  this.events.on(solidClientAuthnCore.EVENTS.LOGIN, callback);
683
1362
  }
1363
+ /**
1364
+ * Register a callback function to be called when a user logs out:
1365
+ *
1366
+ * @param callback The function called when a user completes logout.
1367
+ * @deprecated Prefer session.events.on(EVENTS.LOGOUT, callback)
1368
+ */
684
1369
  onLogout(callback) {
685
1370
  this.events.on(solidClientAuthnCore.EVENTS.LOGOUT, callback);
686
1371
  }
1372
+ /**
1373
+ * Register a callback function to be called when a user logs out:
1374
+ *
1375
+ * @param callback The function called when an error occurs.
1376
+ * @since 1.11.0
1377
+ * @deprecated Prefer session.events.on(EVENTS.ERROR, callback)
1378
+ */
687
1379
  onError(callback) {
688
1380
  this.events.on(solidClientAuthnCore.EVENTS.ERROR, callback);
689
1381
  }
1382
+ /**
1383
+ * Register a callback function to be called when a session is restored.
1384
+ *
1385
+ * Note: the callback will be called with the saved value of the 'current URL'
1386
+ * at the time the session was restored.
1387
+ *
1388
+ * @param callback The function called when a user's already logged-in session is restored, e.g., after a silent authentication is completed after a page refresh.
1389
+ * @deprecated Prefer session.events.on(EVENTS.SESSION_RESTORED, callback)
1390
+ */
690
1391
  onSessionRestore(callback) {
691
1392
  this.events.on(solidClientAuthnCore.EVENTS.SESSION_RESTORED, callback);
692
1393
  }
1394
+ /**
1395
+ * Register a callback that runs when the session expires and can no longer
1396
+ * make authenticated requests, but following a user logout.
1397
+ * @param callback The function that runs on session expiration.
1398
+ * @since 1.11.0
1399
+ * @deprecated Prefer session.events.on(EVENTS.SESSION_EXPIRED, callback)
1400
+ */
693
1401
  onSessionExpiration(callback) {
694
1402
  this.events.on(solidClientAuthnCore.EVENTS.SESSION_EXPIRED, callback);
695
1403
  }
@@ -704,41 +1412,132 @@ class Session extends EventEmitter {
704
1412
  }
705
1413
  }
706
1414
 
1415
+ //
1416
+ // Copyright Inrupt Inc.
1417
+ //
1418
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
1419
+ // of this software and associated documentation files (the "Software"), to deal in
1420
+ // the Software without restriction, including without limitation the rights to use,
1421
+ // copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
1422
+ // Software, and to permit persons to whom the Software is furnished to do so,
1423
+ // subject to the following conditions:
1424
+ //
1425
+ // The above copyright notice and this permission notice shall be included in
1426
+ // all copies or substantial portions of the Software.
1427
+ //
1428
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
1429
+ // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
1430
+ // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
1431
+ // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
1432
+ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
1433
+ // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1434
+ //
707
1435
  let defaultSession;
1436
+ /**
1437
+ * Obtain the {@link Session} used when not explicitly instantiating one yourself.
1438
+ *
1439
+ * When using the top-level exports {@link fetch}, {@link login}, {@link logout},
1440
+ * {@link handleIncomingRedirect}, {@link onLogin} and {@link onLogout}, these apply to an
1441
+ * implicitly-instantiated {@link Session}.
1442
+ * This function returns a reference to that Session in order to obtain e.g. the current user's
1443
+ * WebID.
1444
+ * @since 1.3.0
1445
+ */
708
1446
  function getDefaultSession() {
709
1447
  if (typeof defaultSession === "undefined") {
710
1448
  defaultSession = new Session();
711
1449
  }
712
1450
  return defaultSession;
713
1451
  }
1452
+ /**
1453
+ * This function's signature is equal to `window.fetch`, but if the current user is authenticated
1454
+ * (see [[login]] and [[handleIncomingRedirect]]), requests made using it will include that user's
1455
+ * credentials. If not, this will behave just like the regular `window.fetch`.
1456
+ *
1457
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch}
1458
+ * @since 1.3.0
1459
+ */
1460
+ /* eslint-disable-next-line no-shadow */
714
1461
  const fetch = (...args) => {
715
1462
  const session = getDefaultSession();
716
1463
  return session.fetch(...args);
717
1464
  };
1465
+ /**
1466
+ * Triggers the login process. Note that this method will redirect the user away from your app.
1467
+ *
1468
+ * @param options Parameter to customize the login behaviour. In particular, two options are mandatory: `options.oidcIssuer`, the user's identity provider, and `options.redirectUrl`, the URL to which the user will be redirected after logging in their identity provider.
1469
+ * @returns This method should redirect the user away from the app: it does not return anything. The login process is completed by [[handleIncomingRedirect]].
1470
+ * @since 1.3.0
1471
+ */
718
1472
  const login = (...args) => {
719
1473
  const session = getDefaultSession();
720
1474
  return session.login(...args);
721
1475
  };
1476
+ /**
1477
+ * Logs the user out of the application.
1478
+ *
1479
+ * By default this does not log the user out of their Solid identity provider.
1480
+ * In order to do so, you must set the logoutType to `idp`. For usage details
1481
+ * see {@link Session.logout}.
1482
+ *
1483
+ * @since 1.3.0
1484
+ */
722
1485
  const logout = (...args) => {
723
1486
  const session = getDefaultSession();
724
1487
  return session.logout(...args);
725
1488
  };
1489
+ /**
1490
+ * Completes the login process by processing the information provided by the Solid identity provider through redirect.
1491
+ *
1492
+ * @param url The URL of the page handling the redirect, including the query parameters — these contain the information to process the login.
1493
+ * @since 1.3.0
1494
+ */
726
1495
  const handleIncomingRedirect = (...args) => {
727
1496
  const session = getDefaultSession();
728
1497
  return session.handleIncomingRedirect(...args);
729
1498
  };
1499
+ /**
1500
+ * Register a callback function to be called when a user completes login.
1501
+ *
1502
+ * The callback is called when {@link handleIncomingRedirect} completes successfully.
1503
+ * @since 1.3.0
1504
+ *
1505
+ * @param callback The function called when a user completes login.
1506
+ * @deprecated Prefer events.on(EVENTS.LOGIN, callback)
1507
+
1508
+ */
730
1509
  const onLogin = (...args) => {
731
1510
  const session = getDefaultSession();
732
1511
  return session.onLogin(...args);
733
1512
  };
1513
+ /**
1514
+ * Register a callback function to be called when a user logs out:
1515
+ *
1516
+ * @param callback The function called when a user completes logout.
1517
+ * @since 1.3.0
1518
+ * @deprecated Prefer events.on(EVENTS.LOGOUT, callback)
1519
+ *
1520
+ */
734
1521
  const onLogout = (...args) => {
735
1522
  const session = getDefaultSession();
736
1523
  return session.onLogout(...args);
737
1524
  };
1525
+ /**
1526
+ * Register a callback function to be called when a session is restored:
1527
+ *
1528
+ * @param callback The function called when a session is restored.
1529
+ * @since 1.3.0
1530
+ * @deprecated Prefer events.on(EVENTS.SESSION_RESTORED, callback)
1531
+ */
738
1532
  const onSessionRestore = (...args) => {
739
1533
  const session = getDefaultSession();
740
1534
  return session.onSessionRestore(...args);
741
1535
  };
1536
+ /**
1537
+ * {@link SessionEventEmitter} instance to subscribe to events by the default session.
1538
+ *
1539
+ * @since 1.14.0
1540
+ */
742
1541
  const events = () => {
743
1542
  return getDefaultSession().events;
744
1543
  };