@esri/arcgis-rest-auth 3.4.2 → 4.0.0-beta.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 (72) hide show
  1. package/.ultra.cache.json +1 -0
  2. package/CHANGELOG.md +110 -0
  3. package/README.md +5 -5
  4. package/dist/bundled/auth.esm.js +7 -0
  5. package/dist/bundled/auth.esm.js.map +1 -0
  6. package/dist/bundled/auth.esm.min.js +7 -0
  7. package/dist/bundled/auth.esm.min.js.map +1 -0
  8. package/dist/bundled/auth.umd.js +112 -0
  9. package/dist/bundled/auth.umd.js.map +1 -0
  10. package/dist/bundled/auth.umd.min.js +7 -0
  11. package/dist/bundled/auth.umd.min.js.map +1 -0
  12. package/dist/cjs/index.js +20 -0
  13. package/dist/cjs/index.js.map +1 -0
  14. package/dist/cjs/package.json +3 -0
  15. package/dist/esm/index.d.ts +4 -9
  16. package/dist/esm/index.js +1 -8
  17. package/dist/esm/index.js.map +1 -1
  18. package/dist/esm/package.json +3 -0
  19. package/package.json +44 -45
  20. package/src/index.ts +34 -0
  21. package/tsconfig.json +6 -0
  22. package/dist/esm/ApiKey.d.ts +0 -26
  23. package/dist/esm/ApiKey.js +0 -23
  24. package/dist/esm/ApiKey.js.map +0 -1
  25. package/dist/esm/ApplicationSession.d.ts +0 -60
  26. package/dist/esm/ApplicationSession.js +0 -59
  27. package/dist/esm/ApplicationSession.js.map +0 -1
  28. package/dist/esm/UserSession.d.ts +0 -496
  29. package/dist/esm/UserSession.js +0 -890
  30. package/dist/esm/UserSession.js.map +0 -1
  31. package/dist/esm/app-tokens.d.ts +0 -87
  32. package/dist/esm/app-tokens.js +0 -104
  33. package/dist/esm/app-tokens.js.map +0 -1
  34. package/dist/esm/authenticated-request-options.d.ts +0 -18
  35. package/dist/esm/authenticated-request-options.js +0 -3
  36. package/dist/esm/authenticated-request-options.js.map +0 -1
  37. package/dist/esm/federation-utils.d.ts +0 -5
  38. package/dist/esm/federation-utils.js +0 -59
  39. package/dist/esm/federation-utils.js.map +0 -1
  40. package/dist/esm/fetch-token.d.ts +0 -9
  41. package/dist/esm/fetch-token.js +0 -23
  42. package/dist/esm/fetch-token.js.map +0 -1
  43. package/dist/esm/generate-token.d.ts +0 -7
  44. package/dist/esm/generate-token.js +0 -17
  45. package/dist/esm/generate-token.js.map +0 -1
  46. package/dist/esm/validate-app-access.d.ts +0 -47
  47. package/dist/esm/validate-app-access.js +0 -52
  48. package/dist/esm/validate-app-access.js.map +0 -1
  49. package/dist/node/ApiKey.js +0 -26
  50. package/dist/node/ApiKey.js.map +0 -1
  51. package/dist/node/ApplicationSession.js +0 -62
  52. package/dist/node/ApplicationSession.js.map +0 -1
  53. package/dist/node/UserSession.js +0 -893
  54. package/dist/node/UserSession.js.map +0 -1
  55. package/dist/node/app-tokens.js +0 -109
  56. package/dist/node/app-tokens.js.map +0 -1
  57. package/dist/node/authenticated-request-options.js +0 -5
  58. package/dist/node/authenticated-request-options.js.map +0 -1
  59. package/dist/node/federation-utils.js +0 -67
  60. package/dist/node/federation-utils.js.map +0 -1
  61. package/dist/node/fetch-token.js +0 -27
  62. package/dist/node/fetch-token.js.map +0 -1
  63. package/dist/node/generate-token.js +0 -21
  64. package/dist/node/generate-token.js.map +0 -1
  65. package/dist/node/index.js +0 -14
  66. package/dist/node/index.js.map +0 -1
  67. package/dist/node/validate-app-access.js +0 -56
  68. package/dist/node/validate-app-access.js.map +0 -1
  69. package/dist/umd/auth.umd.js +0 -1253
  70. package/dist/umd/auth.umd.js.map +0 -1
  71. package/dist/umd/auth.umd.min.js +0 -7
  72. package/dist/umd/auth.umd.min.js.map +0 -1
