@inrupt/solid-client-authn-browser 1.11.8-alpha.1 → 1.11.8-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ClientAuthentication.d.ts +18 -17
- package/dist/Session.d.ts +35 -35
- package/dist/constant.d.ts +2 -2
- package/dist/defaultSession.d.ts +9 -9
- package/dist/dependencies.d.ts +6 -6
- package/dist/iframe.d.ts +3 -3
- package/dist/index.d.ts +4 -4
- package/dist/index.es.js +1693 -0
- package/dist/index.js +1717 -27
- package/dist/login/AggregateLoginHandler.d.ts +4 -4
- package/dist/login/oidc/AggregateOidcHandler.d.ts +4 -4
- package/dist/login/oidc/ClientRegistrar.d.ts +6 -6
- package/dist/login/oidc/IssuerConfigFetcher.d.ts +8 -8
- package/dist/login/oidc/OidcLoginHandler.d.ts +10 -10
- package/dist/login/oidc/Redirector.d.ts +4 -4
- package/dist/login/oidc/oidcHandlers/AuthorizationCodeWithPkceOidcHandler.d.ts +8 -8
- package/dist/login/oidc/oidcHandlers/OidcHandlerCanHandleTest.d.ts +9 -9
- package/dist/login/oidc/redirectHandler/AggregateRedirectHandler.d.ts +4 -4
- package/dist/login/oidc/redirectHandler/AuthCodeRedirectHandler.d.ts +15 -15
- package/dist/login/oidc/redirectHandler/ErrorOidcHandler.d.ts +9 -9
- package/dist/login/oidc/redirectHandler/FallbackRedirectHandler.d.ts +7 -7
- package/dist/login/oidc/refresh/TokenRefresher.d.ts +10 -10
- package/dist/login/webid/WebIdLoginHandler.d.ts +5 -5
- package/dist/logout/GeneralLogoutHandler.d.ts +7 -7
- package/dist/sessionInfo/SessionInfoManager.d.ts +16 -16
- package/dist/solid-client-authn.bundle.js +1720 -2
- package/dist/storage/BrowserStorage.d.ts +7 -7
- package/dist/storage/StorageUtility.d.ts +4 -4
- package/dist/util/UuidGenerator.d.ts +6 -6
- package/dist/util/urlPath.d.ts +1 -1
- package/examples/demoClientApp/package-lock.json +67 -0
- package/examples/demoClientApp/package.json +2 -1
- package/examples/demoClientApp/src/DemoClientApp.js +9 -1
- package/jest.config.js +2 -1
- package/package.json +13 -10
- package/rollup.config.js +57 -0
- package/src/ClientAuthentication.spec.ts +69 -1
- package/src/ClientAuthentication.ts +32 -14
- package/src/login/oidc/oidcHandlers/AuthorizationCodeWithPkceOidcHandler.spec.ts +2 -9
- package/src/login/oidc/redirectHandler/__mocks__/RedirectHandler.ts +13 -0
- package/src/index.browser.spec.ts +0 -27
- package/src/index.browser.ts +0 -24
- package/webpack.browser.js +0 -19
- package/webpack.common.js +0 -22
- package/webpack.config.js +0 -8
- package/webpack.dev.js +0 -17
- package/webpack.prod.js +0 -3
package/dist/index.es.js
ADDED
|
@@ -0,0 +1,1693 @@
|
|
|
1
|
+
import { StorageUtility, determineSigningAlg, PREFERRED_SIGNING_ALG, getWebidFromTokenPayload, createDpopHeader, OidcProviderError, InvalidResponseError, generateDpopKeyPair, EVENTS, ConfigurationError, handleRegistration, isSupportedTokenType, loadOidcContextFromStorage, buildAuthenticatedFetch, AggregateHandler, InMemoryStorage, SOLID_CLIENT_AUTHN_KEY_PREFIX } from '@inrupt/solid-client-authn-core';
|
|
2
|
+
export { ConfigurationError, InMemoryStorage, NotImplementedError } from '@inrupt/solid-client-authn-core';
|
|
3
|
+
import { OidcClient, WebStorageStateStore } from '@inrupt/oidc-client';
|
|
4
|
+
|
|
5
|
+
var domain;
|
|
6
|
+
|
|
7
|
+
// This constructor is used to store event handlers. Instantiating this is
|
|
8
|
+
// faster than explicitly calling `Object.create(null)` to get a "clean" empty
|
|
9
|
+
// object (tested with v8 v4.9).
|
|
10
|
+
function EventHandlers() {}
|
|
11
|
+
EventHandlers.prototype = Object.create(null);
|
|
12
|
+
|
|
13
|
+
function EventEmitter() {
|
|
14
|
+
EventEmitter.init.call(this);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// nodejs oddity
|
|
18
|
+
// require('events') === require('events').EventEmitter
|
|
19
|
+
EventEmitter.EventEmitter = EventEmitter;
|
|
20
|
+
|
|
21
|
+
EventEmitter.usingDomains = false;
|
|
22
|
+
|
|
23
|
+
EventEmitter.prototype.domain = undefined;
|
|
24
|
+
EventEmitter.prototype._events = undefined;
|
|
25
|
+
EventEmitter.prototype._maxListeners = undefined;
|
|
26
|
+
|
|
27
|
+
// By default EventEmitters will print a warning if more than 10 listeners are
|
|
28
|
+
// added to it. This is a useful default which helps finding memory leaks.
|
|
29
|
+
EventEmitter.defaultMaxListeners = 10;
|
|
30
|
+
|
|
31
|
+
EventEmitter.init = function() {
|
|
32
|
+
this.domain = null;
|
|
33
|
+
if (EventEmitter.usingDomains) {
|
|
34
|
+
// if there is an active domain, then attach to it.
|
|
35
|
+
if (domain.active ) ;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (!this._events || this._events === Object.getPrototypeOf(this)._events) {
|
|
39
|
+
this._events = new EventHandlers();
|
|
40
|
+
this._eventsCount = 0;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
this._maxListeners = this._maxListeners || undefined;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// Obviously not all Emitters should be limited to 10. This function allows
|
|
47
|
+
// that to be increased. Set to zero for unlimited.
|
|
48
|
+
EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) {
|
|
49
|
+
if (typeof n !== 'number' || n < 0 || isNaN(n))
|
|
50
|
+
throw new TypeError('"n" argument must be a positive number');
|
|
51
|
+
this._maxListeners = n;
|
|
52
|
+
return this;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
function $getMaxListeners(that) {
|
|
56
|
+
if (that._maxListeners === undefined)
|
|
57
|
+
return EventEmitter.defaultMaxListeners;
|
|
58
|
+
return that._maxListeners;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
EventEmitter.prototype.getMaxListeners = function getMaxListeners() {
|
|
62
|
+
return $getMaxListeners(this);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
// These standalone emit* functions are used to optimize calling of event
|
|
66
|
+
// handlers for fast cases because emit() itself often has a variable number of
|
|
67
|
+
// arguments and can be deoptimized because of that. These functions always have
|
|
68
|
+
// the same number of arguments and thus do not get deoptimized, so the code
|
|
69
|
+
// inside them can execute faster.
|
|
70
|
+
function emitNone(handler, isFn, self) {
|
|
71
|
+
if (isFn)
|
|
72
|
+
handler.call(self);
|
|
73
|
+
else {
|
|
74
|
+
var len = handler.length;
|
|
75
|
+
var listeners = arrayClone(handler, len);
|
|
76
|
+
for (var i = 0; i < len; ++i)
|
|
77
|
+
listeners[i].call(self);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
function emitOne(handler, isFn, self, arg1) {
|
|
81
|
+
if (isFn)
|
|
82
|
+
handler.call(self, arg1);
|
|
83
|
+
else {
|
|
84
|
+
var len = handler.length;
|
|
85
|
+
var listeners = arrayClone(handler, len);
|
|
86
|
+
for (var i = 0; i < len; ++i)
|
|
87
|
+
listeners[i].call(self, arg1);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
function emitTwo(handler, isFn, self, arg1, arg2) {
|
|
91
|
+
if (isFn)
|
|
92
|
+
handler.call(self, arg1, arg2);
|
|
93
|
+
else {
|
|
94
|
+
var len = handler.length;
|
|
95
|
+
var listeners = arrayClone(handler, len);
|
|
96
|
+
for (var i = 0; i < len; ++i)
|
|
97
|
+
listeners[i].call(self, arg1, arg2);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
function emitThree(handler, isFn, self, arg1, arg2, arg3) {
|
|
101
|
+
if (isFn)
|
|
102
|
+
handler.call(self, arg1, arg2, arg3);
|
|
103
|
+
else {
|
|
104
|
+
var len = handler.length;
|
|
105
|
+
var listeners = arrayClone(handler, len);
|
|
106
|
+
for (var i = 0; i < len; ++i)
|
|
107
|
+
listeners[i].call(self, arg1, arg2, arg3);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function emitMany(handler, isFn, self, args) {
|
|
112
|
+
if (isFn)
|
|
113
|
+
handler.apply(self, args);
|
|
114
|
+
else {
|
|
115
|
+
var len = handler.length;
|
|
116
|
+
var listeners = arrayClone(handler, len);
|
|
117
|
+
for (var i = 0; i < len; ++i)
|
|
118
|
+
listeners[i].apply(self, args);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
EventEmitter.prototype.emit = function emit(type) {
|
|
123
|
+
var er, handler, len, args, i, events, domain;
|
|
124
|
+
var doError = (type === 'error');
|
|
125
|
+
|
|
126
|
+
events = this._events;
|
|
127
|
+
if (events)
|
|
128
|
+
doError = (doError && events.error == null);
|
|
129
|
+
else if (!doError)
|
|
130
|
+
return false;
|
|
131
|
+
|
|
132
|
+
domain = this.domain;
|
|
133
|
+
|
|
134
|
+
// If there is no 'error' event listener then throw.
|
|
135
|
+
if (doError) {
|
|
136
|
+
er = arguments[1];
|
|
137
|
+
if (domain) {
|
|
138
|
+
if (!er)
|
|
139
|
+
er = new Error('Uncaught, unspecified "error" event');
|
|
140
|
+
er.domainEmitter = this;
|
|
141
|
+
er.domain = domain;
|
|
142
|
+
er.domainThrown = false;
|
|
143
|
+
domain.emit('error', er);
|
|
144
|
+
} else if (er instanceof Error) {
|
|
145
|
+
throw er; // Unhandled 'error' event
|
|
146
|
+
} else {
|
|
147
|
+
// At least give some kind of context to the user
|
|
148
|
+
var err = new Error('Uncaught, unspecified "error" event. (' + er + ')');
|
|
149
|
+
err.context = er;
|
|
150
|
+
throw err;
|
|
151
|
+
}
|
|
152
|
+
return false;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
handler = events[type];
|
|
156
|
+
|
|
157
|
+
if (!handler)
|
|
158
|
+
return false;
|
|
159
|
+
|
|
160
|
+
var isFn = typeof handler === 'function';
|
|
161
|
+
len = arguments.length;
|
|
162
|
+
switch (len) {
|
|
163
|
+
// fast cases
|
|
164
|
+
case 1:
|
|
165
|
+
emitNone(handler, isFn, this);
|
|
166
|
+
break;
|
|
167
|
+
case 2:
|
|
168
|
+
emitOne(handler, isFn, this, arguments[1]);
|
|
169
|
+
break;
|
|
170
|
+
case 3:
|
|
171
|
+
emitTwo(handler, isFn, this, arguments[1], arguments[2]);
|
|
172
|
+
break;
|
|
173
|
+
case 4:
|
|
174
|
+
emitThree(handler, isFn, this, arguments[1], arguments[2], arguments[3]);
|
|
175
|
+
break;
|
|
176
|
+
// slower
|
|
177
|
+
default:
|
|
178
|
+
args = new Array(len - 1);
|
|
179
|
+
for (i = 1; i < len; i++)
|
|
180
|
+
args[i - 1] = arguments[i];
|
|
181
|
+
emitMany(handler, isFn, this, args);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return true;
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
function _addListener(target, type, listener, prepend) {
|
|
188
|
+
var m;
|
|
189
|
+
var events;
|
|
190
|
+
var existing;
|
|
191
|
+
|
|
192
|
+
if (typeof listener !== 'function')
|
|
193
|
+
throw new TypeError('"listener" argument must be a function');
|
|
194
|
+
|
|
195
|
+
events = target._events;
|
|
196
|
+
if (!events) {
|
|
197
|
+
events = target._events = new EventHandlers();
|
|
198
|
+
target._eventsCount = 0;
|
|
199
|
+
} else {
|
|
200
|
+
// To avoid recursion in the case that type === "newListener"! Before
|
|
201
|
+
// adding it to the listeners, first emit "newListener".
|
|
202
|
+
if (events.newListener) {
|
|
203
|
+
target.emit('newListener', type,
|
|
204
|
+
listener.listener ? listener.listener : listener);
|
|
205
|
+
|
|
206
|
+
// Re-assign `events` because a newListener handler could have caused the
|
|
207
|
+
// this._events to be assigned to a new object
|
|
208
|
+
events = target._events;
|
|
209
|
+
}
|
|
210
|
+
existing = events[type];
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if (!existing) {
|
|
214
|
+
// Optimize the case of one listener. Don't need the extra array object.
|
|
215
|
+
existing = events[type] = listener;
|
|
216
|
+
++target._eventsCount;
|
|
217
|
+
} else {
|
|
218
|
+
if (typeof existing === 'function') {
|
|
219
|
+
// Adding the second element, need to change to array.
|
|
220
|
+
existing = events[type] = prepend ? [listener, existing] :
|
|
221
|
+
[existing, listener];
|
|
222
|
+
} else {
|
|
223
|
+
// If we've already got an array, just append.
|
|
224
|
+
if (prepend) {
|
|
225
|
+
existing.unshift(listener);
|
|
226
|
+
} else {
|
|
227
|
+
existing.push(listener);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Check for listener leak
|
|
232
|
+
if (!existing.warned) {
|
|
233
|
+
m = $getMaxListeners(target);
|
|
234
|
+
if (m && m > 0 && existing.length > m) {
|
|
235
|
+
existing.warned = true;
|
|
236
|
+
var w = new Error('Possible EventEmitter memory leak detected. ' +
|
|
237
|
+
existing.length + ' ' + type + ' listeners added. ' +
|
|
238
|
+
'Use emitter.setMaxListeners() to increase limit');
|
|
239
|
+
w.name = 'MaxListenersExceededWarning';
|
|
240
|
+
w.emitter = target;
|
|
241
|
+
w.type = type;
|
|
242
|
+
w.count = existing.length;
|
|
243
|
+
emitWarning(w);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
return target;
|
|
249
|
+
}
|
|
250
|
+
function emitWarning(e) {
|
|
251
|
+
typeof console.warn === 'function' ? console.warn(e) : console.log(e);
|
|
252
|
+
}
|
|
253
|
+
EventEmitter.prototype.addListener = function addListener(type, listener) {
|
|
254
|
+
return _addListener(this, type, listener, false);
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
EventEmitter.prototype.on = EventEmitter.prototype.addListener;
|
|
258
|
+
|
|
259
|
+
EventEmitter.prototype.prependListener =
|
|
260
|
+
function prependListener(type, listener) {
|
|
261
|
+
return _addListener(this, type, listener, true);
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
function _onceWrap(target, type, listener) {
|
|
265
|
+
var fired = false;
|
|
266
|
+
function g() {
|
|
267
|
+
target.removeListener(type, g);
|
|
268
|
+
if (!fired) {
|
|
269
|
+
fired = true;
|
|
270
|
+
listener.apply(target, arguments);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
g.listener = listener;
|
|
274
|
+
return g;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
EventEmitter.prototype.once = function once(type, listener) {
|
|
278
|
+
if (typeof listener !== 'function')
|
|
279
|
+
throw new TypeError('"listener" argument must be a function');
|
|
280
|
+
this.on(type, _onceWrap(this, type, listener));
|
|
281
|
+
return this;
|
|
282
|
+
};
|
|
283
|
+
|
|
284
|
+
EventEmitter.prototype.prependOnceListener =
|
|
285
|
+
function prependOnceListener(type, listener) {
|
|
286
|
+
if (typeof listener !== 'function')
|
|
287
|
+
throw new TypeError('"listener" argument must be a function');
|
|
288
|
+
this.prependListener(type, _onceWrap(this, type, listener));
|
|
289
|
+
return this;
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
// emits a 'removeListener' event iff the listener was removed
|
|
293
|
+
EventEmitter.prototype.removeListener =
|
|
294
|
+
function removeListener(type, listener) {
|
|
295
|
+
var list, events, position, i, originalListener;
|
|
296
|
+
|
|
297
|
+
if (typeof listener !== 'function')
|
|
298
|
+
throw new TypeError('"listener" argument must be a function');
|
|
299
|
+
|
|
300
|
+
events = this._events;
|
|
301
|
+
if (!events)
|
|
302
|
+
return this;
|
|
303
|
+
|
|
304
|
+
list = events[type];
|
|
305
|
+
if (!list)
|
|
306
|
+
return this;
|
|
307
|
+
|
|
308
|
+
if (list === listener || (list.listener && list.listener === listener)) {
|
|
309
|
+
if (--this._eventsCount === 0)
|
|
310
|
+
this._events = new EventHandlers();
|
|
311
|
+
else {
|
|
312
|
+
delete events[type];
|
|
313
|
+
if (events.removeListener)
|
|
314
|
+
this.emit('removeListener', type, list.listener || listener);
|
|
315
|
+
}
|
|
316
|
+
} else if (typeof list !== 'function') {
|
|
317
|
+
position = -1;
|
|
318
|
+
|
|
319
|
+
for (i = list.length; i-- > 0;) {
|
|
320
|
+
if (list[i] === listener ||
|
|
321
|
+
(list[i].listener && list[i].listener === listener)) {
|
|
322
|
+
originalListener = list[i].listener;
|
|
323
|
+
position = i;
|
|
324
|
+
break;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
if (position < 0)
|
|
329
|
+
return this;
|
|
330
|
+
|
|
331
|
+
if (list.length === 1) {
|
|
332
|
+
list[0] = undefined;
|
|
333
|
+
if (--this._eventsCount === 0) {
|
|
334
|
+
this._events = new EventHandlers();
|
|
335
|
+
return this;
|
|
336
|
+
} else {
|
|
337
|
+
delete events[type];
|
|
338
|
+
}
|
|
339
|
+
} else {
|
|
340
|
+
spliceOne(list, position);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
if (events.removeListener)
|
|
344
|
+
this.emit('removeListener', type, originalListener || listener);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
return this;
|
|
348
|
+
};
|
|
349
|
+
|
|
350
|
+
// Alias for removeListener added in NodeJS 10.0
|
|
351
|
+
// https://nodejs.org/api/events.html#events_emitter_off_eventname_listener
|
|
352
|
+
EventEmitter.prototype.off = function(type, listener){
|
|
353
|
+
return this.removeListener(type, listener);
|
|
354
|
+
};
|
|
355
|
+
|
|
356
|
+
EventEmitter.prototype.removeAllListeners =
|
|
357
|
+
function removeAllListeners(type) {
|
|
358
|
+
var listeners, events;
|
|
359
|
+
|
|
360
|
+
events = this._events;
|
|
361
|
+
if (!events)
|
|
362
|
+
return this;
|
|
363
|
+
|
|
364
|
+
// not listening for removeListener, no need to emit
|
|
365
|
+
if (!events.removeListener) {
|
|
366
|
+
if (arguments.length === 0) {
|
|
367
|
+
this._events = new EventHandlers();
|
|
368
|
+
this._eventsCount = 0;
|
|
369
|
+
} else if (events[type]) {
|
|
370
|
+
if (--this._eventsCount === 0)
|
|
371
|
+
this._events = new EventHandlers();
|
|
372
|
+
else
|
|
373
|
+
delete events[type];
|
|
374
|
+
}
|
|
375
|
+
return this;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
// emit removeListener for all listeners on all events
|
|
379
|
+
if (arguments.length === 0) {
|
|
380
|
+
var keys = Object.keys(events);
|
|
381
|
+
for (var i = 0, key; i < keys.length; ++i) {
|
|
382
|
+
key = keys[i];
|
|
383
|
+
if (key === 'removeListener') continue;
|
|
384
|
+
this.removeAllListeners(key);
|
|
385
|
+
}
|
|
386
|
+
this.removeAllListeners('removeListener');
|
|
387
|
+
this._events = new EventHandlers();
|
|
388
|
+
this._eventsCount = 0;
|
|
389
|
+
return this;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
listeners = events[type];
|
|
393
|
+
|
|
394
|
+
if (typeof listeners === 'function') {
|
|
395
|
+
this.removeListener(type, listeners);
|
|
396
|
+
} else if (listeners) {
|
|
397
|
+
// LIFO order
|
|
398
|
+
do {
|
|
399
|
+
this.removeListener(type, listeners[listeners.length - 1]);
|
|
400
|
+
} while (listeners[0]);
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
return this;
|
|
404
|
+
};
|
|
405
|
+
|
|
406
|
+
EventEmitter.prototype.listeners = function listeners(type) {
|
|
407
|
+
var evlistener;
|
|
408
|
+
var ret;
|
|
409
|
+
var events = this._events;
|
|
410
|
+
|
|
411
|
+
if (!events)
|
|
412
|
+
ret = [];
|
|
413
|
+
else {
|
|
414
|
+
evlistener = events[type];
|
|
415
|
+
if (!evlistener)
|
|
416
|
+
ret = [];
|
|
417
|
+
else if (typeof evlistener === 'function')
|
|
418
|
+
ret = [evlistener.listener || evlistener];
|
|
419
|
+
else
|
|
420
|
+
ret = unwrapListeners(evlistener);
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
return ret;
|
|
424
|
+
};
|
|
425
|
+
|
|
426
|
+
EventEmitter.listenerCount = function(emitter, type) {
|
|
427
|
+
if (typeof emitter.listenerCount === 'function') {
|
|
428
|
+
return emitter.listenerCount(type);
|
|
429
|
+
} else {
|
|
430
|
+
return listenerCount.call(emitter, type);
|
|
431
|
+
}
|
|
432
|
+
};
|
|
433
|
+
|
|
434
|
+
EventEmitter.prototype.listenerCount = listenerCount;
|
|
435
|
+
function listenerCount(type) {
|
|
436
|
+
var events = this._events;
|
|
437
|
+
|
|
438
|
+
if (events) {
|
|
439
|
+
var evlistener = events[type];
|
|
440
|
+
|
|
441
|
+
if (typeof evlistener === 'function') {
|
|
442
|
+
return 1;
|
|
443
|
+
} else if (evlistener) {
|
|
444
|
+
return evlistener.length;
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
return 0;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
EventEmitter.prototype.eventNames = function eventNames() {
|
|
452
|
+
return this._eventsCount > 0 ? Reflect.ownKeys(this._events) : [];
|
|
453
|
+
};
|
|
454
|
+
|
|
455
|
+
// About 1.5x faster than the two-arg version of Array#splice().
|
|
456
|
+
function spliceOne(list, index) {
|
|
457
|
+
for (var i = index, k = i + 1, n = list.length; k < n; i += 1, k += 1)
|
|
458
|
+
list[i] = list[k];
|
|
459
|
+
list.pop();
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
function arrayClone(arr, i) {
|
|
463
|
+
var copy = new Array(i);
|
|
464
|
+
while (i--)
|
|
465
|
+
copy[i] = arr[i];
|
|
466
|
+
return copy;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
function unwrapListeners(arr) {
|
|
470
|
+
var ret = new Array(arr.length);
|
|
471
|
+
for (var i = 0; i < ret.length; ++i) {
|
|
472
|
+
ret[i] = arr[i].listener || arr[i];
|
|
473
|
+
}
|
|
474
|
+
return ret;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
// Unique ID creation requires a high quality random # generator. In the browser we therefore
|
|
478
|
+
// require the crypto API and do not support built-in fallback to lower quality random number
|
|
479
|
+
// generators (like Math.random()).
|
|
480
|
+
var getRandomValues;
|
|
481
|
+
var rnds8 = new Uint8Array(16);
|
|
482
|
+
function rng() {
|
|
483
|
+
// lazy load so that environments that need to polyfill have a chance to do so
|
|
484
|
+
if (!getRandomValues) {
|
|
485
|
+
// getRandomValues needs to be invoked in a context where "this" is a Crypto implementation. Also,
|
|
486
|
+
// find the complete implementation of crypto (msCrypto) on IE11.
|
|
487
|
+
getRandomValues = typeof crypto !== 'undefined' && crypto.getRandomValues && crypto.getRandomValues.bind(crypto) || typeof msCrypto !== 'undefined' && typeof msCrypto.getRandomValues === 'function' && msCrypto.getRandomValues.bind(msCrypto);
|
|
488
|
+
|
|
489
|
+
if (!getRandomValues) {
|
|
490
|
+
throw new Error('crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported');
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
return getRandomValues(rnds8);
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
var REGEX = /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i;
|
|
498
|
+
|
|
499
|
+
function validate(uuid) {
|
|
500
|
+
return typeof uuid === 'string' && REGEX.test(uuid);
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
/**
|
|
504
|
+
* Convert array of 16 byte values to UUID string format of the form:
|
|
505
|
+
* XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
|
|
506
|
+
*/
|
|
507
|
+
|
|
508
|
+
var byteToHex = [];
|
|
509
|
+
|
|
510
|
+
for (var i = 0; i < 256; ++i) {
|
|
511
|
+
byteToHex.push((i + 0x100).toString(16).substr(1));
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
function stringify(arr) {
|
|
515
|
+
var offset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
|
|
516
|
+
// Note: Be careful editing this code! It's been tuned for performance
|
|
517
|
+
// and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434
|
|
518
|
+
var uuid = (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase(); // Consistency check for valid UUID. If this throws, it's likely due to one
|
|
519
|
+
// of the following:
|
|
520
|
+
// - One or more input array values don't map to a hex octet (leading to
|
|
521
|
+
// "undefined" in the uuid)
|
|
522
|
+
// - Invalid input values for the RFC `version` or `variant` fields
|
|
523
|
+
|
|
524
|
+
if (!validate(uuid)) {
|
|
525
|
+
throw TypeError('Stringified UUID is invalid');
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
return uuid;
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
function v4(options, buf, offset) {
|
|
532
|
+
options = options || {};
|
|
533
|
+
var rnds = options.random || (options.rng || rng)(); // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
|
|
534
|
+
|
|
535
|
+
rnds[6] = rnds[6] & 0x0f | 0x40;
|
|
536
|
+
rnds[8] = rnds[8] & 0x3f | 0x80; // Copy bytes to buffer, if provided
|
|
537
|
+
|
|
538
|
+
if (buf) {
|
|
539
|
+
offset = offset || 0;
|
|
540
|
+
|
|
541
|
+
for (var i = 0; i < 16; ++i) {
|
|
542
|
+
buf[offset + i] = rnds[i];
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
return buf;
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
return stringify(rnds);
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
class StorageUtilityBrowser extends StorageUtility {
|
|
552
|
+
constructor(secureStorage, insecureStorage) {
|
|
553
|
+
super(secureStorage, insecureStorage);
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
function processErrorResponse(responseBody, options) {
|
|
558
|
+
var _a, _b, _c, _d;
|
|
559
|
+
if (responseBody.error === "invalid_redirect_uri") {
|
|
560
|
+
throw new Error(`Dynamic client registration failed: the provided redirect uri [${(_a = options.redirectUrl) === null || _a === void 0 ? void 0 : _a.toString()}] is invalid - ${(_b = responseBody.error_description) !== null && _b !== void 0 ? _b : ""}`);
|
|
561
|
+
}
|
|
562
|
+
if (responseBody.error === "invalid_client_metadata") {
|
|
563
|
+
throw new Error(`Dynamic client registration failed: the provided client metadata ${JSON.stringify(options)} is invalid - ${(_c = responseBody.error_description) !== null && _c !== void 0 ? _c : ""}`);
|
|
564
|
+
}
|
|
565
|
+
throw new Error(`Dynamic client registration failed: ${responseBody.error} - ${(_d = responseBody.error_description) !== null && _d !== void 0 ? _d : ""}`);
|
|
566
|
+
}
|
|
567
|
+
function validateRegistrationResponse(responseBody, options) {
|
|
568
|
+
if (responseBody.client_id === undefined) {
|
|
569
|
+
throw new Error(`Dynamic client registration failed: no client_id has been found on ${JSON.stringify(responseBody)}`);
|
|
570
|
+
}
|
|
571
|
+
if (options.redirectUrl &&
|
|
572
|
+
(responseBody.redirect_uris === undefined ||
|
|
573
|
+
responseBody.redirect_uris[0] !== options.redirectUrl.toString())) {
|
|
574
|
+
throw new Error(`Dynamic client registration failed: the returned redirect URIs ${JSON.stringify(responseBody.redirect_uris)} don't match the provided ${JSON.stringify([
|
|
575
|
+
options.redirectUrl.toString(),
|
|
576
|
+
])}`);
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
async function registerClient(options, issuerConfig) {
|
|
580
|
+
var _a;
|
|
581
|
+
if (!issuerConfig.registrationEndpoint) {
|
|
582
|
+
throw new Error("Dynamic Registration could not be completed because the issuer has no registration endpoint.");
|
|
583
|
+
}
|
|
584
|
+
if (!Array.isArray(issuerConfig.idTokenSigningAlgValuesSupported)) {
|
|
585
|
+
throw new Error("The OIDC issuer discovery profile is missing the 'id_token_signing_alg_values_supported' value, which is mandatory.");
|
|
586
|
+
}
|
|
587
|
+
const signingAlg = determineSigningAlg(issuerConfig.idTokenSigningAlgValuesSupported, PREFERRED_SIGNING_ALG);
|
|
588
|
+
const config = {
|
|
589
|
+
client_name: options.clientName,
|
|
590
|
+
application_type: "web",
|
|
591
|
+
redirect_uris: [(_a = options.redirectUrl) === null || _a === void 0 ? void 0 : _a.toString()],
|
|
592
|
+
subject_type: "public",
|
|
593
|
+
token_endpoint_auth_method: "client_secret_basic",
|
|
594
|
+
id_token_signed_response_alg: signingAlg,
|
|
595
|
+
grant_types: ["authorization_code", "refresh_token"],
|
|
596
|
+
};
|
|
597
|
+
const headers = {
|
|
598
|
+
"Content-Type": "application/json",
|
|
599
|
+
};
|
|
600
|
+
if (options.registrationAccessToken) {
|
|
601
|
+
headers.Authorization = `Bearer ${options.registrationAccessToken}`;
|
|
602
|
+
}
|
|
603
|
+
const registerResponse = await fetch(issuerConfig.registrationEndpoint.toString(), {
|
|
604
|
+
method: "POST",
|
|
605
|
+
headers,
|
|
606
|
+
body: JSON.stringify(config),
|
|
607
|
+
});
|
|
608
|
+
if (registerResponse.ok) {
|
|
609
|
+
const responseBody = await registerResponse.json();
|
|
610
|
+
validateRegistrationResponse(responseBody, options);
|
|
611
|
+
return {
|
|
612
|
+
clientId: responseBody.client_id,
|
|
613
|
+
clientSecret: responseBody.client_secret,
|
|
614
|
+
idTokenSignedResponseAlg: responseBody.id_token_signed_response_alg,
|
|
615
|
+
clientType: "dynamic",
|
|
616
|
+
};
|
|
617
|
+
}
|
|
618
|
+
if (registerResponse.status === 400) {
|
|
619
|
+
processErrorResponse(await registerResponse.json(), options);
|
|
620
|
+
}
|
|
621
|
+
throw new Error(`Dynamic client registration failed: the server returned ${registerResponse.status} ${registerResponse.statusText} - ${await registerResponse.text()}`);
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
function hasError(value) {
|
|
625
|
+
return value.error !== undefined && typeof value.error === "string";
|
|
626
|
+
}
|
|
627
|
+
function hasErrorDescription(value) {
|
|
628
|
+
return (value.error_description !== undefined &&
|
|
629
|
+
typeof value.error_description === "string");
|
|
630
|
+
}
|
|
631
|
+
function hasErrorUri(value) {
|
|
632
|
+
return value.error_uri !== undefined && typeof value.error_uri === "string";
|
|
633
|
+
}
|
|
634
|
+
function hasAccessToken(value) {
|
|
635
|
+
return (value.access_token !== undefined && typeof value.access_token === "string");
|
|
636
|
+
}
|
|
637
|
+
function hasIdToken(value) {
|
|
638
|
+
return value.id_token !== undefined && typeof value.id_token === "string";
|
|
639
|
+
}
|
|
640
|
+
function hasRefreshToken(value) {
|
|
641
|
+
return (value.refresh_token !== undefined && typeof value.refresh_token === "string");
|
|
642
|
+
}
|
|
643
|
+
function hasTokenType(value) {
|
|
644
|
+
return value.token_type !== undefined && typeof value.token_type === "string";
|
|
645
|
+
}
|
|
646
|
+
function hasExpiresIn(value) {
|
|
647
|
+
return value.expires_in === undefined || typeof value.expires_in === "number";
|
|
648
|
+
}
|
|
649
|
+
function validatePreconditions(issuer, data) {
|
|
650
|
+
if (data.grantType &&
|
|
651
|
+
(!issuer.grantTypesSupported ||
|
|
652
|
+
!issuer.grantTypesSupported.includes(data.grantType))) {
|
|
653
|
+
throw new Error(`The issuer [${issuer.issuer}] does not support the [${data.grantType}] grant`);
|
|
654
|
+
}
|
|
655
|
+
if (!issuer.tokenEndpoint) {
|
|
656
|
+
throw new Error(`This issuer [${issuer.issuer}] does not have a token endpoint`);
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
function validateTokenEndpointResponse(tokenResponse, dpop) {
|
|
660
|
+
if (hasError(tokenResponse)) {
|
|
661
|
+
throw new OidcProviderError(`Token endpoint returned error [${tokenResponse.error}]${hasErrorDescription(tokenResponse)
|
|
662
|
+
? `: ${tokenResponse.error_description}`
|
|
663
|
+
: ""}${hasErrorUri(tokenResponse) ? ` (see ${tokenResponse.error_uri})` : ""}`, tokenResponse.error, hasErrorDescription(tokenResponse)
|
|
664
|
+
? tokenResponse.error_description
|
|
665
|
+
: undefined);
|
|
666
|
+
}
|
|
667
|
+
if (!hasAccessToken(tokenResponse)) {
|
|
668
|
+
throw new InvalidResponseError(["access_token"]);
|
|
669
|
+
}
|
|
670
|
+
if (!hasIdToken(tokenResponse)) {
|
|
671
|
+
throw new InvalidResponseError(["id_token"]);
|
|
672
|
+
}
|
|
673
|
+
if (!hasTokenType(tokenResponse)) {
|
|
674
|
+
throw new InvalidResponseError(["token_type"]);
|
|
675
|
+
}
|
|
676
|
+
if (!hasExpiresIn(tokenResponse)) {
|
|
677
|
+
throw new InvalidResponseError(["expires_in"]);
|
|
678
|
+
}
|
|
679
|
+
if (!dpop && tokenResponse.token_type.toLowerCase() !== "bearer") {
|
|
680
|
+
throw new Error(`Invalid token endpoint response: requested a [Bearer] token, but got a 'token_type' value of [${tokenResponse.token_type}].`);
|
|
681
|
+
}
|
|
682
|
+
return tokenResponse;
|
|
683
|
+
}
|
|
684
|
+
async function getTokens(issuer, client, data, dpop) {
|
|
685
|
+
validatePreconditions(issuer, data);
|
|
686
|
+
const headers = {
|
|
687
|
+
"content-type": "application/x-www-form-urlencoded",
|
|
688
|
+
};
|
|
689
|
+
let dpopKey;
|
|
690
|
+
if (dpop) {
|
|
691
|
+
dpopKey = await generateDpopKeyPair();
|
|
692
|
+
headers.DPoP = await createDpopHeader(issuer.tokenEndpoint, "POST", dpopKey);
|
|
693
|
+
}
|
|
694
|
+
if (client.clientSecret) {
|
|
695
|
+
headers.Authorization = `Basic ${btoa(`${client.clientId}:${client.clientSecret}`)}`;
|
|
696
|
+
}
|
|
697
|
+
const requestBody = {
|
|
698
|
+
grant_type: data.grantType,
|
|
699
|
+
redirect_uri: data.redirectUrl,
|
|
700
|
+
code: data.code,
|
|
701
|
+
code_verifier: data.codeVerifier,
|
|
702
|
+
client_id: client.clientId,
|
|
703
|
+
};
|
|
704
|
+
const tokenRequestInit = {
|
|
705
|
+
method: "POST",
|
|
706
|
+
headers,
|
|
707
|
+
body: new URLSearchParams(requestBody).toString(),
|
|
708
|
+
};
|
|
709
|
+
const rawTokenResponse = await await fetch(issuer.tokenEndpoint, tokenRequestInit);
|
|
710
|
+
const jsonTokenResponse = (await rawTokenResponse.json());
|
|
711
|
+
const tokenResponse = validateTokenEndpointResponse(jsonTokenResponse, dpop);
|
|
712
|
+
const webId = await getWebidFromTokenPayload(tokenResponse.id_token, issuer.jwksUri, issuer.issuer, client.clientId);
|
|
713
|
+
return {
|
|
714
|
+
accessToken: tokenResponse.access_token,
|
|
715
|
+
idToken: tokenResponse.id_token,
|
|
716
|
+
refreshToken: hasRefreshToken(tokenResponse)
|
|
717
|
+
? tokenResponse.refresh_token
|
|
718
|
+
: undefined,
|
|
719
|
+
webId,
|
|
720
|
+
dpopKey,
|
|
721
|
+
expiresIn: tokenResponse.expires_in,
|
|
722
|
+
};
|
|
723
|
+
}
|
|
724
|
+
async function getBearerToken(redirectUrl) {
|
|
725
|
+
let signinResponse;
|
|
726
|
+
try {
|
|
727
|
+
const client = new OidcClient({
|
|
728
|
+
response_mode: "query",
|
|
729
|
+
loadUserInfo: false,
|
|
730
|
+
});
|
|
731
|
+
signinResponse = await client.processSigninResponse(redirectUrl);
|
|
732
|
+
if (client.settings.metadata === undefined) {
|
|
733
|
+
throw new Error("Cannot retrieve issuer metadata from client information in storage.");
|
|
734
|
+
}
|
|
735
|
+
if (client.settings.metadata.jwks_uri === undefined) {
|
|
736
|
+
throw new Error("Missing some issuer metadata from client information in storage: 'jwks_uri' is undefined");
|
|
737
|
+
}
|
|
738
|
+
if (client.settings.metadata.issuer === undefined) {
|
|
739
|
+
throw new Error("Missing some issuer metadata from client information in storage: 'issuer' is undefined");
|
|
740
|
+
}
|
|
741
|
+
if (client.settings.client_id === undefined) {
|
|
742
|
+
throw new Error("Missing some client information in storage: 'client_id' is undefined");
|
|
743
|
+
}
|
|
744
|
+
const webId = await getWebidFromTokenPayload(signinResponse.id_token, client.settings.metadata.jwks_uri, client.settings.metadata.issuer, client.settings.client_id);
|
|
745
|
+
return {
|
|
746
|
+
accessToken: signinResponse.access_token,
|
|
747
|
+
idToken: signinResponse.id_token,
|
|
748
|
+
webId,
|
|
749
|
+
refreshToken: signinResponse.refresh_token,
|
|
750
|
+
};
|
|
751
|
+
}
|
|
752
|
+
catch (err) {
|
|
753
|
+
throw new Error(`Problem handling Auth Code Grant (Flow) redirect - URL [${redirectUrl}]: ${err}`);
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
async function getDpopToken(issuer, client, data) {
|
|
757
|
+
return getTokens(issuer, client, data, true);
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
async function refresh(refreshToken, issuer, client, dpopKey) {
|
|
761
|
+
const requestBody = {
|
|
762
|
+
grant_type: "refresh_token",
|
|
763
|
+
refresh_token: refreshToken,
|
|
764
|
+
scope: "openid offline_access",
|
|
765
|
+
};
|
|
766
|
+
let dpopHeader = {};
|
|
767
|
+
if (dpopKey !== undefined) {
|
|
768
|
+
dpopHeader = {
|
|
769
|
+
DPoP: await createDpopHeader(issuer.tokenEndpoint, "POST", dpopKey),
|
|
770
|
+
};
|
|
771
|
+
}
|
|
772
|
+
let authHeader = {};
|
|
773
|
+
if (client.clientSecret !== undefined) {
|
|
774
|
+
authHeader = {
|
|
775
|
+
Authorization: `Basic ${btoa(`${client.clientId}:${client.clientSecret}`)}`,
|
|
776
|
+
};
|
|
777
|
+
}
|
|
778
|
+
const rawResponse = await fetch(issuer.tokenEndpoint, {
|
|
779
|
+
method: "POST",
|
|
780
|
+
body: new URLSearchParams(requestBody).toString(),
|
|
781
|
+
headers: {
|
|
782
|
+
...dpopHeader,
|
|
783
|
+
...authHeader,
|
|
784
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
785
|
+
},
|
|
786
|
+
});
|
|
787
|
+
let response;
|
|
788
|
+
try {
|
|
789
|
+
response = await rawResponse.json();
|
|
790
|
+
}
|
|
791
|
+
catch (e) {
|
|
792
|
+
throw new Error(`The token endpoint of issuer ${issuer.issuer} returned a malformed response.`);
|
|
793
|
+
}
|
|
794
|
+
const validatedResponse = validateTokenEndpointResponse(response, dpopKey !== undefined);
|
|
795
|
+
const webId = await getWebidFromTokenPayload(validatedResponse.id_token, issuer.jwksUri, issuer.issuer, client.clientId);
|
|
796
|
+
return {
|
|
797
|
+
accessToken: validatedResponse.access_token,
|
|
798
|
+
idToken: validatedResponse.id_token,
|
|
799
|
+
refreshToken: typeof validatedResponse.refresh_token === "string"
|
|
800
|
+
? validatedResponse.refresh_token
|
|
801
|
+
: undefined,
|
|
802
|
+
webId,
|
|
803
|
+
dpopKey,
|
|
804
|
+
expiresIn: validatedResponse.expires_in,
|
|
805
|
+
};
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
function removeOidcQueryParam(redirectUrl) {
|
|
809
|
+
const cleanedUrl = new URL(redirectUrl);
|
|
810
|
+
cleanedUrl.searchParams.delete("code");
|
|
811
|
+
cleanedUrl.searchParams.delete("state");
|
|
812
|
+
cleanedUrl.hash = "";
|
|
813
|
+
return cleanedUrl.toString();
|
|
814
|
+
}
|
|
815
|
+
async function clearOidcPersistentStorage() {
|
|
816
|
+
const client = new OidcClient({
|
|
817
|
+
response_mode: "query",
|
|
818
|
+
});
|
|
819
|
+
await client.clearStaleState(new WebStorageStateStore({}));
|
|
820
|
+
const myStorage = window.localStorage;
|
|
821
|
+
const itemsToRemove = [];
|
|
822
|
+
for (let i = 0; i <= myStorage.length; i += 1) {
|
|
823
|
+
const key = myStorage.key(i);
|
|
824
|
+
if (key &&
|
|
825
|
+
(key.match(/^oidc\..+$/) ||
|
|
826
|
+
key.match(/^solidClientAuthenticationUser:.+$/))) {
|
|
827
|
+
itemsToRemove.push(key);
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
itemsToRemove.forEach((key) => myStorage.removeItem(key));
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
const globalFetch = (request, init) => window.fetch(request, init);
|
|
834
|
+
class ClientAuthentication {
|
|
835
|
+
constructor(loginHandler, redirectHandler, logoutHandler, sessionInfoManager, issuerConfigFetcher) {
|
|
836
|
+
this.loginHandler = loginHandler;
|
|
837
|
+
this.redirectHandler = redirectHandler;
|
|
838
|
+
this.logoutHandler = logoutHandler;
|
|
839
|
+
this.sessionInfoManager = sessionInfoManager;
|
|
840
|
+
this.issuerConfigFetcher = issuerConfigFetcher;
|
|
841
|
+
this.login = async (options, eventEmitter) => {
|
|
842
|
+
var _a, _b;
|
|
843
|
+
await this.sessionInfoManager.clear(options.sessionId);
|
|
844
|
+
const redirectUrl = removeOidcQueryParam((_a = options.redirectUrl) !== null && _a !== void 0 ? _a : window.location.href);
|
|
845
|
+
await this.loginHandler.handle({
|
|
846
|
+
...options,
|
|
847
|
+
redirectUrl,
|
|
848
|
+
clientName: (_b = options.clientName) !== null && _b !== void 0 ? _b : options.clientId,
|
|
849
|
+
eventEmitter,
|
|
850
|
+
});
|
|
851
|
+
};
|
|
852
|
+
this.fetch = globalFetch;
|
|
853
|
+
this.logout = async (sessionId) => {
|
|
854
|
+
await this.logoutHandler.handle(sessionId);
|
|
855
|
+
this.fetch = globalFetch;
|
|
856
|
+
};
|
|
857
|
+
this.getSessionInfo = async (sessionId) => {
|
|
858
|
+
return this.sessionInfoManager.get(sessionId);
|
|
859
|
+
};
|
|
860
|
+
this.getAllSessionInfo = async () => {
|
|
861
|
+
return this.sessionInfoManager.getAll();
|
|
862
|
+
};
|
|
863
|
+
this.validateCurrentSession = async (currentSessionId) => {
|
|
864
|
+
const sessionInfo = await this.sessionInfoManager.get(currentSessionId);
|
|
865
|
+
if (sessionInfo === undefined ||
|
|
866
|
+
sessionInfo.clientAppId === undefined ||
|
|
867
|
+
sessionInfo.issuer === undefined) {
|
|
868
|
+
return null;
|
|
869
|
+
}
|
|
870
|
+
return sessionInfo;
|
|
871
|
+
};
|
|
872
|
+
this.handleIncomingRedirect = async (url, eventEmitter) => {
|
|
873
|
+
try {
|
|
874
|
+
const redirectInfo = await this.redirectHandler.handle(url, eventEmitter);
|
|
875
|
+
this.fetch = redirectInfo.fetch.bind(window);
|
|
876
|
+
this.cleanUrlAfterRedirect(url);
|
|
877
|
+
return {
|
|
878
|
+
isLoggedIn: redirectInfo.isLoggedIn,
|
|
879
|
+
webId: redirectInfo.webId,
|
|
880
|
+
sessionId: redirectInfo.sessionId,
|
|
881
|
+
expirationDate: redirectInfo.expirationDate,
|
|
882
|
+
};
|
|
883
|
+
}
|
|
884
|
+
catch (err) {
|
|
885
|
+
this.cleanUrlAfterRedirect(url);
|
|
886
|
+
eventEmitter.emit(EVENTS.ERROR, "redirect", err);
|
|
887
|
+
}
|
|
888
|
+
};
|
|
889
|
+
}
|
|
890
|
+
cleanUrlAfterRedirect(url) {
|
|
891
|
+
const cleanedUpUrl = new URL(url);
|
|
892
|
+
cleanedUpUrl.searchParams.delete("state");
|
|
893
|
+
cleanedUpUrl.searchParams.delete("code");
|
|
894
|
+
cleanedUpUrl.searchParams.delete("id_token");
|
|
895
|
+
cleanedUpUrl.searchParams.delete("access_token");
|
|
896
|
+
cleanedUpUrl.searchParams.delete("error");
|
|
897
|
+
cleanedUpUrl.searchParams.delete("error_description");
|
|
898
|
+
window.history.replaceState(null, "", cleanedUpUrl.toString());
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
function hasIssuer(options) {
|
|
903
|
+
return typeof options.oidcIssuer === "string";
|
|
904
|
+
}
|
|
905
|
+
function hasRedirectUrl(options) {
|
|
906
|
+
return typeof options.redirectUrl === "string";
|
|
907
|
+
}
|
|
908
|
+
class OidcLoginHandler {
|
|
909
|
+
constructor(storageUtility, oidcHandler, issuerConfigFetcher, clientRegistrar) {
|
|
910
|
+
this.storageUtility = storageUtility;
|
|
911
|
+
this.oidcHandler = oidcHandler;
|
|
912
|
+
this.issuerConfigFetcher = issuerConfigFetcher;
|
|
913
|
+
this.clientRegistrar = clientRegistrar;
|
|
914
|
+
}
|
|
915
|
+
async canHandle(options) {
|
|
916
|
+
return hasIssuer(options) && hasRedirectUrl(options);
|
|
917
|
+
}
|
|
918
|
+
async handle(options) {
|
|
919
|
+
if (!hasIssuer(options)) {
|
|
920
|
+
throw new ConfigurationError(`OidcLoginHandler requires an OIDC issuer: missing property 'oidcIssuer' in ${JSON.stringify(options)}`);
|
|
921
|
+
}
|
|
922
|
+
if (!hasRedirectUrl(options)) {
|
|
923
|
+
throw new ConfigurationError(`OidcLoginHandler requires a redirect URL: missing property 'redirectUrl' in ${JSON.stringify(options)}`);
|
|
924
|
+
}
|
|
925
|
+
const issuerConfig = await this.issuerConfigFetcher.fetchConfig(options.oidcIssuer);
|
|
926
|
+
const clientRegistration = await handleRegistration(options, issuerConfig, this.storageUtility, this.clientRegistrar);
|
|
927
|
+
const OidcOptions = {
|
|
928
|
+
issuer: issuerConfig.issuer,
|
|
929
|
+
dpop: options.tokenType.toLowerCase() === "dpop",
|
|
930
|
+
...options,
|
|
931
|
+
issuerConfiguration: issuerConfig,
|
|
932
|
+
client: clientRegistration,
|
|
933
|
+
};
|
|
934
|
+
return this.oidcHandler.handle(OidcOptions);
|
|
935
|
+
}
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
class AuthorizationCodeWithPkceOidcHandler {
|
|
939
|
+
constructor(storageUtility, redirector) {
|
|
940
|
+
this.storageUtility = storageUtility;
|
|
941
|
+
this.redirector = redirector;
|
|
942
|
+
}
|
|
943
|
+
async canHandle(oidcLoginOptions) {
|
|
944
|
+
return !!(oidcLoginOptions.issuerConfiguration.grantTypesSupported &&
|
|
945
|
+
oidcLoginOptions.issuerConfiguration.grantTypesSupported.indexOf("authorization_code") > -1);
|
|
946
|
+
}
|
|
947
|
+
async handle(oidcLoginOptions) {
|
|
948
|
+
var _a;
|
|
949
|
+
const oidcOptions = {
|
|
950
|
+
authority: oidcLoginOptions.issuer.toString(),
|
|
951
|
+
client_id: oidcLoginOptions.client.clientId,
|
|
952
|
+
client_secret: oidcLoginOptions.client.clientSecret,
|
|
953
|
+
redirect_uri: oidcLoginOptions.redirectUrl.toString(),
|
|
954
|
+
post_logout_redirect_uri: oidcLoginOptions.redirectUrl.toString(),
|
|
955
|
+
response_type: "code",
|
|
956
|
+
scope: "openid offline_access webid",
|
|
957
|
+
filterProtocolClaims: true,
|
|
958
|
+
loadUserInfo: false,
|
|
959
|
+
code_verifier: true,
|
|
960
|
+
prompt: (_a = oidcLoginOptions.prompt) !== null && _a !== void 0 ? _a : "consent",
|
|
961
|
+
};
|
|
962
|
+
const oidcClientLibrary = new OidcClient(oidcOptions);
|
|
963
|
+
const { redirector } = this;
|
|
964
|
+
const storage = this.storageUtility;
|
|
965
|
+
try {
|
|
966
|
+
const signingRequest = await oidcClientLibrary.createSigninRequest();
|
|
967
|
+
await Promise.all([
|
|
968
|
+
storage.setForUser(signingRequest.state._id, {
|
|
969
|
+
sessionId: oidcLoginOptions.sessionId,
|
|
970
|
+
}),
|
|
971
|
+
storage.setForUser(oidcLoginOptions.sessionId, {
|
|
972
|
+
codeVerifier: signingRequest.state._code_verifier,
|
|
973
|
+
issuer: oidcLoginOptions.issuer.toString(),
|
|
974
|
+
redirectUrl: oidcLoginOptions.redirectUrl,
|
|
975
|
+
dpop: oidcLoginOptions.dpop ? "true" : "false",
|
|
976
|
+
}),
|
|
977
|
+
]);
|
|
978
|
+
redirector.redirect(signingRequest.url.toString(), {
|
|
979
|
+
handleRedirect: oidcLoginOptions.handleRedirect,
|
|
980
|
+
redirectInIframe: oidcLoginOptions.inIframe,
|
|
981
|
+
});
|
|
982
|
+
}
|
|
983
|
+
catch (err) {
|
|
984
|
+
console.error(err);
|
|
985
|
+
}
|
|
986
|
+
return undefined;
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
function appendToUrlPathname(url, append) {
|
|
991
|
+
const parsedUrl = new URL(url);
|
|
992
|
+
const path = parsedUrl.pathname;
|
|
993
|
+
parsedUrl.pathname = `${path}${path.endsWith("/") ? "" : "/"}${append.startsWith("/") ? append.substring(1) : append}`;
|
|
994
|
+
return parsedUrl.toString();
|
|
995
|
+
}
|
|
996
|
+
|
|
997
|
+
const WELL_KNOWN_OPENID_CONFIG = ".well-known/openid-configuration";
|
|
998
|
+
const issuerConfigKeyMap = {
|
|
999
|
+
issuer: {
|
|
1000
|
+
toKey: "issuer",
|
|
1001
|
+
convertToUrl: true,
|
|
1002
|
+
},
|
|
1003
|
+
authorization_endpoint: {
|
|
1004
|
+
toKey: "authorizationEndpoint",
|
|
1005
|
+
convertToUrl: true,
|
|
1006
|
+
},
|
|
1007
|
+
token_endpoint: {
|
|
1008
|
+
toKey: "tokenEndpoint",
|
|
1009
|
+
convertToUrl: true,
|
|
1010
|
+
},
|
|
1011
|
+
userinfo_endpoint: {
|
|
1012
|
+
toKey: "userinfoEndpoint",
|
|
1013
|
+
convertToUrl: true,
|
|
1014
|
+
},
|
|
1015
|
+
jwks_uri: {
|
|
1016
|
+
toKey: "jwksUri",
|
|
1017
|
+
convertToUrl: true,
|
|
1018
|
+
},
|
|
1019
|
+
registration_endpoint: {
|
|
1020
|
+
toKey: "registrationEndpoint",
|
|
1021
|
+
convertToUrl: true,
|
|
1022
|
+
},
|
|
1023
|
+
scopes_supported: { toKey: "scopesSupported" },
|
|
1024
|
+
response_types_supported: { toKey: "responseTypesSupported" },
|
|
1025
|
+
response_modes_supported: { toKey: "responseModesSupported" },
|
|
1026
|
+
grant_types_supported: { toKey: "grantTypesSupported" },
|
|
1027
|
+
acr_values_supported: { toKey: "acrValuesSupported" },
|
|
1028
|
+
subject_types_supported: { toKey: "subjectTypesSupported" },
|
|
1029
|
+
id_token_signing_alg_values_supported: {
|
|
1030
|
+
toKey: "idTokenSigningAlgValuesSupported",
|
|
1031
|
+
},
|
|
1032
|
+
id_token_encryption_alg_values_supported: {
|
|
1033
|
+
toKey: "idTokenEncryptionAlgValuesSupported",
|
|
1034
|
+
},
|
|
1035
|
+
id_token_encryption_enc_values_supported: {
|
|
1036
|
+
toKey: "idTokenEncryptionEncValuesSupported",
|
|
1037
|
+
},
|
|
1038
|
+
userinfo_signing_alg_values_supported: {
|
|
1039
|
+
toKey: "userinfoSigningAlgValuesSupported",
|
|
1040
|
+
},
|
|
1041
|
+
userinfo_encryption_alg_values_supported: {
|
|
1042
|
+
toKey: "userinfoEncryptionAlgValuesSupported",
|
|
1043
|
+
},
|
|
1044
|
+
userinfo_encryption_enc_values_supported: {
|
|
1045
|
+
toKey: "userinfoEncryptionEncValuesSupported",
|
|
1046
|
+
},
|
|
1047
|
+
request_object_signing_alg_values_supported: {
|
|
1048
|
+
toKey: "requestObjectSigningAlgValuesSupported",
|
|
1049
|
+
},
|
|
1050
|
+
request_object_encryption_alg_values_supported: {
|
|
1051
|
+
toKey: "requestObjectEncryptionAlgValuesSupported",
|
|
1052
|
+
},
|
|
1053
|
+
request_object_encryption_enc_values_supported: {
|
|
1054
|
+
toKey: "requestObjectEncryptionEncValuesSupported",
|
|
1055
|
+
},
|
|
1056
|
+
token_endpoint_auth_methods_supported: {
|
|
1057
|
+
toKey: "tokenEndpointAuthMethodsSupported",
|
|
1058
|
+
},
|
|
1059
|
+
token_endpoint_auth_signing_alg_values_supported: {
|
|
1060
|
+
toKey: "tokenEndpointAuthSigningAlgValuesSupported",
|
|
1061
|
+
},
|
|
1062
|
+
display_values_supported: { toKey: "displayValuesSupported" },
|
|
1063
|
+
claim_types_supported: { toKey: "claimTypesSupported" },
|
|
1064
|
+
claims_supported: { toKey: "claimsSupported" },
|
|
1065
|
+
service_documentation: { toKey: "serviceDocumentation" },
|
|
1066
|
+
claims_locales_supported: { toKey: "claimsLocalesSupported" },
|
|
1067
|
+
ui_locales_supported: { toKey: "uiLocalesSupported" },
|
|
1068
|
+
claims_parameter_supported: { toKey: "claimsParameterSupported" },
|
|
1069
|
+
request_parameter_supported: { toKey: "requestParameterSupported" },
|
|
1070
|
+
request_uri_parameter_supported: { toKey: "requestUriParameterSupported" },
|
|
1071
|
+
require_request_uri_registration: { toKey: "requireRequestUriRegistration" },
|
|
1072
|
+
op_policy_uri: {
|
|
1073
|
+
toKey: "opPolicyUri",
|
|
1074
|
+
convertToUrl: true,
|
|
1075
|
+
},
|
|
1076
|
+
op_tos_uri: {
|
|
1077
|
+
toKey: "opTosUri",
|
|
1078
|
+
convertToUrl: true,
|
|
1079
|
+
},
|
|
1080
|
+
};
|
|
1081
|
+
function processConfig(config) {
|
|
1082
|
+
const parsedConfig = {};
|
|
1083
|
+
Object.keys(config).forEach((key) => {
|
|
1084
|
+
if (issuerConfigKeyMap[key]) {
|
|
1085
|
+
parsedConfig[issuerConfigKeyMap[key].toKey] = config[key];
|
|
1086
|
+
}
|
|
1087
|
+
});
|
|
1088
|
+
if (!Array.isArray(parsedConfig.scopesSupported)) {
|
|
1089
|
+
parsedConfig.scopesSupported = ["openid"];
|
|
1090
|
+
}
|
|
1091
|
+
return parsedConfig;
|
|
1092
|
+
}
|
|
1093
|
+
class IssuerConfigFetcher {
|
|
1094
|
+
constructor(storageUtility) {
|
|
1095
|
+
this.storageUtility = storageUtility;
|
|
1096
|
+
}
|
|
1097
|
+
static getLocalStorageKey(issuer) {
|
|
1098
|
+
return `issuerConfig:${issuer}`;
|
|
1099
|
+
}
|
|
1100
|
+
async fetchConfig(issuer) {
|
|
1101
|
+
let issuerConfig;
|
|
1102
|
+
const openIdConfigUrl = appendToUrlPathname(issuer, WELL_KNOWN_OPENID_CONFIG);
|
|
1103
|
+
const issuerConfigRequestBody = await window.fetch(openIdConfigUrl);
|
|
1104
|
+
try {
|
|
1105
|
+
issuerConfig = processConfig(await issuerConfigRequestBody.json());
|
|
1106
|
+
}
|
|
1107
|
+
catch (err) {
|
|
1108
|
+
throw new ConfigurationError(`[${issuer.toString()}] has an invalid configuration: ${err.message}`);
|
|
1109
|
+
}
|
|
1110
|
+
await this.storageUtility.set(IssuerConfigFetcher.getLocalStorageKey(issuer), JSON.stringify(issuerConfig));
|
|
1111
|
+
return issuerConfig;
|
|
1112
|
+
}
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
function getUnauthenticatedSession() {
|
|
1116
|
+
return {
|
|
1117
|
+
isLoggedIn: false,
|
|
1118
|
+
sessionId: v4(),
|
|
1119
|
+
fetch,
|
|
1120
|
+
};
|
|
1121
|
+
}
|
|
1122
|
+
async function clear(sessionId, storage) {
|
|
1123
|
+
await Promise.all([
|
|
1124
|
+
storage.deleteAllUserData(sessionId, { secure: false }),
|
|
1125
|
+
storage.deleteAllUserData(sessionId, { secure: true }),
|
|
1126
|
+
storage.delete("clientKey", { secure: false }),
|
|
1127
|
+
]);
|
|
1128
|
+
await clearOidcPersistentStorage();
|
|
1129
|
+
}
|
|
1130
|
+
class SessionInfoManager {
|
|
1131
|
+
constructor(storageUtility) {
|
|
1132
|
+
this.storageUtility = storageUtility;
|
|
1133
|
+
}
|
|
1134
|
+
update(_sessionId, _options) {
|
|
1135
|
+
throw new Error("Not Implemented");
|
|
1136
|
+
}
|
|
1137
|
+
async get(sessionId) {
|
|
1138
|
+
var _a;
|
|
1139
|
+
const isLoggedIn = await this.storageUtility.getForUser(sessionId, "isLoggedIn", {
|
|
1140
|
+
secure: true,
|
|
1141
|
+
});
|
|
1142
|
+
const webId = await this.storageUtility.getForUser(sessionId, "webId", {
|
|
1143
|
+
secure: true,
|
|
1144
|
+
});
|
|
1145
|
+
const clientId = await this.storageUtility.getForUser(sessionId, "clientId", {
|
|
1146
|
+
secure: false,
|
|
1147
|
+
});
|
|
1148
|
+
const clientSecret = await this.storageUtility.getForUser(sessionId, "clientSecret", {
|
|
1149
|
+
secure: false,
|
|
1150
|
+
});
|
|
1151
|
+
const redirectUrl = await this.storageUtility.getForUser(sessionId, "redirectUrl", {
|
|
1152
|
+
secure: false,
|
|
1153
|
+
});
|
|
1154
|
+
const refreshToken = await this.storageUtility.getForUser(sessionId, "refreshToken", {
|
|
1155
|
+
secure: true,
|
|
1156
|
+
});
|
|
1157
|
+
const issuer = await this.storageUtility.getForUser(sessionId, "issuer", {
|
|
1158
|
+
secure: false,
|
|
1159
|
+
});
|
|
1160
|
+
const tokenType = (_a = (await this.storageUtility.getForUser(sessionId, "tokenType", {
|
|
1161
|
+
secure: false,
|
|
1162
|
+
}))) !== null && _a !== void 0 ? _a : "DPoP";
|
|
1163
|
+
if (!isSupportedTokenType(tokenType)) {
|
|
1164
|
+
throw new Error(`Tokens of type [${tokenType}] are not supported.`);
|
|
1165
|
+
}
|
|
1166
|
+
if (clientId === undefined &&
|
|
1167
|
+
isLoggedIn === undefined &&
|
|
1168
|
+
webId === undefined &&
|
|
1169
|
+
refreshToken === undefined) {
|
|
1170
|
+
return undefined;
|
|
1171
|
+
}
|
|
1172
|
+
return {
|
|
1173
|
+
sessionId,
|
|
1174
|
+
webId,
|
|
1175
|
+
isLoggedIn: isLoggedIn === "true",
|
|
1176
|
+
redirectUrl,
|
|
1177
|
+
refreshToken,
|
|
1178
|
+
issuer,
|
|
1179
|
+
clientAppId: clientId,
|
|
1180
|
+
clientAppSecret: clientSecret,
|
|
1181
|
+
tokenType,
|
|
1182
|
+
};
|
|
1183
|
+
}
|
|
1184
|
+
async getAll() {
|
|
1185
|
+
throw new Error("Not implemented");
|
|
1186
|
+
}
|
|
1187
|
+
async clear(sessionId) {
|
|
1188
|
+
return clear(sessionId, this.storageUtility);
|
|
1189
|
+
}
|
|
1190
|
+
async register(_sessionId) {
|
|
1191
|
+
throw new Error("Not implemented");
|
|
1192
|
+
}
|
|
1193
|
+
async getRegisteredSessionIdAll() {
|
|
1194
|
+
throw new Error("Not implemented");
|
|
1195
|
+
}
|
|
1196
|
+
async clearAll() {
|
|
1197
|
+
throw new Error("Not implemented");
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
class FallbackRedirectHandler {
|
|
1202
|
+
async canHandle(redirectUrl) {
|
|
1203
|
+
try {
|
|
1204
|
+
new URL(redirectUrl);
|
|
1205
|
+
return true;
|
|
1206
|
+
}
|
|
1207
|
+
catch (e) {
|
|
1208
|
+
throw new Error(`[${redirectUrl}] is not a valid URL, and cannot be used as a redirect URL: ${e}`);
|
|
1209
|
+
}
|
|
1210
|
+
}
|
|
1211
|
+
async handle(_redirectUrl) {
|
|
1212
|
+
return getUnauthenticatedSession();
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1216
|
+
class GeneralLogoutHandler {
|
|
1217
|
+
constructor(sessionInfoManager) {
|
|
1218
|
+
this.sessionInfoManager = sessionInfoManager;
|
|
1219
|
+
}
|
|
1220
|
+
async canHandle() {
|
|
1221
|
+
return true;
|
|
1222
|
+
}
|
|
1223
|
+
async handle(userId) {
|
|
1224
|
+
await this.sessionInfoManager.clear(userId);
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1227
|
+
|
|
1228
|
+
class AuthCodeRedirectHandler {
|
|
1229
|
+
constructor(storageUtility, sessionInfoManager, issuerConfigFetcher, clientRegistrar, tokerRefresher) {
|
|
1230
|
+
this.storageUtility = storageUtility;
|
|
1231
|
+
this.sessionInfoManager = sessionInfoManager;
|
|
1232
|
+
this.issuerConfigFetcher = issuerConfigFetcher;
|
|
1233
|
+
this.clientRegistrar = clientRegistrar;
|
|
1234
|
+
this.tokerRefresher = tokerRefresher;
|
|
1235
|
+
}
|
|
1236
|
+
async canHandle(redirectUrl) {
|
|
1237
|
+
try {
|
|
1238
|
+
const myUrl = new URL(redirectUrl);
|
|
1239
|
+
return (myUrl.searchParams.get("code") !== null &&
|
|
1240
|
+
myUrl.searchParams.get("state") !== null);
|
|
1241
|
+
}
|
|
1242
|
+
catch (e) {
|
|
1243
|
+
throw new Error(`[${redirectUrl}] is not a valid URL, and cannot be used as a redirect URL: ${e}`);
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
async handle(redirectUrl, eventEmitter) {
|
|
1247
|
+
if (!(await this.canHandle(redirectUrl))) {
|
|
1248
|
+
throw new Error(`AuthCodeRedirectHandler cannot handle [${redirectUrl}]: it is missing one of [code, state].`);
|
|
1249
|
+
}
|
|
1250
|
+
const url = new URL(redirectUrl);
|
|
1251
|
+
const oauthState = url.searchParams.get("state");
|
|
1252
|
+
const storedSessionId = (await this.storageUtility.getForUser(oauthState, "sessionId", {
|
|
1253
|
+
errorIfNull: true,
|
|
1254
|
+
}));
|
|
1255
|
+
const { issuerConfig, codeVerifier, redirectUrl: storedRedirectIri, dpop: isDpop, } = await loadOidcContextFromStorage(storedSessionId, this.storageUtility, this.issuerConfigFetcher);
|
|
1256
|
+
if (codeVerifier === undefined) {
|
|
1257
|
+
throw new Error(`The code verifier for session ${storedSessionId} is missing from storage.`);
|
|
1258
|
+
}
|
|
1259
|
+
if (storedRedirectIri === undefined) {
|
|
1260
|
+
throw new Error(`The redirect URL for session ${storedSessionId} is missing from storage.`);
|
|
1261
|
+
}
|
|
1262
|
+
const client = await this.clientRegistrar.getClient({ sessionId: storedSessionId }, issuerConfig);
|
|
1263
|
+
let tokens;
|
|
1264
|
+
const tokenCreatedAt = Date.now();
|
|
1265
|
+
if (isDpop) {
|
|
1266
|
+
tokens = await getDpopToken(issuerConfig, client, {
|
|
1267
|
+
grantType: "authorization_code",
|
|
1268
|
+
code: url.searchParams.get("code"),
|
|
1269
|
+
codeVerifier,
|
|
1270
|
+
redirectUrl: storedRedirectIri,
|
|
1271
|
+
});
|
|
1272
|
+
window.localStorage.removeItem(`oidc.${oauthState}`);
|
|
1273
|
+
}
|
|
1274
|
+
else {
|
|
1275
|
+
tokens = await getBearerToken(url.toString());
|
|
1276
|
+
}
|
|
1277
|
+
let refreshOptions;
|
|
1278
|
+
if (tokens.refreshToken !== undefined) {
|
|
1279
|
+
refreshOptions = {
|
|
1280
|
+
sessionId: storedSessionId,
|
|
1281
|
+
refreshToken: tokens.refreshToken,
|
|
1282
|
+
tokenRefresher: this.tokerRefresher,
|
|
1283
|
+
};
|
|
1284
|
+
}
|
|
1285
|
+
const authFetch = await buildAuthenticatedFetch(fetch, tokens.accessToken, {
|
|
1286
|
+
dpopKey: tokens.dpopKey,
|
|
1287
|
+
refreshOptions,
|
|
1288
|
+
eventEmitter,
|
|
1289
|
+
expiresIn: tokens.expiresIn,
|
|
1290
|
+
});
|
|
1291
|
+
await this.storageUtility.setForUser(storedSessionId, {
|
|
1292
|
+
webId: tokens.webId,
|
|
1293
|
+
isLoggedIn: "true",
|
|
1294
|
+
}, { secure: true });
|
|
1295
|
+
url.searchParams.delete("code");
|
|
1296
|
+
await this.storageUtility.setForUser(storedSessionId, {
|
|
1297
|
+
redirectUrl: url.toString(),
|
|
1298
|
+
}, {
|
|
1299
|
+
secure: false,
|
|
1300
|
+
});
|
|
1301
|
+
const sessionInfo = await this.sessionInfoManager.get(storedSessionId);
|
|
1302
|
+
if (!sessionInfo) {
|
|
1303
|
+
throw new Error(`Could not retrieve session: [${storedSessionId}].`);
|
|
1304
|
+
}
|
|
1305
|
+
return Object.assign(sessionInfo, {
|
|
1306
|
+
fetch: authFetch,
|
|
1307
|
+
expirationDate: typeof tokens.expiresIn === "number"
|
|
1308
|
+
? tokenCreatedAt + tokens.expiresIn * 1000
|
|
1309
|
+
: null,
|
|
1310
|
+
});
|
|
1311
|
+
}
|
|
1312
|
+
}
|
|
1313
|
+
|
|
1314
|
+
class AggregateRedirectHandler extends AggregateHandler {
|
|
1315
|
+
constructor(redirectHandlers) {
|
|
1316
|
+
super(redirectHandlers);
|
|
1317
|
+
}
|
|
1318
|
+
}
|
|
1319
|
+
|
|
1320
|
+
class BrowserStorage {
|
|
1321
|
+
get storage() {
|
|
1322
|
+
return window.localStorage;
|
|
1323
|
+
}
|
|
1324
|
+
async get(key) {
|
|
1325
|
+
return this.storage.getItem(key) || undefined;
|
|
1326
|
+
}
|
|
1327
|
+
async set(key, value) {
|
|
1328
|
+
this.storage.setItem(key, value);
|
|
1329
|
+
}
|
|
1330
|
+
async delete(key) {
|
|
1331
|
+
this.storage.removeItem(key);
|
|
1332
|
+
}
|
|
1333
|
+
}
|
|
1334
|
+
|
|
1335
|
+
let redirectIframe;
|
|
1336
|
+
function getRedirectIframe() {
|
|
1337
|
+
if (typeof redirectIframe === "undefined") {
|
|
1338
|
+
redirectIframe = window.document.createElement("iframe");
|
|
1339
|
+
redirectIframe.setAttribute("hidden", "true");
|
|
1340
|
+
redirectIframe.setAttribute("sandbox", "allow-scripts allow-same-origin");
|
|
1341
|
+
}
|
|
1342
|
+
return redirectIframe;
|
|
1343
|
+
}
|
|
1344
|
+
function redirectInIframe(redirectUrl) {
|
|
1345
|
+
const iframe = getRedirectIframe();
|
|
1346
|
+
window.document.body.appendChild(iframe);
|
|
1347
|
+
iframe.src = redirectUrl;
|
|
1348
|
+
}
|
|
1349
|
+
function setupIframeListener(handleIframeRedirect) {
|
|
1350
|
+
if (typeof window === "undefined") {
|
|
1351
|
+
return;
|
|
1352
|
+
}
|
|
1353
|
+
window.addEventListener("message", async (evt) => {
|
|
1354
|
+
const iframe = getRedirectIframe();
|
|
1355
|
+
if (evt.origin === window.location.origin &&
|
|
1356
|
+
evt.source === iframe.contentWindow) {
|
|
1357
|
+
if (typeof evt.data.redirectUrl === "string") {
|
|
1358
|
+
await handleIframeRedirect(evt.data.redirectUrl);
|
|
1359
|
+
}
|
|
1360
|
+
}
|
|
1361
|
+
if (window.document.body.contains(iframe)) {
|
|
1362
|
+
window.document.body.removeChild(iframe);
|
|
1363
|
+
}
|
|
1364
|
+
});
|
|
1365
|
+
}
|
|
1366
|
+
function postRedirectUrlToParent(redirectUrl) {
|
|
1367
|
+
window.top.postMessage({
|
|
1368
|
+
redirectUrl,
|
|
1369
|
+
}, window.location.origin);
|
|
1370
|
+
}
|
|
1371
|
+
|
|
1372
|
+
class Redirector {
|
|
1373
|
+
redirect(redirectUrl, options) {
|
|
1374
|
+
if (options && options.handleRedirect) {
|
|
1375
|
+
options.handleRedirect(redirectUrl);
|
|
1376
|
+
}
|
|
1377
|
+
else if (options && options.redirectByReplacingState) {
|
|
1378
|
+
window.history.replaceState({}, "", redirectUrl);
|
|
1379
|
+
}
|
|
1380
|
+
else if (options === null || options === void 0 ? void 0 : options.redirectInIframe) {
|
|
1381
|
+
redirectInIframe(redirectUrl);
|
|
1382
|
+
}
|
|
1383
|
+
else {
|
|
1384
|
+
window.location.href = redirectUrl;
|
|
1385
|
+
}
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1388
|
+
|
|
1389
|
+
class ClientRegistrar {
|
|
1390
|
+
constructor(storageUtility) {
|
|
1391
|
+
this.storageUtility = storageUtility;
|
|
1392
|
+
}
|
|
1393
|
+
async getClient(options, issuerConfig) {
|
|
1394
|
+
var _a;
|
|
1395
|
+
const [storedClientId, storedClientSecret,] = await Promise.all([
|
|
1396
|
+
this.storageUtility.getForUser(options.sessionId, "clientId", {
|
|
1397
|
+
secure: false,
|
|
1398
|
+
}),
|
|
1399
|
+
this.storageUtility.getForUser(options.sessionId, "clientSecret", {
|
|
1400
|
+
secure: false,
|
|
1401
|
+
}),
|
|
1402
|
+
]);
|
|
1403
|
+
if (storedClientId) {
|
|
1404
|
+
return {
|
|
1405
|
+
clientId: storedClientId,
|
|
1406
|
+
clientSecret: storedClientSecret,
|
|
1407
|
+
clientType: "dynamic",
|
|
1408
|
+
};
|
|
1409
|
+
}
|
|
1410
|
+
const extendedOptions = { ...options };
|
|
1411
|
+
extendedOptions.registrationAccessToken =
|
|
1412
|
+
(_a = extendedOptions.registrationAccessToken) !== null && _a !== void 0 ? _a : (await this.storageUtility.getForUser(options.sessionId, "registrationAccessToken"));
|
|
1413
|
+
try {
|
|
1414
|
+
const registeredClient = await registerClient(extendedOptions, issuerConfig);
|
|
1415
|
+
const infoToSave = {
|
|
1416
|
+
clientId: registeredClient.clientId,
|
|
1417
|
+
};
|
|
1418
|
+
if (registeredClient.clientSecret) {
|
|
1419
|
+
infoToSave.clientSecret = registeredClient.clientSecret;
|
|
1420
|
+
}
|
|
1421
|
+
if (registeredClient.idTokenSignedResponseAlg) {
|
|
1422
|
+
infoToSave.idTokenSignedResponseAlg =
|
|
1423
|
+
registeredClient.idTokenSignedResponseAlg;
|
|
1424
|
+
}
|
|
1425
|
+
await this.storageUtility.setForUser(extendedOptions.sessionId, infoToSave, {
|
|
1426
|
+
secure: false,
|
|
1427
|
+
});
|
|
1428
|
+
return registeredClient;
|
|
1429
|
+
}
|
|
1430
|
+
catch (error) {
|
|
1431
|
+
throw new Error(`Client registration failed: [${error}]`);
|
|
1432
|
+
}
|
|
1433
|
+
}
|
|
1434
|
+
}
|
|
1435
|
+
|
|
1436
|
+
class ErrorOidcHandler {
|
|
1437
|
+
async canHandle(redirectUrl) {
|
|
1438
|
+
try {
|
|
1439
|
+
return new URL(redirectUrl).searchParams.has("error");
|
|
1440
|
+
}
|
|
1441
|
+
catch (e) {
|
|
1442
|
+
throw new Error(`[${redirectUrl}] is not a valid URL, and cannot be used as a redirect URL: ${e}`);
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1445
|
+
async handle(redirectUrl, eventEmitter) {
|
|
1446
|
+
if (eventEmitter !== undefined) {
|
|
1447
|
+
const url = new URL(redirectUrl);
|
|
1448
|
+
const errorUrl = url.searchParams.get("error");
|
|
1449
|
+
const errorDescriptionUrl = url.searchParams.get("error_description");
|
|
1450
|
+
eventEmitter.emit(EVENTS.ERROR, errorUrl, errorDescriptionUrl);
|
|
1451
|
+
}
|
|
1452
|
+
return getUnauthenticatedSession();
|
|
1453
|
+
}
|
|
1454
|
+
}
|
|
1455
|
+
|
|
1456
|
+
class TokenRefresher {
|
|
1457
|
+
constructor(storageUtility, issuerConfigFetcher, clientRegistrar) {
|
|
1458
|
+
this.storageUtility = storageUtility;
|
|
1459
|
+
this.issuerConfigFetcher = issuerConfigFetcher;
|
|
1460
|
+
this.clientRegistrar = clientRegistrar;
|
|
1461
|
+
}
|
|
1462
|
+
async refresh(sessionId, refreshToken, dpopKey, eventEmitter) {
|
|
1463
|
+
const oidcContext = await loadOidcContextFromStorage(sessionId, this.storageUtility, this.issuerConfigFetcher);
|
|
1464
|
+
const clientInfo = await this.clientRegistrar.getClient({ sessionId }, oidcContext.issuerConfig);
|
|
1465
|
+
if (refreshToken === undefined) {
|
|
1466
|
+
throw new Error(`Session [${sessionId}] has no refresh token to allow it to refresh its access token.`);
|
|
1467
|
+
}
|
|
1468
|
+
if (oidcContext.dpop && dpopKey === undefined) {
|
|
1469
|
+
throw new Error(`For session [${sessionId}], the key bound to the DPoP access token must be provided to refresh said access token.`);
|
|
1470
|
+
}
|
|
1471
|
+
const tokenSet = await refresh(refreshToken, oidcContext.issuerConfig, clientInfo, dpopKey);
|
|
1472
|
+
if (tokenSet.refreshToken !== undefined) {
|
|
1473
|
+
eventEmitter === null || eventEmitter === void 0 ? void 0 : eventEmitter.emit(EVENTS.NEW_REFRESH_TOKEN, tokenSet.refreshToken);
|
|
1474
|
+
await this.storageUtility.setForUser(sessionId, {
|
|
1475
|
+
refreshToken: tokenSet.refreshToken,
|
|
1476
|
+
});
|
|
1477
|
+
}
|
|
1478
|
+
return tokenSet;
|
|
1479
|
+
}
|
|
1480
|
+
}
|
|
1481
|
+
|
|
1482
|
+
function getClientAuthenticationWithDependencies(dependencies) {
|
|
1483
|
+
const inMemoryStorage = new InMemoryStorage();
|
|
1484
|
+
const secureStorage = dependencies.secureStorage || inMemoryStorage;
|
|
1485
|
+
const insecureStorage = dependencies.insecureStorage || new BrowserStorage();
|
|
1486
|
+
const storageUtility = new StorageUtilityBrowser(secureStorage, insecureStorage);
|
|
1487
|
+
const issuerConfigFetcher = new IssuerConfigFetcher(storageUtility);
|
|
1488
|
+
const clientRegistrar = new ClientRegistrar(storageUtility);
|
|
1489
|
+
const sessionInfoManager = new SessionInfoManager(storageUtility);
|
|
1490
|
+
const tokenRefresher = new TokenRefresher(storageUtility, issuerConfigFetcher, clientRegistrar);
|
|
1491
|
+
const loginHandler = new OidcLoginHandler(storageUtility, new AuthorizationCodeWithPkceOidcHandler(storageUtility, new Redirector()), issuerConfigFetcher, clientRegistrar);
|
|
1492
|
+
const redirectHandler = new AggregateRedirectHandler([
|
|
1493
|
+
new ErrorOidcHandler(),
|
|
1494
|
+
new AuthCodeRedirectHandler(storageUtility, sessionInfoManager, issuerConfigFetcher, clientRegistrar, tokenRefresher),
|
|
1495
|
+
new FallbackRedirectHandler(),
|
|
1496
|
+
]);
|
|
1497
|
+
return new ClientAuthentication(loginHandler, redirectHandler, new GeneralLogoutHandler(sessionInfoManager), sessionInfoManager, issuerConfigFetcher);
|
|
1498
|
+
}
|
|
1499
|
+
|
|
1500
|
+
const KEY_CURRENT_SESSION = `${SOLID_CLIENT_AUTHN_KEY_PREFIX}currentSession`;
|
|
1501
|
+
const KEY_CURRENT_URL = `${SOLID_CLIENT_AUTHN_KEY_PREFIX}currentUrl`;
|
|
1502
|
+
|
|
1503
|
+
async function silentlyAuthenticate(sessionId, clientAuthn, options = {
|
|
1504
|
+
inIframe: false,
|
|
1505
|
+
}, session) {
|
|
1506
|
+
var _a;
|
|
1507
|
+
const storedSessionInfo = await clientAuthn.validateCurrentSession(sessionId);
|
|
1508
|
+
if (storedSessionInfo !== null) {
|
|
1509
|
+
window.localStorage.setItem(KEY_CURRENT_URL, window.location.href);
|
|
1510
|
+
await clientAuthn.login({
|
|
1511
|
+
sessionId,
|
|
1512
|
+
prompt: "none",
|
|
1513
|
+
oidcIssuer: storedSessionInfo.issuer,
|
|
1514
|
+
redirectUrl: storedSessionInfo.redirectUrl,
|
|
1515
|
+
clientId: storedSessionInfo.clientAppId,
|
|
1516
|
+
clientSecret: storedSessionInfo.clientAppSecret,
|
|
1517
|
+
tokenType: (_a = storedSessionInfo.tokenType) !== null && _a !== void 0 ? _a : "DPoP",
|
|
1518
|
+
inIframe: options.inIframe,
|
|
1519
|
+
}, session);
|
|
1520
|
+
return true;
|
|
1521
|
+
}
|
|
1522
|
+
return false;
|
|
1523
|
+
}
|
|
1524
|
+
function isLoggedIn(sessionInfo) {
|
|
1525
|
+
return !!(sessionInfo === null || sessionInfo === void 0 ? void 0 : sessionInfo.isLoggedIn);
|
|
1526
|
+
}
|
|
1527
|
+
class Session extends EventEmitter {
|
|
1528
|
+
constructor(sessionOptions = {}, sessionId) {
|
|
1529
|
+
super();
|
|
1530
|
+
this.tokenRequestInProgress = false;
|
|
1531
|
+
this.login = async (options) => {
|
|
1532
|
+
var _a;
|
|
1533
|
+
await this.clientAuthentication.login({
|
|
1534
|
+
sessionId: this.info.sessionId,
|
|
1535
|
+
...options,
|
|
1536
|
+
tokenType: (_a = options.tokenType) !== null && _a !== void 0 ? _a : "DPoP",
|
|
1537
|
+
}, this);
|
|
1538
|
+
return new Promise(() => undefined);
|
|
1539
|
+
};
|
|
1540
|
+
this.fetch = async (url, init) => {
|
|
1541
|
+
return this.clientAuthentication.fetch(url, init);
|
|
1542
|
+
};
|
|
1543
|
+
this.internalLogout = async (emitSignal) => {
|
|
1544
|
+
window.localStorage.removeItem(KEY_CURRENT_SESSION);
|
|
1545
|
+
await this.clientAuthentication.logout(this.info.sessionId);
|
|
1546
|
+
this.info.isLoggedIn = false;
|
|
1547
|
+
if (emitSignal) {
|
|
1548
|
+
this.emit(EVENTS.LOGOUT);
|
|
1549
|
+
}
|
|
1550
|
+
};
|
|
1551
|
+
this.logout = async () => this.internalLogout(true);
|
|
1552
|
+
this.handleIncomingRedirect = async (inputOptions = {}) => {
|
|
1553
|
+
var _a;
|
|
1554
|
+
if (this.info.isLoggedIn) {
|
|
1555
|
+
return this.info;
|
|
1556
|
+
}
|
|
1557
|
+
if (this.tokenRequestInProgress) {
|
|
1558
|
+
return undefined;
|
|
1559
|
+
}
|
|
1560
|
+
const options = typeof inputOptions === "string" ? { url: inputOptions } : inputOptions;
|
|
1561
|
+
const url = (_a = options.url) !== null && _a !== void 0 ? _a : window.location.href;
|
|
1562
|
+
if (window.frameElement !== null) {
|
|
1563
|
+
postRedirectUrlToParent(url);
|
|
1564
|
+
return undefined;
|
|
1565
|
+
}
|
|
1566
|
+
this.tokenRequestInProgress = true;
|
|
1567
|
+
const sessionInfo = await this.clientAuthentication.handleIncomingRedirect(url, this);
|
|
1568
|
+
if (isLoggedIn(sessionInfo)) {
|
|
1569
|
+
this.setSessionInfo(sessionInfo);
|
|
1570
|
+
const currentUrl = window.localStorage.getItem(KEY_CURRENT_URL);
|
|
1571
|
+
if (currentUrl === null) {
|
|
1572
|
+
this.emit(EVENTS.LOGIN);
|
|
1573
|
+
}
|
|
1574
|
+
else {
|
|
1575
|
+
window.localStorage.removeItem(KEY_CURRENT_URL);
|
|
1576
|
+
this.emit(EVENTS.SESSION_RESTORED, currentUrl);
|
|
1577
|
+
}
|
|
1578
|
+
}
|
|
1579
|
+
else if (options.restorePreviousSession === true) {
|
|
1580
|
+
const storedSessionId = window.localStorage.getItem(KEY_CURRENT_SESSION);
|
|
1581
|
+
if (storedSessionId !== null) {
|
|
1582
|
+
const attemptedSilentAuthentication = await silentlyAuthenticate(storedSessionId, this.clientAuthentication, undefined, this);
|
|
1583
|
+
if (attemptedSilentAuthentication) {
|
|
1584
|
+
return new Promise(() => { });
|
|
1585
|
+
}
|
|
1586
|
+
}
|
|
1587
|
+
}
|
|
1588
|
+
this.tokenRequestInProgress = false;
|
|
1589
|
+
return sessionInfo;
|
|
1590
|
+
};
|
|
1591
|
+
if (sessionOptions.clientAuthentication) {
|
|
1592
|
+
this.clientAuthentication = sessionOptions.clientAuthentication;
|
|
1593
|
+
}
|
|
1594
|
+
else if (sessionOptions.secureStorage && sessionOptions.insecureStorage) {
|
|
1595
|
+
this.clientAuthentication = getClientAuthenticationWithDependencies({
|
|
1596
|
+
secureStorage: sessionOptions.secureStorage,
|
|
1597
|
+
insecureStorage: sessionOptions.insecureStorage,
|
|
1598
|
+
});
|
|
1599
|
+
}
|
|
1600
|
+
else {
|
|
1601
|
+
this.clientAuthentication = getClientAuthenticationWithDependencies({});
|
|
1602
|
+
}
|
|
1603
|
+
if (sessionOptions.sessionInfo) {
|
|
1604
|
+
this.info = {
|
|
1605
|
+
sessionId: sessionOptions.sessionInfo.sessionId,
|
|
1606
|
+
isLoggedIn: false,
|
|
1607
|
+
webId: sessionOptions.sessionInfo.webId,
|
|
1608
|
+
};
|
|
1609
|
+
}
|
|
1610
|
+
else {
|
|
1611
|
+
this.info = {
|
|
1612
|
+
sessionId: sessionId !== null && sessionId !== void 0 ? sessionId : v4(),
|
|
1613
|
+
isLoggedIn: false,
|
|
1614
|
+
};
|
|
1615
|
+
}
|
|
1616
|
+
setupIframeListener(async (redirectUrl) => {
|
|
1617
|
+
const sessionInfo = await this.clientAuthentication.handleIncomingRedirect(redirectUrl, this);
|
|
1618
|
+
if (!isLoggedIn(sessionInfo)) {
|
|
1619
|
+
return;
|
|
1620
|
+
}
|
|
1621
|
+
this.setSessionInfo(sessionInfo);
|
|
1622
|
+
});
|
|
1623
|
+
this.on("tokenRenewal", () => silentlyAuthenticate(this.info.sessionId, this.clientAuthentication, {
|
|
1624
|
+
inIframe: true,
|
|
1625
|
+
}, this));
|
|
1626
|
+
this.on(EVENTS.LOGIN, () => window.localStorage.setItem(KEY_CURRENT_SESSION, this.info.sessionId));
|
|
1627
|
+
this.on(EVENTS.SESSION_EXPIRED, () => this.internalLogout(false));
|
|
1628
|
+
this.on(EVENTS.ERROR, () => this.internalLogout(false));
|
|
1629
|
+
window.localStorage.removeItem("tmp-resource-server-session-enabled");
|
|
1630
|
+
}
|
|
1631
|
+
onLogin(callback) {
|
|
1632
|
+
this.on(EVENTS.LOGIN, callback);
|
|
1633
|
+
}
|
|
1634
|
+
onLogout(callback) {
|
|
1635
|
+
this.on(EVENTS.LOGOUT, callback);
|
|
1636
|
+
}
|
|
1637
|
+
onError(callback) {
|
|
1638
|
+
this.on(EVENTS.ERROR, callback);
|
|
1639
|
+
}
|
|
1640
|
+
onSessionRestore(callback) {
|
|
1641
|
+
this.on(EVENTS.SESSION_RESTORED, callback);
|
|
1642
|
+
}
|
|
1643
|
+
onSessionExpiration(callback) {
|
|
1644
|
+
this.on(EVENTS.SESSION_EXPIRED, callback);
|
|
1645
|
+
}
|
|
1646
|
+
setSessionInfo(sessionInfo) {
|
|
1647
|
+
this.info.isLoggedIn = sessionInfo.isLoggedIn;
|
|
1648
|
+
this.info.webId = sessionInfo.webId;
|
|
1649
|
+
this.info.sessionId = sessionInfo.sessionId;
|
|
1650
|
+
this.info.expirationDate = sessionInfo.expirationDate;
|
|
1651
|
+
this.on(EVENTS.SESSION_EXTENDED, (expiresIn) => {
|
|
1652
|
+
this.info.expirationDate = Date.now() + expiresIn * 1000;
|
|
1653
|
+
});
|
|
1654
|
+
}
|
|
1655
|
+
}
|
|
1656
|
+
|
|
1657
|
+
let defaultSession;
|
|
1658
|
+
function getDefaultSession() {
|
|
1659
|
+
if (typeof defaultSession === "undefined") {
|
|
1660
|
+
defaultSession = new Session();
|
|
1661
|
+
}
|
|
1662
|
+
return defaultSession;
|
|
1663
|
+
}
|
|
1664
|
+
const fetch$1 = (...args) => {
|
|
1665
|
+
const session = getDefaultSession();
|
|
1666
|
+
return session.fetch(...args);
|
|
1667
|
+
};
|
|
1668
|
+
const login = (...args) => {
|
|
1669
|
+
const session = getDefaultSession();
|
|
1670
|
+
return session.login(...args);
|
|
1671
|
+
};
|
|
1672
|
+
const logout = (...args) => {
|
|
1673
|
+
const session = getDefaultSession();
|
|
1674
|
+
return session.logout(...args);
|
|
1675
|
+
};
|
|
1676
|
+
const handleIncomingRedirect = (...args) => {
|
|
1677
|
+
const session = getDefaultSession();
|
|
1678
|
+
return session.handleIncomingRedirect(...args);
|
|
1679
|
+
};
|
|
1680
|
+
const onLogin = (...args) => {
|
|
1681
|
+
const session = getDefaultSession();
|
|
1682
|
+
return session.onLogin(...args);
|
|
1683
|
+
};
|
|
1684
|
+
const onLogout = (...args) => {
|
|
1685
|
+
const session = getDefaultSession();
|
|
1686
|
+
return session.onLogout(...args);
|
|
1687
|
+
};
|
|
1688
|
+
const onSessionRestore = (...args) => {
|
|
1689
|
+
const session = getDefaultSession();
|
|
1690
|
+
return session.onSessionRestore(...args);
|
|
1691
|
+
};
|
|
1692
|
+
|
|
1693
|
+
export { Session, fetch$1 as fetch, getClientAuthenticationWithDependencies, getDefaultSession, handleIncomingRedirect, login, logout, onLogin, onLogout, onSessionRestore };
|