@@ -1,893 +0,0 @@
1
- "use strict";
2
- /* Copyright (c) 2017-2019 Environmental Systems Research Institute, Inc.
3
- * Apache-2.0 */
4
- Object.defineProperty(exports, "__esModule", { value: true });
5
- exports.UserSession = void 0;
6
- var tslib_1 = require("tslib");
7
- var arcgis_rest_request_1 = require("@esri/arcgis-rest-request");
8
- var generate_token_1 = require("./generate-token");
9
- var fetch_token_1 = require("./fetch-token");
10
- var federation_utils_1 = require("./federation-utils");
11
- var validate_app_access_1 = require("./validate-app-access");
12
- function defer() {
13
- var deferred = {
14
- promise: null,
15
- resolve: null,
16
- reject: null,
17
- };
18
- deferred.promise = new Promise(function (resolve, reject) {
19
- deferred.resolve = resolve;
20
- deferred.reject = reject;
21
- });
22
- return deferred;
23
- }
24
- /**
25
- * ```js
26
- * import { UserSession } from '@esri/arcgis-rest-auth';
27
- * UserSession.beginOAuth2({
28
- * // register an app of your own to create a unique clientId
29
- * clientId: "abc123",
30
- * redirectUri: 'https://yourapp.com/authenticate.html'
31
- * })
32
- * .then(session)
33
- * // or
34
- * new UserSession({
35
- * username: "jsmith",
36
- * password: "123456"
37
- * })
38
- * // or
39
- * UserSession.deserialize(cache)
40
- * ```
41
- * Used to authenticate both ArcGIS Online and ArcGIS Enterprise users. `UserSession` includes helper methods for [OAuth 2.0](/arcgis-rest-js/guides/browser-authentication/) in both browser and server applications.
42
- */
43
- var UserSession = /** @class */ (function () {
44
- function UserSession(options) {
45
- this.clientId = options.clientId;
46
- this._refreshToken = options.refreshToken;
47
- this._refreshTokenExpires = options.refreshTokenExpires;
48
- this.username = options.username;
49
- this.password = options.password;
50
- this._token = options.token;
51
- this._tokenExpires = options.tokenExpires;
52
- this.portal = options.portal
53
- ? arcgis_rest_request_1.cleanUrl(options.portal)
54
- : "https://www.arcgis.com/sharing/rest";
55
- this.ssl = options.ssl;
56
- this.provider = options.provider || "arcgis";
57
- this.tokenDuration = options.tokenDuration || 20160;
58
- this.redirectUri = options.redirectUri;
59
- this.refreshTokenTTL = options.refreshTokenTTL || 20160;
60
- this.server = options.server;
61
- this.federatedServers = {};
62
- this.trustedDomains = [];
63
- // if a non-federated server was passed explicitly, it should be trusted.
64
- if (options.server) {
65
- // if the url includes more than '/arcgis/', trim the rest
66
- var root = this.getServerRootUrl(options.server);
67
- this.federatedServers[root] = {
68
- token: options.token,
69
- expires: options.tokenExpires,
70
- };
71
- }
72
- this._pendingTokenRequests = {};
73
- }
74
- Object.defineProperty(UserSession.prototype, "token", {
75
- /**
76
- * The current ArcGIS Online or ArcGIS Enterprise `token`.
77
- */
78
- get: function () {
79
- return this._token;
80
- },
81
- enumerable: false,
82
- configurable: true
83
- });
84
- Object.defineProperty(UserSession.prototype, "tokenExpires", {
85
- /**
86
- * The expiration time of the current `token`.
87
- */
88
- get: function () {
89
- return this._tokenExpires;
90
- },
91
- enumerable: false,
92
- configurable: true
93
- });
94
- Object.defineProperty(UserSession.prototype, "refreshToken", {
95
- /**
96
- * The current token to ArcGIS Online or ArcGIS Enterprise.
97
- */
98
- get: function () {
99
- return this._refreshToken;
100
- },
101
- enumerable: false,
102
- configurable: true
103
- });
104
- Object.defineProperty(UserSession.prototype, "refreshTokenExpires", {
105
- /**
106
- * The expiration time of the current `refreshToken`.
107
- */
108
- get: function () {
109
- return this._refreshTokenExpires;
110
- },
111
- enumerable: false,
112
- configurable: true
113
- });
114
- Object.defineProperty(UserSession.prototype, "trustedServers", {
115
- /**
116
- * Deprecated, use `federatedServers` instead.
117
- *
118
- * @deprecated
119
- */
120
- get: function () {
121
- console.log("DEPRECATED: use federatedServers instead");
122
- return this.federatedServers;
123
- },
124
- enumerable: false,
125
- configurable: true
126
- });
127
- /**
128
- * Begins a new browser-based OAuth 2.0 sign in. If `options.popup` is `true` the
129
- * authentication window will open in a new tab/window and the function will return
130
- * Promise<UserSession>. Otherwise, the user will be redirected to the
131
- * authorization page in their current tab/window and the function will return `undefined`.
132
- *
133
- * @browserOnly
134
- */
135
- /* istanbul ignore next */
136
- UserSession.beginOAuth2 = function (options, win) {
137
- if (win === void 0) { win = window; }
138
- if (options.duration) {
139
- console.log("DEPRECATED: 'duration' is deprecated - use 'expiration' instead");
140
- }
141
- var _a = tslib_1.__assign({
142
- portal: "https://www.arcgis.com/sharing/rest",
143
- provider: "arcgis",
144
- expiration: 20160,
145
- popup: true,
146
- popupWindowFeatures: "height=400,width=600,menubar=no,location=yes,resizable=yes,scrollbars=yes,status=yes",
147
- state: options.clientId,
148
- locale: "",
149
- }, options), portal = _a.portal, provider = _a.provider, clientId = _a.clientId, expiration = _a.expiration, redirectUri = _a.redirectUri, popup = _a.popup, popupWindowFeatures = _a.popupWindowFeatures, state = _a.state, locale = _a.locale, params = _a.params;
150
- var url;
151
- if (provider === "arcgis") {
152
- url = portal + "/oauth2/authorize?client_id=" + clientId + "&response_type=token&expiration=" + (options.duration || expiration) + "&redirect_uri=" + encodeURIComponent(redirectUri) + "&state=" + state + "&locale=" + locale;
153
- }
154
- else {
155
- url = portal + "/oauth2/social/authorize?client_id=" + clientId + "&socialLoginProviderName=" + provider + "&autoAccountCreateForSocial=true&response_type=token&expiration=" + (options.duration || expiration) + "&redirect_uri=" + encodeURIComponent(redirectUri) + "&state=" + state + "&locale=" + locale;
156
- }
157
- // append additional params
158
- if (params) {
159
- url = url + "&" + arcgis_rest_request_1.encodeQueryString(params);
160
- }
161
- if (!popup) {
162
- win.location.href = url;
163
- return undefined;
164
- }
165
- var session = defer();
166
- win["__ESRI_REST_AUTH_HANDLER_" + clientId] = function (errorString, oauthInfoString) {
167
- if (errorString) {
168
- var error = JSON.parse(errorString);
169
- session.reject(new arcgis_rest_request_1.ArcGISAuthError(error.errorMessage, error.error));
170
- return;
171
- }
172
- if (oauthInfoString) {
173
- var oauthInfo = JSON.parse(oauthInfoString);
174
- session.resolve(new UserSession({
175
- clientId: clientId,
176
- portal: portal,
177
- ssl: oauthInfo.ssl,
178
- token: oauthInfo.token,
179
- tokenExpires: new Date(oauthInfo.expires),
180
- username: oauthInfo.username,
181
- }));
182
- }
183
- };
184
- win.open(url, "oauth-window", popupWindowFeatures);
185
- return session.promise;
186
- };
187
- /**
188
- * Completes a browser-based OAuth 2.0 sign in. If `options.popup` is `true` the user
189
- * will be returned to the previous window. Otherwise a new `UserSession`
190
- * will be returned. You must pass the same values for `options.popup` and
191
- * `options.portal` as you used in `beginOAuth2()`.
192
- *
193
- * @browserOnly
194
- */
195
- /* istanbul ignore next */
196
- UserSession.completeOAuth2 = function (options, win) {
197
- if (win === void 0) { win = window; }
198
- var _a = tslib_1.__assign({ portal: "https://www.arcgis.com/sharing/rest", popup: true }, options), portal = _a.portal, clientId = _a.clientId, popup = _a.popup;
199
- function completeSignIn(error, oauthInfo) {
200
- try {
201
- var handlerFn = void 0;
202
- var handlerFnName = "__ESRI_REST_AUTH_HANDLER_" + clientId;
203
- if (popup) {
204
- // Guard b/c IE does not support window.opener
205
- if (win.opener) {
206
- if (win.opener.parent && win.opener.parent[handlerFnName]) {
207
- handlerFn = win.opener.parent[handlerFnName];
208
- }
209
- else if (win.opener && win.opener[handlerFnName]) {
210
- // support pop-out oauth from within an iframe
211
- handlerFn = win.opener[handlerFnName];
212
- }
213
- }
214
- else {
215
- // IE
216
- if (win !== win.parent && win.parent && win.parent[handlerFnName]) {
217
- handlerFn = win.parent[handlerFnName];
218
- }
219
- }
220
- // if we have a handler fn, call it and close the window
221
- if (handlerFn) {
222
- handlerFn(error ? JSON.stringify(error) : undefined, JSON.stringify(oauthInfo));
223
- win.close();
224
- return undefined;
225
- }
226
- }
227
- }
228
- catch (e) {
229
- throw new arcgis_rest_request_1.ArcGISAuthError("Unable to complete authentication. It's possible you specified popup based oAuth2 but no handler from \"beginOAuth2()\" present. This generally happens because the \"popup\" option differs between \"beginOAuth2()\" and \"completeOAuth2()\".");
230
- }
231
- if (error) {
232
- throw new arcgis_rest_request_1.ArcGISAuthError(error.errorMessage, error.error);
233
- }
234
- return new UserSession({
235
- clientId: clientId,
236
- portal: portal,
237
- ssl: oauthInfo.ssl,
238
- token: oauthInfo.token,
239
- tokenExpires: oauthInfo.expires,
240
- username: oauthInfo.username,
241
- });
242
- }
243
- var params = arcgis_rest_request_1.decodeQueryString(win.location.hash);
244
- if (!params.access_token) {
245
- var error = void 0;
246
- var errorMessage = "Unknown error";
247
- if (params.error) {
248
- error = params.error;
249
- errorMessage = params.error_description;
250
- }
251
- return completeSignIn({ error: error, errorMessage: errorMessage });
252
- }
253
- var token = params.access_token;
254
- var expires = new Date(Date.now() + parseInt(params.expires_in, 10) * 1000 - 60 * 1000);
255
- var username = params.username;
256
- var ssl = params.ssl === "true";
257
- return completeSignIn(undefined, {
258
- token: token,
259
- expires: expires,
260
- ssl: ssl,
261
- username: username,
262
- });
263
- };
264
- /**
265
- * Request session information from the parent application
266
- *
267
- * When an application is embedded into another application via an IFrame, the embedded app can
268
- * use `window.postMessage` to request credentials from the host application. This function wraps
269
- * that behavior.
270
- *
271
- * The ArcGIS API for Javascript has this built into the Identity Manager as of the 4.19 release.
272
- *
273
- * Note: The parent application will not respond if the embedded app's origin is not:
274
- * - the same origin as the parent or *.arcgis.com (JSAPI)
275
- * - in the list of valid child origins (REST-JS)
276
- *
277
- *
278
- * @param parentOrigin origin of the parent frame. Passed into the embedded application as `parentOrigin` query param
279
- * @browserOnly
280
- */
281
- UserSession.fromParent = function (parentOrigin, win) {
282
- /* istanbul ignore next: must pass in a mockwindow for tests so we can't cover the other branch */
283
- if (!win && window) {
284
- win = window;
285
- }
286
- // Declare handler outside of promise scope so we can detach it
287
- var handler;
288
- // return a promise that will resolve when the handler receives
289
- // session information from the correct origin
290
- return new Promise(function (resolve, reject) {
291
- // create an event handler that just wraps the parentMessageHandler
292
- handler = function (event) {
293
- // ensure we only listen to events from the parent
294
- if (event.source === win.parent && event.data) {
295
- try {
296
- return resolve(UserSession.parentMessageHandler(event));
297
- }
298
- catch (err) {
299
- return reject(err);
300
- }
301
- }
302
- };
303
- // add listener
304
- win.addEventListener("message", handler, false);
305
- win.parent.postMessage({ type: "arcgis:auth:requestCredential" }, parentOrigin);
306
- }).then(function (session) {
307
- win.removeEventListener("message", handler, false);
308
- return session;
309
- });
310
- };
311
- /**
312
- * Begins a new server-based OAuth 2.0 sign in. This will redirect the user to
313
- * the ArcGIS Online or ArcGIS Enterprise authorization page.
314
- *
315
- * @nodeOnly
316
- */
317
- UserSession.authorize = function (options, response) {
318
- if (options.duration) {
319
- console.log("DEPRECATED: 'duration' is deprecated - use 'expiration' instead");
320
- }
321
- var _a = tslib_1.__assign({ portal: "https://arcgis.com/sharing/rest", expiration: 20160 }, options), portal = _a.portal, clientId = _a.clientId, expiration = _a.expiration, redirectUri = _a.redirectUri;
322
- response.writeHead(301, {
323
- Location: portal + "/oauth2/authorize?client_id=" + clientId + "&expiration=" + (options.duration || expiration) + "&response_type=code&redirect_uri=" + encodeURIComponent(redirectUri),
324
- });
325
- response.end();
326
- };
327
- /**
328
- * Completes the server-based OAuth 2.0 sign in process by exchanging the `authorizationCode`
329
- * for a `access_token`.
330
- *
331
- * @nodeOnly
332
- */
333
- UserSession.exchangeAuthorizationCode = function (options, authorizationCode) {
334
- var _a = tslib_1.__assign({
335
- portal: "https://www.arcgis.com/sharing/rest",
336
- refreshTokenTTL: 20160,
337
- }, options), portal = _a.portal, clientId = _a.clientId, redirectUri = _a.redirectUri, refreshTokenTTL = _a.refreshTokenTTL;
338
- return fetch_token_1.fetchToken(portal + "/oauth2/token", {
339
- params: {
340
- grant_type: "authorization_code",
341
- client_id: clientId,
342
- redirect_uri: redirectUri,
343
- code: authorizationCode,
344
- },
345
- }).then(function (response) {
346
- return new UserSession({
347
- clientId: clientId,
348
- portal: portal,
349
- ssl: response.ssl,
350
- redirectUri: redirectUri,
351
- refreshToken: response.refreshToken,
352
- refreshTokenTTL: refreshTokenTTL,
353
- refreshTokenExpires: new Date(Date.now() + (refreshTokenTTL - 1) * 60 * 1000),
354
- token: response.token,
355
- tokenExpires: response.expires,
356
- username: response.username,
357
- });
358
- });
359
- };
360
- UserSession.deserialize = function (str) {
361
- var options = JSON.parse(str);
362
- return new UserSession({
363
- clientId: options.clientId,
364
- refreshToken: options.refreshToken,
365
- refreshTokenExpires: new Date(options.refreshTokenExpires),
366
- username: options.username,
367
- password: options.password,
368
- token: options.token,
369
- tokenExpires: new Date(options.tokenExpires),
370
- portal: options.portal,
371
- ssl: options.ssl,
372
- tokenDuration: options.tokenDuration,
373
- redirectUri: options.redirectUri,
374
- refreshTokenTTL: options.refreshTokenTTL,
375
- });
376
- };
377
- /**
378
- * Translates authentication from the format used in the [ArcGIS API for JavaScript](https://developers.arcgis.com/javascript/).
379
- *
380
- * ```js
381
- * UserSession.fromCredential({
382
- * userId: "jsmith",
383
- * token: "secret"
384
- * });
385
- * ```
386
- *
387
- * @returns UserSession
388
- */
389
- UserSession.fromCredential = function (credential) {
390
- // At ArcGIS Online 9.1, credentials no longer include the ssl and expires properties
391
- // Here, we provide default values for them to cover this condition
392
- var ssl = typeof credential.ssl !== "undefined" ? credential.ssl : true;
393
- var expires = credential.expires || Date.now() + 7200000 /* 2 hours */;
394
- return new UserSession({
395
- portal: credential.server.includes("sharing/rest")
396
- ? credential.server
397
- : credential.server + "/sharing/rest",
398
- ssl: ssl,
399
- token: credential.token,
400
- username: credential.userId,
401
- tokenExpires: new Date(expires),
402
- });
403
- };
404
- /**
405
- * Handle the response from the parent
406
- * @param event DOM Event
407
- */
408
- UserSession.parentMessageHandler = function (event) {
409
- if (event.data.type === "arcgis:auth:credential") {
410
- return UserSession.fromCredential(event.data.credential);
411
- }
412
- if (event.data.type === "arcgis:auth:error") {
413
- var err = new Error(event.data.error.message);
414
- err.name = event.data.error.name;
415
- throw err;
416
- }
417
- else {
418
- throw new Error("Unknown message type.");
419
- }
420
- };
421
- /**
422
- * Returns authentication in a format useable in the [ArcGIS API for JavaScript](https://developers.arcgis.com/javascript/).
423
- *
424
- * ```js
425
- * esriId.registerToken(session.toCredential());
426
- * ```
427
- *
428
- * @returns ICredential
429
- */
430
- UserSession.prototype.toCredential = function () {
431
- return {
432
- expires: this.tokenExpires.getTime(),
433
- server: this.portal,
434
- ssl: this.ssl,
435
- token: this.token,
436
- userId: this.username,
437
- };
438
- };
439
- /**
440
- * Returns information about the currently logged in [user](https://developers.arcgis.com/rest/users-groups-and-items/user.htm). Subsequent calls will *not* result in additional web traffic.
441
- *
442
- * ```js
443
- * session.getUser()
444
- * .then(response => {
445
- * console.log(response.role); // "org_admin"
446
- * })
447
- * ```
448
- *
449
- * @param requestOptions - Options for the request. NOTE: `rawResponse` is not supported by this operation.
450
- * @returns A Promise that will resolve with the data from the response.
451
- */
452
- UserSession.prototype.getUser = function (requestOptions) {
453
- var _this = this;
454
- if (this._pendingUserRequest) {
455
- return this._pendingUserRequest;
456
- }
457
- else if (this._user) {
458
- return Promise.resolve(this._user);
459
- }
460
- else {
461
- var url = this.portal + "/community/self";
462
- var options = tslib_1.__assign(tslib_1.__assign({ httpMethod: "GET", authentication: this }, requestOptions), { rawResponse: false });
463
- this._pendingUserRequest = arcgis_rest_request_1.request(url, options).then(function (response) {
464
- _this._user = response;
465
- _this._pendingUserRequest = null;
466
- return response;
467
- });
468
- return this._pendingUserRequest;
469
- }
470
- };
471
- /**
472
- * Returns information about the currently logged in user's [portal](https://developers.arcgis.com/rest/users-groups-and-items/portal-self.htm). Subsequent calls will *not* result in additional web traffic.
473
- *
474
- * ```js
475
- * session.getPortal()
476
- * .then(response => {
477
- * console.log(portal.name); // "City of ..."
478
- * })
479
- * ```
480
- *
481
- * @param requestOptions - Options for the request. NOTE: `rawResponse` is not supported by this operation.
482
- * @returns A Promise that will resolve with the data from the response.
483
- */
484
- UserSession.prototype.getPortal = function (requestOptions) {
485
- var _this = this;
486
- if (this._pendingPortalRequest) {
487
- return this._pendingPortalRequest;
488
- }
489
- else if (this._portalInfo) {
490
- return Promise.resolve(this._portalInfo);
491
- }
492
- else {
493
- var url = this.portal + "/portals/self";
494
- var options = tslib_1.__assign(tslib_1.__assign({ httpMethod: "GET", authentication: this }, requestOptions), { rawResponse: false });
495
- this._pendingPortalRequest = arcgis_rest_request_1.request(url, options).then(function (response) {
496
- _this._portalInfo = response;
497
- _this._pendingPortalRequest = null;
498
- return response;
499
- });
500
- return this._pendingPortalRequest;
501
- }
502
- };
503
- /**
504
- * Returns the username for the currently logged in [user](https://developers.arcgis.com/rest/users-groups-and-items/user.htm). Subsequent calls will *not* result in additional web traffic. This is also used internally when a username is required for some requests but is not present in the options.
505
- *
506
- * * ```js
507
- * session.getUsername()
508
- * .then(response => {
509
- * console.log(response); // "casey_jones"
510
- * })
511
- * ```
512
- */
513
- UserSession.prototype.getUsername = function () {
514
- if (this.username) {
515
- return Promise.resolve(this.username);
516
- }
517
- else if (this._user) {
518
- return Promise.resolve(this._user.username);
519
- }
520
- else {
521
- return this.getUser().then(function (user) {
522
- return user.username;
523
- });
524
- }
525
- };
526
- /**
527
- * Gets an appropriate token for the given URL. If `portal` is ArcGIS Online and
528
- * the request is to an ArcGIS Online domain `token` will be used. If the request
529
- * is to the current `portal` the current `token` will also be used. However if
530
- * the request is to an unknown server we will validate the server with a request
531
- * to our current `portal`.
532
- */
533
- UserSession.prototype.getToken = function (url, requestOptions) {
534
- if (federation_utils_1.canUseOnlineToken(this.portal, url)) {
535
- return this.getFreshToken(requestOptions);
536
- }
537
- else if (new RegExp(this.portal, "i").test(url)) {
538
- return this.getFreshToken(requestOptions);
539
- }
540
- else {
541
- return this.getTokenForServer(url, requestOptions);
542
- }
543
- };
544
- /**
545
- * Get application access information for the current user
546
- * see `validateAppAccess` function for details
547
- *
548
- * @param clientId application client id
549
- */
550
- UserSession.prototype.validateAppAccess = function (clientId) {
551
- return this.getToken(this.portal).then(function (token) {
552
- return validate_app_access_1.validateAppAccess(token, clientId);
553
- });
554
- };
555
- UserSession.prototype.toJSON = function () {
556
- return {
557
- clientId: this.clientId,
558
- refreshToken: this.refreshToken,
559
- refreshTokenExpires: this.refreshTokenExpires,
560
- username: this.username,
561
- password: this.password,
562
- token: this.token,
563
- tokenExpires: this.tokenExpires,
564
- portal: this.portal,
565
- ssl: this.ssl,
566
- tokenDuration: this.tokenDuration,
567
- redirectUri: this.redirectUri,
568
- refreshTokenTTL: this.refreshTokenTTL,
569
- };
570
- };
571
- UserSession.prototype.serialize = function () {
572
- return JSON.stringify(this);
573
- };
574
- /**
575
- * For a "Host" app that embeds other platform apps via iframes, after authenticating the user
576
- * and creating a UserSession, the app can then enable "post message" style authentication by calling
577
- * this method.
578
- *
579
- * Internally this adds an event listener on window for the `message` event
580
- *
581
- * @param validChildOrigins Array of origins that are allowed to request authentication from the host app
582
- */
583
- UserSession.prototype.enablePostMessageAuth = function (validChildOrigins, win) {
584
- /* istanbul ignore next: must pass in a mockwindow for tests so we can't cover the other branch */
585
- if (!win && window) {
586
- win = window;
587
- }
588
- this._hostHandler = this.createPostMessageHandler(validChildOrigins);
589
- win.addEventListener("message", this._hostHandler, false);
590
- };
591
- /**
592
- * For a "Host" app that has embedded other platform apps via iframes, when the host needs
593
- * to transition routes, it should call `UserSession.disablePostMessageAuth()` to remove
594
- * the event listener and prevent memory leaks
595
- */
596
- UserSession.prototype.disablePostMessageAuth = function (win) {
597
- /* istanbul ignore next: must pass in a mockwindow for tests so we can't cover the other branch */
598
- if (!win && window) {
599
- win = window;
600
- }
601
- win.removeEventListener("message", this._hostHandler, false);
602
- };
603
- /**
604
- * Manually refreshes the current `token` and `tokenExpires`.
605
- */
606
- UserSession.prototype.refreshSession = function (requestOptions) {
607
- // make sure subsequent calls to getUser() don't returned cached metadata
608
- this._user = null;
609
- if (this.username && this.password) {
610
- return this.refreshWithUsernameAndPassword(requestOptions);
611
- }
612
- if (this.clientId && this.refreshToken) {
613
- return this.refreshWithRefreshToken();
614
- }
615
- return Promise.reject(new arcgis_rest_request_1.ArcGISAuthError("Unable to refresh token."));
616
- };
617
- /**
618
- * Determines the root of the ArcGIS Server or Portal for a given URL.
619
- *
620
- * @param url the URl to determine the root url for.
621
- */
622
- UserSession.prototype.getServerRootUrl = function (url) {
623
- var root = arcgis_rest_request_1.cleanUrl(url).split(/\/rest(\/admin)?\/services(?:\/|#|\?|$)/)[0];
624
- var _a = root.match(/(https?:\/\/)(.+)/), match = _a[0], protocol = _a[1], domainAndPath = _a[2];
625
- var _b = domainAndPath.split("/"), domain = _b[0], path = _b.slice(1);
626
- // only the domain is lowercased because in some cases an org id might be
627
- // in the path which cannot be lowercased.
628
- return "" + protocol + domain.toLowerCase() + "/" + path.join("/");
629
- };
630
- /**
631
- * Returns the proper [`credentials`] option for `fetch` for a given domain.
632
- * See [trusted server](https://enterprise.arcgis.com/en/portal/latest/administer/windows/configure-security.htm#ESRI_SECTION1_70CC159B3540440AB325BE5D89DBE94A).
633
- * Used internally by underlying request methods to add support for specific security considerations.
634
- *
635
- * @param url The url of the request
636
- * @returns "include" or "same-origin"
637
- */
638
- UserSession.prototype.getDomainCredentials = function (url) {
639
- if (!this.trustedDomains || !this.trustedDomains.length) {
640
- return "same-origin";
641
- }
642
- return this.trustedDomains.some(function (domainWithProtocol) {
643
- return url.startsWith(domainWithProtocol);
644
- })
645
- ? "include"
646
- : "same-origin";
647
- };
648
- /**
649
- * Return a function that closes over the validOrigins array and
650
- * can be used as an event handler for the `message` event
651
- *
652
- * @param validOrigins Array of valid origins
653
- */
654
- UserSession.prototype.createPostMessageHandler = function (validOrigins) {
655
- var _this = this;
656
- // return a function that closes over the validOrigins and
657
- // has access to the credential
658
- return function (event) {
659
- // Verify that the origin is valid
660
- // Note: do not use regex's here. validOrigins is an array so we're checking that the event's origin
661
- // is in the array via exact match. More info about avoiding postMessage xss issues here
662
- // https://jlajara.gitlab.io/web/2020/07/17/Dom_XSS_PostMessage_2.html#tipsbypasses-in-postmessage-vulnerabilities
663
- var isValidOrigin = validOrigins.indexOf(event.origin) > -1;
664
- // JSAPI handles this slightly differently - instead of checking a list, it will respond if
665
- // event.origin === window.location.origin || event.origin.endsWith('.arcgis.com')
666
- // For Hub, and to enable cross domain debugging with port's in urls, we are opting to
667
- // use a list of valid origins
668
- // Ensure the message type is something we want to handle
669
- var isValidType = event.data.type === "arcgis:auth:requestCredential";
670
- if (isValidOrigin && isValidType) {
671
- var credential = _this.toCredential();
672
- // the following line allows us to conform to our spec without changing other depended-on functionality
673
- // https://github.com/Esri/arcgis-rest-js/blob/master/packages/arcgis-rest-auth/post-message-auth-spec.md#arcgisauthcredential
674
- credential.server = credential.server.replace("/sharing/rest", "");
675
- event.source.postMessage({
676
- type: "arcgis:auth:credential",
677
- credential: credential,
678
- }, event.origin);
679
- }
680
- };
681
- };
682
- /**
683
- * Validates that a given URL is properly federated with our current `portal`.
684
- * Attempts to use the internal `federatedServers` cache first.
685
- */
686
- UserSession.prototype.getTokenForServer = function (url, requestOptions) {
687
- var _this = this;
688
- // requests to /rest/services/ and /rest/admin/services/ are both valid
689
- // Federated servers may have inconsistent casing, so lowerCase it
690
- var root = this.getServerRootUrl(url);
691
- var existingToken = this.federatedServers[root];
692
- if (existingToken &&
693
- existingToken.expires &&
694
- existingToken.expires.getTime() > Date.now()) {
695
- return Promise.resolve(existingToken.token);
696
- }
697
- if (this._pendingTokenRequests[root]) {
698
- return this._pendingTokenRequests[root];
699
- }
700
- this._pendingTokenRequests[root] = this.fetchAuthorizedDomains().then(function () {
701
- return arcgis_rest_request_1.request(root + "/rest/info", {
702
- credentials: _this.getDomainCredentials(url),
703
- })
704
- .then(function (response) {
705
- if (response.owningSystemUrl) {
706
- /**
707
- * if this server is not owned by this portal
708
- * bail out with an error since we know we wont
709
- * be able to generate a token
710
- */
711
- if (!federation_utils_1.isFederated(response.owningSystemUrl, _this.portal)) {
712
- throw new arcgis_rest_request_1.ArcGISAuthError(url + " is not federated with " + _this.portal + ".", "NOT_FEDERATED");
713
- }
714
- else {
715
- /**
716
- * if the server is federated, use the relevant token endpoint.
717
- */
718
- return arcgis_rest_request_1.request(response.owningSystemUrl + "/sharing/rest/info", requestOptions);
719
- }
720
- }
721
- else if (response.authInfo &&
722
- _this.federatedServers[root] !== undefined) {
723
- /**
724
- * if its a stand-alone instance of ArcGIS Server that doesn't advertise
725
- * federation, but the root server url is recognized, use its built in token endpoint.
726
- */
727
- return Promise.resolve({
728
- authInfo: response.authInfo,
729
- });
730
- }
731
- else {
732
- throw new arcgis_rest_request_1.ArcGISAuthError(url + " is not federated with any portal and is not explicitly trusted.", "NOT_FEDERATED");
733
- }
734
- })
735
- .then(function (response) {
736
- return response.authInfo.tokenServicesUrl;
737
- })
738
- .then(function (tokenServicesUrl) {
739
- // an expired token cant be used to generate a new token
740
- if (_this.token && _this.tokenExpires.getTime() > Date.now()) {
741
- return generate_token_1.generateToken(tokenServicesUrl, {
742
- params: {
743
- token: _this.token,
744
- serverUrl: url,
745
- expiration: _this.tokenDuration,
746
- client: "referer",
747
- },
748
- });
749
- // generate an entirely fresh token if necessary
750
- }
751
- else {
752
- return generate_token_1.generateToken(tokenServicesUrl, {
753
- params: {
754
- username: _this.username,
755
- password: _this.password,
756
- expiration: _this.tokenDuration,
757
- client: "referer",
758
- },
759
- }).then(function (response) {
760
- _this._token = response.token;
761
- _this._tokenExpires = new Date(response.expires);
762
- return response;
763
- });
764
- }
765
- })
766
- .then(function (response) {
767
- _this.federatedServers[root] = {
768
- expires: new Date(response.expires),
769
- token: response.token,
770
- };
771
- delete _this._pendingTokenRequests[root];
772
- return response.token;
773
- });
774
- });
775
- return this._pendingTokenRequests[root];
776
- };
777
- /**
778
- * Returns an unexpired token for the current `portal`.
779
- */
780
- UserSession.prototype.getFreshToken = function (requestOptions) {
781
- var _this = this;
782
- if (this.token && !this.tokenExpires) {
783
- return Promise.resolve(this.token);
784
- }
785
- if (this.token &&
786
- this.tokenExpires &&
787
- this.tokenExpires.getTime() > Date.now()) {
788
- return Promise.resolve(this.token);
789
- }
790
- if (!this._pendingTokenRequests[this.portal]) {
791
- this._pendingTokenRequests[this.portal] = this.refreshSession(requestOptions).then(function (session) {
792
- _this._pendingTokenRequests[_this.portal] = null;
793
- return session.token;
794
- });
795
- }
796
- return this._pendingTokenRequests[this.portal];
797
- };
798
- /**
799
- * Refreshes the current `token` and `tokenExpires` with `username` and
800
- * `password`.
801
- */
802
- UserSession.prototype.refreshWithUsernameAndPassword = function (requestOptions) {
803
- var _this = this;
804
- var options = tslib_1.__assign({ params: {
805
- username: this.username,
806
- password: this.password,
807
- expiration: this.tokenDuration,
808
- } }, requestOptions);
809
- return generate_token_1.generateToken(this.portal + "/generateToken", options).then(function (response) {
810
- _this._token = response.token;
811
- _this._tokenExpires = new Date(response.expires);
812
- return _this;
813
- });
814
- };
815
- /**
816
- * Refreshes the current `token` and `tokenExpires` with `refreshToken`.
817
- */
818
- UserSession.prototype.refreshWithRefreshToken = function (requestOptions) {
819
- var _this = this;
820
- if (this.refreshToken &&
821
- this.refreshTokenExpires &&
822
- this.refreshTokenExpires.getTime() < Date.now()) {
823
- return this.refreshRefreshToken(requestOptions);
824
- }
825
- var options = tslib_1.__assign({ params: {
826
- client_id: this.clientId,
827
- refresh_token: this.refreshToken,
828
- grant_type: "refresh_token",
829
- } }, requestOptions);
830
- return fetch_token_1.fetchToken(this.portal + "/oauth2/token", options).then(function (response) {
831
- _this._token = response.token;
832
- _this._tokenExpires = response.expires;
833
- return _this;
834
- });
835
- };
836
- /**
837
- * Exchanges an unexpired `refreshToken` for a new one, also updates `token` and
838
- * `tokenExpires`.
839
- */
840
- UserSession.prototype.refreshRefreshToken = function (requestOptions) {
841
- var _this = this;
842
- var options = tslib_1.__assign({ params: {
843
- client_id: this.clientId,
844
- refresh_token: this.refreshToken,
845
- redirect_uri: this.redirectUri,
846
- grant_type: "exchange_refresh_token",
847
- } }, requestOptions);
848
- return fetch_token_1.fetchToken(this.portal + "/oauth2/token", options).then(function (response) {
849
- _this._token = response.token;
850
- _this._tokenExpires = response.expires;
851
- _this._refreshToken = response.refreshToken;
852
- _this._refreshTokenExpires = new Date(Date.now() + (_this.refreshTokenTTL - 1) * 60 * 1000);
853
- return _this;
854
- });
855
- };
856
- /**
857
- * ensures that the authorizedCrossOriginDomains are obtained from the portal and cached
858
- * so we can check them later.
859
- *
860
- * @returns this
861
- */
862
- UserSession.prototype.fetchAuthorizedDomains = function () {
863
- var _this = this;
864
- // if this token is for a specific server or we don't have a portal
865
- // don't get the portal info because we cant get the authorizedCrossOriginDomains
866
- if (this.server || !this.portal) {
867
- return Promise.resolve(this);
868
- }
869
- return this.getPortal().then(function (portalInfo) {
870
- /**
871
- * Specific domains can be configured as secure.esri.com or https://secure.esri.com this
872
- * normalizes to https://secure.esri.com so we can use startsWith later.
873
- */
874
- if (portalInfo.authorizedCrossOriginDomains &&
875
- portalInfo.authorizedCrossOriginDomains.length) {
876
- _this.trustedDomains = portalInfo.authorizedCrossOriginDomains
877
- .filter(function (d) { return !d.startsWith("http://"); })
878
- .map(function (d) {
879
- if (d.startsWith("https://")) {
880
- return d;
881
- }
882
- else {
883
- return "https://" + d;
884
- }
885
- });
886
- }
887
- return _this;
888
- });
889
- };
890
- return UserSession;
891
- }());
892
- exports.UserSession = UserSession;
893
- //# sourceMappingURL=UserSession.js.map