@itwin/map-layers-auth 4.3.0-dev.9 → 4.4.0-dev.1

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/CHANGELOG.md CHANGED
@@ -1,6 +1,33 @@
1
1
  # Change Log - @itwin/map-layers-auth
2
2
 
3
- This log was last generated on Mon, 16 Oct 2023 12:52:11 GMT and should not be manually modified.
3
+ This log was last generated on Thu, 30 Nov 2023 17:07:27 GMT and should not be manually modified.
4
+
5
+ ## 4.2.4
6
+ Mon, 20 Nov 2023 16:14:45 GMT
7
+
8
+ _Version update only_
9
+
10
+ ## 4.2.3
11
+ Mon, 06 Nov 2023 14:01:52 GMT
12
+
13
+ _Version update only_
14
+
15
+ ## 4.2.2
16
+ Thu, 02 Nov 2023 15:36:21 GMT
17
+
18
+ ### Updates
19
+
20
+ - Fix legacy token flow for ArcGIS services not supporting Oauth2.
21
+
22
+ ## 4.2.1
23
+ Tue, 24 Oct 2023 15:09:13 GMT
24
+
25
+ _Version update only_
26
+
27
+ ## 4.2.0
28
+ Tue, 17 Oct 2023 15:14:32 GMT
29
+
30
+ _Version update only_
4
31
 
5
32
  ## 4.1.9
6
33
  Tue, 10 Oct 2023 18:48:12 GMT
@@ -98,6 +125,11 @@ Mon, 22 May 2023 15:34:14 GMT
98
125
  - Update to eslint@8
99
126
  - Upgrade TypeScript compile target to es2021.
100
127
 
128
+ ## 3.7.17
129
+ Mon, 20 Nov 2023 18:24:23 GMT
130
+
131
+ _Version update only_
132
+
101
133
  ## 3.7.16
102
134
  Mon, 16 Oct 2023 12:49:08 GMT
103
135
 
@@ -35,6 +35,8 @@ export declare class ArcGisAccessClient implements MapLayerAccessClient {
35
35
  private initOauthCallbackFunction;
36
36
  unInitialize(): void;
37
37
  getAccessToken(params: MapLayerAccessTokenParams): Promise<MapLayerAccessToken | undefined>;
38
+ /** @internal */
39
+ static validateOAuth2Endpoint(endpointUrl: string): Promise<boolean>;
38
40
  getTokenServiceEndPoint(mapLayerUrl: string): Promise<MapLayerTokenEndpoint | undefined>;
39
41
  invalidateToken(token: MapLayerAccessToken): boolean;
40
42
  get redirectUri(): string | undefined;
@@ -47,8 +49,7 @@ export declare class ArcGisAccessClient implements MapLayerAccessClient {
47
49
  removeEnterpriseClientId(clientId: ArcGisEnterpriseClientId): void;
48
50
  /** @internal */
49
51
  private getOAuthTokenForMapLayerUrl;
50
- private _oauthAuthorizeEndPointsCache;
51
- private _oauthTokenEndPointsCache;
52
+ private _endPointsCache;
52
53
  /**
53
54
  * Get OAuth2 endpoint that must be cause to get the Oauth2 token
54
55
  * @internal
@@ -64,6 +65,7 @@ export declare class ArcGisAccessClient implements MapLayerAccessClient {
64
65
  * @internal
65
66
  */
66
67
  private isArcGisHostValid;
68
+ private validateEndpointUrl;
67
69
  /**
68
70
  * Get OAuth2 endpoint that must be cause to get the Oauth2 token
69
71
  * @internal
@@ -1 +1 @@
1
- {"version":3,"file":"ArcGisAccessClient.d.ts","sourceRoot":"","sources":["../../../src/ArcGis/ArcGisAccessClient.ts"],"names":[],"mappings":"AAIA;;GAEG;AAEH,OAAO,EAAU,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,yBAAyB,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAMnI,YAAY;AACZ,MAAM,WAAW,wBAAwB;IAGvC,cAAc,EAAE,MAAM,CAAC;IAGvB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,YAAY;AACZ,MAAM,WAAW,oBAAoB;IAEnC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAG9B,mBAAmB,CAAC,EAAE,wBAAwB,EAAE,CAAC;CAClD;AAED;;;;EAIE;AACF,MAAM,WAAW,iBAAiB;IAIhC,WAAW,EAAE,MAAM,CAAC;IAGpB,eAAe,CAAC,EAAE,MAAM,CAAC;IAGzB,SAAS,EAAE,oBAAoB,CAAC;CACjC;AAED,YAAY;AACZ,qBAAa,kBAAmB,YAAW,oBAAoB;IAC7D,SAAgB,iBAAiB,kDAAiB;IAClD,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,WAAW,CAAqB;IACxC,OAAO,CAAC,UAAU,CAAmC;IAGrD,OAAO,CAAC,iBAAiB,CAAS;;IAK3B,UAAU,CAAC,WAAW,CAAC,EAAE,iBAAiB,GAAG,OAAO;IAW3D,OAAO,CAAC,yBAAyB;IAoC1B,YAAY;IAMN,cAAc,CAAC,MAAM,EAAE,yBAAyB,GAAG,OAAO,CAAC,mBAAmB,GAAG,SAAS,CAAC;IAgB3F,uBAAuB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,GAAG,SAAS,CAAC;IAkB9F,eAAe,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO;IAQ3D,IAAW,WAAW,uBAErB;IAEM,6BAA6B,CAAC,GAAG,EAAE,MAAM;IA0BhD,IAAW,UAAU,uBAEpB;IAED,IAAW,oBAAoB,IAIW,MAAM,GAAG,SAAS,CAF3D;IAED,IAAW,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAK3D;IAED,IAAW,yBAAyB,2CAEnC;IAEM,qBAAqB,CAAC,cAAc,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;IAiB9D,wBAAwB,CAAC,QAAQ,EAAE,wBAAwB;IASlE,gBAAgB;YACF,2BAA2B;IAczC,OAAO,CAAC,6BAA6B,CAA0B;IAC/D,OAAO,CAAC,yBAAyB,CAA0B;IAE3D;;;KAGC;IACD,OAAO,CAAC,aAAa;IAQrB;;;KAGC;YACa,cAAc;IAO5B;;;MAGE;IACF,OAAO,CAAC,iBAAiB;IAQzB;;;KAGC;YACa,iBAAiB;IAmD/B;;;KAGC;IACD,OAAO,CAAC,iBAAiB;CA8B1B"}
1
+ {"version":3,"file":"ArcGisAccessClient.d.ts","sourceRoot":"","sources":["../../../src/ArcGis/ArcGisAccessClient.ts"],"names":[],"mappings":"AAIA;;GAEG;AAEH,OAAO,EAAU,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,yBAAyB,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAMnI,YAAY;AACZ,MAAM,WAAW,wBAAwB;IAGvC,cAAc,EAAE,MAAM,CAAC;IAGvB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,YAAY;AACZ,MAAM,WAAW,oBAAoB;IAEnC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAG9B,mBAAmB,CAAC,EAAE,wBAAwB,EAAE,CAAC;CAClD;AAED;;;;EAIE;AACF,MAAM,WAAW,iBAAiB;IAIhC,WAAW,EAAE,MAAM,CAAC;IAGpB,eAAe,CAAC,EAAE,MAAM,CAAC;IAGzB,SAAS,EAAE,oBAAoB,CAAC;CACjC;AASD,YAAY;AACZ,qBAAa,kBAAmB,YAAW,oBAAoB;IAC7D,SAAgB,iBAAiB,kDAAiB;IAClD,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,WAAW,CAAqB;IACxC,OAAO,CAAC,UAAU,CAAmC;IAGrD,OAAO,CAAC,iBAAiB,CAAS;;IAK3B,UAAU,CAAC,WAAW,CAAC,EAAE,iBAAiB,GAAG,OAAO;IAW3D,OAAO,CAAC,yBAAyB;IAoC1B,YAAY;IAMN,cAAc,CAAC,MAAM,EAAE,yBAAyB,GAAG,OAAO,CAAC,mBAAmB,GAAG,SAAS,CAAC;IAgBxG,gBAAgB;WACI,sBAAsB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKpE,uBAAuB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,GAAG,SAAS,CAAC;IAQ9F,eAAe,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO;IAQ3D,IAAW,WAAW,uBAErB;IAEM,6BAA6B,CAAC,GAAG,EAAE,MAAM;IA0BhD,IAAW,UAAU,uBAEpB;IAED,IAAW,oBAAoB,IAIW,MAAM,GAAG,SAAS,CAF3D;IAED,IAAW,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAK3D;IAED,IAAW,yBAAyB,2CAEnC;IAEM,qBAAqB,CAAC,cAAc,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;IAiB9D,wBAAwB,CAAC,QAAQ,EAAE,wBAAwB;IASlE,gBAAgB;YACF,2BAA2B;IAezC,OAAO,CAAC,eAAe,CAA+C;IAEtE;;;KAGC;IACD,OAAO,CAAC,aAAa;IAKrB;;;KAGC;YACa,cAAc;IAO5B;;;MAGE;IACF,OAAO,CAAC,iBAAiB;YAQX,mBAAmB;IAYjC;;;KAGC;YACa,iBAAiB;IA8D/B;;;KAGC;IACD,OAAO,CAAC,iBAAiB;CA8B1B"}
@@ -19,11 +19,10 @@ class ArcGisAccessClient {
19
19
  this.onOAuthProcessEnd = new core_bentley_1.BeEvent();
20
20
  // Should be kept to 'false'. Debugging purposes only.
21
21
  this._forceLegacyToken = false;
22
- // Derive the Oauth URL from a typical MapLayerURL
22
+ // Mapping between a map-layer URL and its corresponding Oauth endpoint
23
23
  // i.e. https://hostname/server/rest/services/NewYork/NewYork3857/MapServer
24
24
  // => https://hostname/portal/sharing/oauth2/authorize
25
- this._oauthAuthorizeEndPointsCache = new Map();
26
- this._oauthTokenEndPointsCache = new Map();
25
+ this._endPointsCache = new Map();
27
26
  }
28
27
  initialize(oAuthConfig) {
29
28
  if (oAuthConfig) {
@@ -84,20 +83,16 @@ class ArcGisAccessClient {
84
83
  }
85
84
  return undefined;
86
85
  }
86
+ /** @internal */
87
+ static async validateOAuth2Endpoint(endpointUrl) {
88
+ const data = await fetch(endpointUrl, { method: "GET" });
89
+ return data.status === 400; // Oauth2 API returns 400 (Bad Request) when there are missing parameters
90
+ }
87
91
  async getTokenServiceEndPoint(mapLayerUrl) {
88
- let tokenEndpoint;
89
92
  if (!this._forceLegacyToken) {
90
- // Note: we used to validate the endpoint by making a request, but because of CORS isssues with some servers
91
- // we could not make a reliable validation.
92
- try {
93
- tokenEndpoint = await this.getOAuth2Endpoint(mapLayerUrl, ArcGisOAuth2Endpoint_1.ArcGisOAuth2EndpointType.Authorize);
94
- if (tokenEndpoint) {
95
- }
96
- }
97
- catch {
98
- }
93
+ return this.getOAuth2Endpoint(mapLayerUrl, ArcGisOAuth2Endpoint_1.ArcGisOAuth2EndpointType.Authorize);
99
94
  }
100
- return tokenEndpoint;
95
+ return undefined;
101
96
  }
102
97
  invalidateToken(token) {
103
98
  let found = ArcGisTokenManager_1.ArcGisTokenManager.invalidateToken(token);
@@ -187,22 +182,18 @@ class ArcGisAccessClient {
187
182
  * Get OAuth2 endpoint that must be cause to get the Oauth2 token
188
183
  * @internal
189
184
  */
190
- cacheEndpoint(url, endpoint, obj) {
191
- if (endpoint === ArcGisOAuth2Endpoint_1.ArcGisOAuth2EndpointType.Authorize) {
192
- this._oauthAuthorizeEndPointsCache.set(url, obj);
193
- }
194
- else {
195
- this._oauthTokenEndPointsCache.set(url, obj);
196
- }
185
+ cacheEndpoint(url, endpointType, endPoint) {
186
+ const entry = endpointType === ArcGisOAuth2Endpoint_1.ArcGisOAuth2EndpointType.Authorize ? { authorizeEndpoint: endPoint } : { tokenEndpoint: endPoint };
187
+ this._endPointsCache.set(url, entry);
197
188
  }
198
189
  /**
199
190
  * Get OAuth2 endpoint that must be cause to get the Oauth2 token
200
191
  * @internal
201
192
  */
202
- async createEndpoint(url, endpoint) {
193
+ async createEndpoint(mapLayerUrl, oauthEndpointUrl, endpointType) {
203
194
  // Validate the URL we just composed
204
- const oauthEndpoint = new ArcGisOAuth2Endpoint_1.ArcGisOAuth2Endpoint(url, this.constructLoginUrl(url, false), false);
205
- this.cacheEndpoint(url, endpoint, oauthEndpoint);
195
+ const oauthEndpoint = new ArcGisOAuth2Endpoint_1.ArcGisOAuth2Endpoint(oauthEndpointUrl, this.constructLoginUrl(oauthEndpointUrl, false), false);
196
+ this.cacheEndpoint(mapLayerUrl, endpointType, oauthEndpoint);
206
197
  return oauthEndpoint;
207
198
  }
208
199
  /**
@@ -215,18 +206,30 @@ class ArcGisAccessClient {
215
206
  ];
216
207
  return allowedHosts.some((host) => url.hostname.toLowerCase().endsWith(host));
217
208
  }
209
+ async validateEndpointUrl(url) {
210
+ let valid;
211
+ try {
212
+ valid = await ArcGisAccessClient.validateOAuth2Endpoint(url.toString());
213
+ }
214
+ catch {
215
+ // If we reach here, this means we could not validate properly the endpoint;
216
+ // we cannot conclude the endpoint is invalid though; it might happen endpoint doesn't support CORS requests,
217
+ // but still valid for Oauth process.
218
+ }
219
+ return valid;
220
+ }
218
221
  /**
219
222
  * Get OAuth2 endpoint that must be cause to get the Oauth2 token
220
223
  * @internal
221
224
  */
222
- async getOAuth2Endpoint(url, endpointType) {
225
+ async getOAuth2Endpoint(mapLayerUrl, endpointType) {
223
226
  // Return from cache if available
224
- const cachedEndpoint = (endpointType === ArcGisOAuth2Endpoint_1.ArcGisOAuth2EndpointType.Authorize ? this._oauthAuthorizeEndPointsCache.get(url) : this._oauthTokenEndPointsCache.get(url));
227
+ const cachedEndpoint = this._endPointsCache.get(mapLayerUrl);
225
228
  if (cachedEndpoint !== undefined) {
226
- return cachedEndpoint;
229
+ return (endpointType === ArcGisOAuth2Endpoint_1.ArcGisOAuth2EndpointType.Authorize ? cachedEndpoint.authorizeEndpoint : cachedEndpoint.authorizeEndpoint);
227
230
  }
228
231
  const endpointStr = (endpointType === ArcGisOAuth2Endpoint_1.ArcGisOAuth2EndpointType.Authorize ? "authorize" : "token");
229
- const urlObj = new URL(url);
232
+ const urlObj = new URL(mapLayerUrl);
230
233
  if (this.isArcGisHostValid(urlObj)) {
231
234
  // ArcGIS Online (fixed)
232
235
  // Doc: https://developers.arcgis.com/documentation/mapping-apis-and-services/security/oauth-2.0/
@@ -243,24 +246,34 @@ class ArcGisAccessClient {
243
246
  if (restUrlFromTokenService === undefined) {
244
247
  // We could not derive the token endpoint from 'tokenServicesUrl'.
245
248
  // ArcGIS Enterprise Format https://<host>:<port>/<subdirectory>/sharing/rest/oauth2/authorize
246
- const regExMatch = url.match(new RegExp(/([^&\/]+)\/rest\/services\/.*/, "i"));
249
+ const regExMatch = mapLayerUrl.match(new RegExp(/([^&\/]+)\/rest\/services\/.*/, "i"));
247
250
  if (regExMatch !== null && regExMatch.length >= 2) {
248
251
  const subdirectory = regExMatch[1];
249
252
  const port = (urlObj.port !== "80" && urlObj.port !== "443") ? `:${urlObj.port}` : "";
250
253
  const newUrlObj = new URL(`${urlObj.protocol}//${urlObj.hostname}${port}/${subdirectory}/sharing/rest/oauth2/${endpointStr}`);
251
254
  // Check again the URL we just composed
252
- return await this.createEndpoint(newUrlObj.toString(), endpointType);
255
+ const isValidUrl = await this.validateEndpointUrl(newUrlObj.toString());
256
+ if (isValidUrl === undefined || isValidUrl) {
257
+ const endpoint = await this.createEndpoint(mapLayerUrl, newUrlObj.toString(), endpointType);
258
+ if (endpoint)
259
+ return endpoint;
260
+ }
253
261
  }
254
262
  }
255
263
  else {
256
- const endpoint = await this.createEndpoint(`${restUrlFromTokenService.toString()}oauth2/${endpointStr}`, endpointType);
257
- if (endpoint)
258
- return endpoint;
264
+ const isValidUrl = await this.validateEndpointUrl(restUrlFromTokenService.toString());
265
+ if (isValidUrl === undefined || isValidUrl) {
266
+ const endpoint = await this.createEndpoint(mapLayerUrl, `${restUrlFromTokenService.toString()}oauth2/${endpointStr}`, endpointType);
267
+ if (endpoint)
268
+ return endpoint;
269
+ }
259
270
  }
260
271
  }
261
272
  catch {
262
273
  }
263
274
  }
275
+ // If we reach here, we were not successful creating an endpoint
276
+ this._endPointsCache.set(mapLayerUrl, {}); // Cache an empty entry, and avoid making repeated failing requests.
264
277
  return undefined; // we could not find any valid oauth2 endpoint
265
278
  }
266
279
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"ArcGisAccessClient.js","sourceRoot":"","sources":["../../../src/ArcGis/ArcGisAccessClient.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n/** @packageDocumentation\r\n * @module Tiles\r\n */\r\n\r\nimport { assert, BeEvent } from \"@itwin/core-bentley\";\r\nimport { MapLayerAccessClient, MapLayerAccessToken, MapLayerAccessTokenParams, MapLayerTokenEndpoint } from \"@itwin/core-frontend\";\r\nimport { ArcGisOAuth2Token, ArcGisTokenClientType } from \"./ArcGisTokenGenerator\";\r\nimport { ArcGisOAuth2Endpoint, ArcGisOAuth2EndpointType } from \"./ArcGisOAuth2Endpoint\";\r\nimport { ArcGisTokenManager } from \"./ArcGisTokenManager\";\r\nimport { ArcGisUrl } from \"./ArcGisUrl\";\r\n\r\n/** @beta */\r\nexport interface ArcGisEnterpriseClientId {\r\n /* Oauth API endpoint base URL (i.e. https://hostname/portal/sharing/oauth2/authorize)\r\n used to identify uniquely each enterprise server. */\r\n serviceBaseUrl: string;\r\n\r\n /* Application's clientId for this enterprise server.*/\r\n clientId: string;\r\n}\r\n\r\n/** @beta */\r\nexport interface ArcGisOAuthClientIds {\r\n /* Application's OAuth clientId in ArcGIS online */\r\n arcgisOnlineClientId?: string;\r\n\r\n /* Application's OAuth clientId for each enterprise server used. */\r\n enterpriseClientIds?: ArcGisEnterpriseClientId[];\r\n}\r\n\r\n/** @beta\r\n * ArcGIS OAuth configurations parameters.\r\n * See https://developers.arcgis.com/documentation/mapping-apis-and-services/security/arcgis-identity/serverless-web-apps/\r\n * more details.\r\n*/\r\nexport interface ArcGisOAuthConfig {\r\n /* URL to which a user is sent once they complete sign in authorization.\r\n Must match a URI you define in the developer dashboard, otherwise, the authorization will be rejected.\r\n */\r\n redirectUri: string;\r\n\r\n /* Optional expiration after which the token will expire. Defined in minutes with a maximum of two weeks (20160 minutes)*/\r\n tokenExpiration?: number;\r\n\r\n /* Application client Ids */\r\n clientIds: ArcGisOAuthClientIds;\r\n}\r\n\r\n/** @beta */\r\nexport class ArcGisAccessClient implements MapLayerAccessClient {\r\n public readonly onOAuthProcessEnd = new BeEvent();\r\n private _redirectUri: string | undefined;\r\n private _expiration: number | undefined;\r\n private _clientIds: ArcGisOAuthClientIds | undefined;\r\n\r\n // Should be kept to 'false'. Debugging purposes only.\r\n private _forceLegacyToken = false;\r\n\r\n public constructor() {\r\n }\r\n\r\n public initialize(oAuthConfig?: ArcGisOAuthConfig): boolean {\r\n if (oAuthConfig) {\r\n this._redirectUri = oAuthConfig.redirectUri;\r\n this._expiration = oAuthConfig.tokenExpiration;\r\n this._clientIds = oAuthConfig.clientIds;\r\n\r\n this.initOauthCallbackFunction();\r\n }\r\n return true;\r\n }\r\n\r\n private initOauthCallbackFunction() {\r\n (window as any).arcGisOAuth2Callback = (redirectLocation?: Location) => {\r\n let eventSuccess = false;\r\n let stateData;\r\n\r\n if (redirectLocation && redirectLocation.hash.length > 0) {\r\n const locationHash = redirectLocation.hash;\r\n const hashParams = new URLSearchParams(locationHash.substring(1));\r\n const token = hashParams.get(\"access_token\") ?? undefined;\r\n const expiresInStr = hashParams.get(\"expires_in\") ?? undefined;\r\n const userName = hashParams.get(\"username\") ?? undefined;\r\n const ssl = hashParams.get(\"ssl\") === \"true\";\r\n const stateStr = hashParams.get(\"state\") ?? undefined;\r\n const persist = hashParams.get(\"persist\") === \"true\";\r\n if (token !== undefined && expiresInStr !== undefined && userName !== undefined && ssl !== undefined && stateStr !== undefined) {\r\n let endpointOrigin;\r\n try {\r\n const state = JSON.parse(stateStr);\r\n stateData = state?.customData;\r\n endpointOrigin = state?.endpointOrigin;\r\n\r\n } catch {\r\n }\r\n const expiresIn = Number(expiresInStr);\r\n const expiresAt = (expiresIn * 1000) + (+new Date()); // Converts the token expiration delay (seconds) into a timestamp (UNIX time)\r\n if (endpointOrigin !== undefined) {\r\n ArcGisTokenManager.setOAuth2Token(endpointOrigin, { token, expiresAt, ssl, userName, persist });\r\n eventSuccess = true;\r\n }\r\n\r\n }\r\n }\r\n this.onOAuthProcessEnd.raiseEvent(eventSuccess, stateData);\r\n };\r\n }\r\n\r\n public unInitialize() {\r\n this._redirectUri = undefined;\r\n this._expiration = undefined;\r\n (window as any).arcGisOAuth2Callback = undefined;\r\n }\r\n\r\n public async getAccessToken(params: MapLayerAccessTokenParams): Promise<MapLayerAccessToken | undefined> {\r\n // First lookup Oauth2 tokens, otherwise check try \"legacy tokens\" if credentials were provided\r\n\r\n if (!this._forceLegacyToken) {\r\n const oauth2Token = await this.getOAuthTokenForMapLayerUrl(params.mapLayerUrl.toString());\r\n if (oauth2Token)\r\n return oauth2Token;\r\n }\r\n\r\n if (params.userName && params.password) {\r\n return ArcGisTokenManager.getToken(params.mapLayerUrl.toString(), params.userName, params.password, { client: ArcGisTokenClientType.referer });\r\n }\r\n\r\n return undefined;\r\n }\r\n\r\n public async getTokenServiceEndPoint(mapLayerUrl: string): Promise<MapLayerTokenEndpoint | undefined> {\r\n let tokenEndpoint: ArcGisOAuth2Endpoint | undefined;\r\n if (!this._forceLegacyToken) {\r\n // Note: we used to validate the endpoint by making a request, but because of CORS isssues with some servers\r\n // we could not make a reliable validation.\r\n try {\r\n tokenEndpoint = await this.getOAuth2Endpoint(mapLayerUrl, ArcGisOAuth2EndpointType.Authorize);\r\n if (tokenEndpoint) {\r\n\r\n }\r\n } catch {\r\n\r\n }\r\n }\r\n\r\n return tokenEndpoint;\r\n }\r\n\r\n public invalidateToken(token: MapLayerAccessToken): boolean {\r\n let found = ArcGisTokenManager.invalidateToken(token);\r\n if (!found) {\r\n found = ArcGisTokenManager.invalidateOAuth2Token(token);\r\n }\r\n return found;\r\n }\r\n\r\n public get redirectUri() {\r\n return this._redirectUri;\r\n }\r\n\r\n public getMatchingEnterpriseClientId(url: string) {\r\n const clientIds = this.arcGisEnterpriseClientIds;\r\n if (!clientIds) {\r\n return undefined;\r\n }\r\n\r\n let clientId: string | undefined;\r\n let defaultClientId: string | undefined;\r\n for (const entry of clientIds) {\r\n if (entry.serviceBaseUrl === \"\") {\r\n defaultClientId = entry.clientId;\r\n } else {\r\n if (url.toLowerCase().startsWith(entry.serviceBaseUrl)) {\r\n clientId = entry.clientId;\r\n }\r\n }\r\n }\r\n\r\n // If we could not find a match with serviceBaseUrl, and a default clientId\r\n // was specified (i.e empty url), then use default clientId\r\n if (clientId === undefined && defaultClientId !== undefined) {\r\n clientId = defaultClientId;\r\n }\r\n return clientId;\r\n }\r\n\r\n public get expiration() {\r\n return this._expiration;\r\n }\r\n\r\n public get arcGisOnlineClientId() {\r\n return this._clientIds?.arcgisOnlineClientId;\r\n }\r\n\r\n public set arcGisOnlineClientId(clientId: string | undefined) {\r\n if (this._clientIds === undefined) {\r\n this._clientIds = { arcgisOnlineClientId: clientId };\r\n }\r\n this._clientIds.arcgisOnlineClientId = clientId;\r\n }\r\n\r\n public get arcGisEnterpriseClientIds() {\r\n return this._clientIds?.enterpriseClientIds;\r\n }\r\n\r\n public setEnterpriseClientId(serviceBaseUrl: string, clientId: string) {\r\n\r\n if (this._clientIds?.enterpriseClientIds) {\r\n const foundIdx = this._clientIds.enterpriseClientIds.findIndex((entry) => entry.serviceBaseUrl === serviceBaseUrl);\r\n if (foundIdx !== -1) {\r\n this._clientIds.enterpriseClientIds[foundIdx].clientId = clientId;\r\n } else {\r\n this._clientIds.enterpriseClientIds.push({ serviceBaseUrl, clientId });\r\n }\r\n } else {\r\n if (this._clientIds === undefined) {\r\n this._clientIds = {};\r\n }\r\n this._clientIds.enterpriseClientIds = [{ serviceBaseUrl, clientId }];\r\n }\r\n }\r\n\r\n public removeEnterpriseClientId(clientId: ArcGisEnterpriseClientId) {\r\n\r\n if (this._clientIds?.enterpriseClientIds) {\r\n this._clientIds.enterpriseClientIds = this._clientIds?.enterpriseClientIds?.filter((item) => item.serviceBaseUrl !== clientId.serviceBaseUrl);\r\n }\r\n\r\n }\r\n\r\n /// //////////\r\n /** @internal */\r\n private async getOAuthTokenForMapLayerUrl(mapLayerUrl: string): Promise<ArcGisOAuth2Token | undefined> {\r\n try {\r\n const oauthEndpoint = await this.getOAuth2Endpoint(mapLayerUrl, ArcGisOAuth2EndpointType.Authorize);\r\n if (oauthEndpoint !== undefined) {\r\n const oauthEndpointUrl = new URL(oauthEndpoint.getUrl());\r\n return ArcGisTokenManager.getOAuth2Token(oauthEndpointUrl.origin);\r\n }\r\n } catch { }\r\n return undefined;\r\n }\r\n\r\n // Derive the Oauth URL from a typical MapLayerURL\r\n // i.e. \t https://hostname/server/rest/services/NewYork/NewYork3857/MapServer\r\n // => https://hostname/portal/sharing/oauth2/authorize\r\n private _oauthAuthorizeEndPointsCache = new Map<string, any>();\r\n private _oauthTokenEndPointsCache = new Map<string, any>();\r\n\r\n /**\r\n * Get OAuth2 endpoint that must be cause to get the Oauth2 token\r\n * @internal\r\n */\r\n private cacheEndpoint(url: string, endpoint: ArcGisOAuth2EndpointType, obj: ArcGisOAuth2Endpoint) {\r\n if (endpoint === ArcGisOAuth2EndpointType.Authorize) {\r\n this._oauthAuthorizeEndPointsCache.set(url, obj);\r\n } else {\r\n this._oauthTokenEndPointsCache.set(url, obj);\r\n }\r\n }\r\n\r\n /**\r\n * Get OAuth2 endpoint that must be cause to get the Oauth2 token\r\n * @internal\r\n */\r\n private async createEndpoint(url: string, endpoint: ArcGisOAuth2EndpointType): Promise<ArcGisOAuth2Endpoint | undefined> {\r\n // Validate the URL we just composed\r\n const oauthEndpoint = new ArcGisOAuth2Endpoint(url, this.constructLoginUrl(url, false), false);\r\n this.cacheEndpoint(url, endpoint, oauthEndpoint);\r\n return oauthEndpoint;\r\n }\r\n\r\n /**\r\n * Returns whether the ArcGis host is valid\r\n * @internal\r\n */\r\n private isArcGisHostValid(url: URL): boolean {\r\n const allowedHosts = [\r\n \"arcgis.com\",\r\n ];\r\n\r\n return allowedHosts.some((host: string) => url.hostname.toLowerCase().endsWith(host));\r\n }\r\n\r\n /**\r\n * Get OAuth2 endpoint that must be cause to get the Oauth2 token\r\n * @internal\r\n */\r\n private async getOAuth2Endpoint(url: string, endpointType: ArcGisOAuth2EndpointType): Promise<ArcGisOAuth2Endpoint | undefined> {\r\n // Return from cache if available\r\n const cachedEndpoint = (endpointType === ArcGisOAuth2EndpointType.Authorize ? this._oauthAuthorizeEndPointsCache.get(url) : this._oauthTokenEndPointsCache.get(url));\r\n if (cachedEndpoint !== undefined) {\r\n return cachedEndpoint;\r\n }\r\n\r\n const endpointStr = (endpointType === ArcGisOAuth2EndpointType.Authorize ? \"authorize\" : \"token\");\r\n\r\n const urlObj = new URL(url);\r\n\r\n if (this.isArcGisHostValid(urlObj)) {\r\n // ArcGIS Online (fixed)\r\n // Doc: https://developers.arcgis.com/documentation/mapping-apis-and-services/security/oauth-2.0/\r\n\r\n if (this.arcGisOnlineClientId === undefined) {\r\n return undefined;\r\n }\r\n\r\n const oauth2Url = `https://www.arcgis.com/sharing/rest/oauth2/${endpointStr}`;\r\n return new ArcGisOAuth2Endpoint(oauth2Url, this.constructLoginUrl(oauth2Url, true), true);\r\n } else {\r\n\r\n // First attempt: derive the Oauth2 token URL from the 'tokenServicesUrl', exposed by the 'info request'\r\n try {\r\n const restUrlFromTokenService = await ArcGisUrl.getRestUrlFromGenerateTokenUrl(urlObj);\r\n if (restUrlFromTokenService === undefined) {\r\n // We could not derive the token endpoint from 'tokenServicesUrl'.\r\n // ArcGIS Enterprise Format https://<host>:<port>/<subdirectory>/sharing/rest/oauth2/authorize\r\n const regExMatch = url.match(new RegExp(/([^&\\/]+)\\/rest\\/services\\/.*/, \"i\"));\r\n if (regExMatch !== null && regExMatch.length >= 2) {\r\n const subdirectory = regExMatch[1];\r\n const port = (urlObj.port !== \"80\" && urlObj.port !== \"443\") ? `:${urlObj.port}` : \"\";\r\n const newUrlObj = new URL(`${urlObj.protocol}//${urlObj.hostname}${port}/${subdirectory}/sharing/rest/oauth2/${endpointStr}`);\r\n\r\n // Check again the URL we just composed\r\n return await this.createEndpoint(newUrlObj.toString(), endpointType);\r\n }\r\n } else {\r\n const endpoint = await this.createEndpoint(`${restUrlFromTokenService.toString()}oauth2/${endpointStr}`, endpointType);\r\n if (endpoint)\r\n return endpoint;\r\n }\r\n } catch {\r\n\r\n }\r\n\r\n }\r\n return undefined; // we could not find any valid oauth2 endpoint\r\n }\r\n\r\n /**\r\n * Construct the complete Authorize url to starts the Oauth process\r\n * @internal\r\n */\r\n private constructLoginUrl(url: string, isArcgisOnline: boolean) {\r\n const urlObj = new URL(url);\r\n\r\n // Set the client id\r\n if (isArcgisOnline) {\r\n const clientId = this.arcGisOnlineClientId;\r\n assert(clientId !== undefined);\r\n if (clientId !== undefined) {\r\n urlObj.searchParams.set(\"client_id\", clientId);\r\n }\r\n\r\n } else {\r\n const clientId = this.getMatchingEnterpriseClientId(url);\r\n assert(clientId !== undefined);\r\n if (undefined !== clientId) {\r\n urlObj.searchParams.set(\"client_id\", clientId);\r\n }\r\n }\r\n\r\n urlObj.searchParams.set(\"response_type\", \"token\");\r\n if (this.expiration !== undefined) {\r\n urlObj.searchParams.set(\"expiration\", `${this.expiration}`);\r\n }\r\n\r\n if (this.redirectUri)\r\n urlObj.searchParams.set(\"redirect_uri\", this.redirectUri);\r\n\r\n return urlObj.toString();\r\n }\r\n\r\n}\r\n"]}
1
+ {"version":3,"file":"ArcGisAccessClient.js","sourceRoot":"","sources":["../../../src/ArcGis/ArcGisAccessClient.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n/** @packageDocumentation\r\n * @module Tiles\r\n */\r\n\r\nimport { assert, BeEvent } from \"@itwin/core-bentley\";\r\nimport { MapLayerAccessClient, MapLayerAccessToken, MapLayerAccessTokenParams, MapLayerTokenEndpoint } from \"@itwin/core-frontend\";\r\nimport { ArcGisOAuth2Token, ArcGisTokenClientType } from \"./ArcGisTokenGenerator\";\r\nimport { ArcGisOAuth2Endpoint, ArcGisOAuth2EndpointType } from \"./ArcGisOAuth2Endpoint\";\r\nimport { ArcGisTokenManager } from \"./ArcGisTokenManager\";\r\nimport { ArcGisUrl } from \"./ArcGisUrl\";\r\n\r\n/** @beta */\r\nexport interface ArcGisEnterpriseClientId {\r\n /* Oauth API endpoint base URL (i.e. https://hostname/portal/sharing/oauth2/authorize)\r\n used to identify uniquely each enterprise server. */\r\n serviceBaseUrl: string;\r\n\r\n /* Application's clientId for this enterprise server.*/\r\n clientId: string;\r\n}\r\n\r\n/** @beta */\r\nexport interface ArcGisOAuthClientIds {\r\n /* Application's OAuth clientId in ArcGIS online */\r\n arcgisOnlineClientId?: string;\r\n\r\n /* Application's OAuth clientId for each enterprise server used. */\r\n enterpriseClientIds?: ArcGisEnterpriseClientId[];\r\n}\r\n\r\n/** @beta\r\n * ArcGIS OAuth configurations parameters.\r\n * See https://developers.arcgis.com/documentation/mapping-apis-and-services/security/arcgis-identity/serverless-web-apps/\r\n * more details.\r\n*/\r\nexport interface ArcGisOAuthConfig {\r\n /* URL to which a user is sent once they complete sign in authorization.\r\n Must match a URI you define in the developer dashboard, otherwise, the authorization will be rejected.\r\n */\r\n redirectUri: string;\r\n\r\n /* Optional expiration after which the token will expire. Defined in minutes with a maximum of two weeks (20160 minutes)*/\r\n tokenExpiration?: number;\r\n\r\n /* Application client Ids */\r\n clientIds: ArcGisOAuthClientIds;\r\n}\r\n\r\ninterface EndPointsCacheEntry {\r\n authorizeEndpoint?: ArcGisOAuth2Endpoint;\r\n tokenEndpoint?: ArcGisOAuth2Endpoint;\r\n}\r\n\r\ntype MapLayerUrl = string;\r\n\r\n/** @beta */\r\nexport class ArcGisAccessClient implements MapLayerAccessClient {\r\n public readonly onOAuthProcessEnd = new BeEvent();\r\n private _redirectUri: string | undefined;\r\n private _expiration: number | undefined;\r\n private _clientIds: ArcGisOAuthClientIds | undefined;\r\n\r\n // Should be kept to 'false'. Debugging purposes only.\r\n private _forceLegacyToken = false;\r\n\r\n public constructor() {\r\n }\r\n\r\n public initialize(oAuthConfig?: ArcGisOAuthConfig): boolean {\r\n if (oAuthConfig) {\r\n this._redirectUri = oAuthConfig.redirectUri;\r\n this._expiration = oAuthConfig.tokenExpiration;\r\n this._clientIds = oAuthConfig.clientIds;\r\n\r\n this.initOauthCallbackFunction();\r\n }\r\n return true;\r\n }\r\n\r\n private initOauthCallbackFunction() {\r\n (window as any).arcGisOAuth2Callback = (redirectLocation?: Location) => {\r\n let eventSuccess = false;\r\n let stateData;\r\n\r\n if (redirectLocation && redirectLocation.hash.length > 0) {\r\n const locationHash = redirectLocation.hash;\r\n const hashParams = new URLSearchParams(locationHash.substring(1));\r\n const token = hashParams.get(\"access_token\") ?? undefined;\r\n const expiresInStr = hashParams.get(\"expires_in\") ?? undefined;\r\n const userName = hashParams.get(\"username\") ?? undefined;\r\n const ssl = hashParams.get(\"ssl\") === \"true\";\r\n const stateStr = hashParams.get(\"state\") ?? undefined;\r\n const persist = hashParams.get(\"persist\") === \"true\";\r\n if (token !== undefined && expiresInStr !== undefined && userName !== undefined && ssl !== undefined && stateStr !== undefined) {\r\n let endpointOrigin;\r\n try {\r\n const state = JSON.parse(stateStr);\r\n stateData = state?.customData;\r\n endpointOrigin = state?.endpointOrigin;\r\n\r\n } catch {\r\n }\r\n const expiresIn = Number(expiresInStr);\r\n const expiresAt = (expiresIn * 1000) + (+new Date()); // Converts the token expiration delay (seconds) into a timestamp (UNIX time)\r\n if (endpointOrigin !== undefined) {\r\n ArcGisTokenManager.setOAuth2Token(endpointOrigin, { token, expiresAt, ssl, userName, persist });\r\n eventSuccess = true;\r\n }\r\n\r\n }\r\n }\r\n this.onOAuthProcessEnd.raiseEvent(eventSuccess, stateData);\r\n };\r\n }\r\n\r\n public unInitialize() {\r\n this._redirectUri = undefined;\r\n this._expiration = undefined;\r\n (window as any).arcGisOAuth2Callback = undefined;\r\n }\r\n\r\n public async getAccessToken(params: MapLayerAccessTokenParams): Promise<MapLayerAccessToken | undefined> {\r\n // First lookup Oauth2 tokens, otherwise check try \"legacy tokens\" if credentials were provided\r\n\r\n if (!this._forceLegacyToken) {\r\n const oauth2Token = await this.getOAuthTokenForMapLayerUrl(params.mapLayerUrl.toString());\r\n if (oauth2Token)\r\n return oauth2Token;\r\n }\r\n\r\n if (params.userName && params.password) {\r\n return ArcGisTokenManager.getToken(params.mapLayerUrl.toString(), params.userName, params.password, { client: ArcGisTokenClientType.referer });\r\n }\r\n\r\n return undefined;\r\n }\r\n\r\n /** @internal */\r\n public static async validateOAuth2Endpoint(endpointUrl: string): Promise<boolean> {\r\n const data = await fetch(endpointUrl, { method: \"GET\" });\r\n return data.status === 400; // Oauth2 API returns 400 (Bad Request) when there are missing parameters\r\n }\r\n\r\n public async getTokenServiceEndPoint(mapLayerUrl: string): Promise<MapLayerTokenEndpoint | undefined> {\r\n if (!this._forceLegacyToken) {\r\n return this.getOAuth2Endpoint(mapLayerUrl, ArcGisOAuth2EndpointType.Authorize);\r\n }\r\n\r\n return undefined;\r\n }\r\n\r\n public invalidateToken(token: MapLayerAccessToken): boolean {\r\n let found = ArcGisTokenManager.invalidateToken(token);\r\n if (!found) {\r\n found = ArcGisTokenManager.invalidateOAuth2Token(token);\r\n }\r\n return found;\r\n }\r\n\r\n public get redirectUri() {\r\n return this._redirectUri;\r\n }\r\n\r\n public getMatchingEnterpriseClientId(url: string) {\r\n const clientIds = this.arcGisEnterpriseClientIds;\r\n if (!clientIds) {\r\n return undefined;\r\n }\r\n\r\n let clientId: string | undefined;\r\n let defaultClientId: string | undefined;\r\n for (const entry of clientIds) {\r\n if (entry.serviceBaseUrl === \"\") {\r\n defaultClientId = entry.clientId;\r\n } else {\r\n if (url.toLowerCase().startsWith(entry.serviceBaseUrl)) {\r\n clientId = entry.clientId;\r\n }\r\n }\r\n }\r\n\r\n // If we could not find a match with serviceBaseUrl, and a default clientId\r\n // was specified (i.e empty url), then use default clientId\r\n if (clientId === undefined && defaultClientId !== undefined) {\r\n clientId = defaultClientId;\r\n }\r\n return clientId;\r\n }\r\n\r\n public get expiration() {\r\n return this._expiration;\r\n }\r\n\r\n public get arcGisOnlineClientId() {\r\n return this._clientIds?.arcgisOnlineClientId;\r\n }\r\n\r\n public set arcGisOnlineClientId(clientId: string | undefined) {\r\n if (this._clientIds === undefined) {\r\n this._clientIds = { arcgisOnlineClientId: clientId };\r\n }\r\n this._clientIds.arcgisOnlineClientId = clientId;\r\n }\r\n\r\n public get arcGisEnterpriseClientIds() {\r\n return this._clientIds?.enterpriseClientIds;\r\n }\r\n\r\n public setEnterpriseClientId(serviceBaseUrl: string, clientId: string) {\r\n\r\n if (this._clientIds?.enterpriseClientIds) {\r\n const foundIdx = this._clientIds.enterpriseClientIds.findIndex((entry) => entry.serviceBaseUrl === serviceBaseUrl);\r\n if (foundIdx !== -1) {\r\n this._clientIds.enterpriseClientIds[foundIdx].clientId = clientId;\r\n } else {\r\n this._clientIds.enterpriseClientIds.push({ serviceBaseUrl, clientId });\r\n }\r\n } else {\r\n if (this._clientIds === undefined) {\r\n this._clientIds = {};\r\n }\r\n this._clientIds.enterpriseClientIds = [{ serviceBaseUrl, clientId }];\r\n }\r\n }\r\n\r\n public removeEnterpriseClientId(clientId: ArcGisEnterpriseClientId) {\r\n\r\n if (this._clientIds?.enterpriseClientIds) {\r\n this._clientIds.enterpriseClientIds = this._clientIds?.enterpriseClientIds?.filter((item) => item.serviceBaseUrl !== clientId.serviceBaseUrl);\r\n }\r\n\r\n }\r\n\r\n /// //////////\r\n /** @internal */\r\n private async getOAuthTokenForMapLayerUrl(mapLayerUrl: string): Promise<ArcGisOAuth2Token | undefined> {\r\n try {\r\n const oauthEndpoint = await this.getOAuth2Endpoint(mapLayerUrl, ArcGisOAuth2EndpointType.Authorize);\r\n if (oauthEndpoint !== undefined) {\r\n const oauthEndpointUrl = new URL(oauthEndpoint.getUrl());\r\n return ArcGisTokenManager.getOAuth2Token(oauthEndpointUrl.origin);\r\n }\r\n } catch { }\r\n return undefined;\r\n }\r\n\r\n // Mapping between a map-layer URL and its corresponding Oauth endpoint\r\n // i.e. \t https://hostname/server/rest/services/NewYork/NewYork3857/MapServer\r\n // => https://hostname/portal/sharing/oauth2/authorize\r\n\r\n private _endPointsCache = new Map<MapLayerUrl, EndPointsCacheEntry>();\r\n\r\n /**\r\n * Get OAuth2 endpoint that must be cause to get the Oauth2 token\r\n * @internal\r\n */\r\n private cacheEndpoint(url: MapLayerUrl, endpointType: ArcGisOAuth2EndpointType, endPoint: ArcGisOAuth2Endpoint) {\r\n const entry = endpointType === ArcGisOAuth2EndpointType.Authorize ? {authorizeEndpoint: endPoint} : {tokenEndpoint: endPoint};\r\n this._endPointsCache.set(url, entry);\r\n }\r\n\r\n /**\r\n * Get OAuth2 endpoint that must be cause to get the Oauth2 token\r\n * @internal\r\n */\r\n private async createEndpoint(mapLayerUrl: MapLayerUrl, oauthEndpointUrl: string, endpointType: ArcGisOAuth2EndpointType): Promise<ArcGisOAuth2Endpoint | undefined> {\r\n // Validate the URL we just composed\r\n const oauthEndpoint = new ArcGisOAuth2Endpoint(oauthEndpointUrl, this.constructLoginUrl(oauthEndpointUrl, false), false);\r\n this.cacheEndpoint(mapLayerUrl, endpointType, oauthEndpoint);\r\n return oauthEndpoint;\r\n }\r\n\r\n /**\r\n * Returns whether the ArcGis host is valid\r\n * @internal\r\n */\r\n private isArcGisHostValid(url: URL): boolean {\r\n const allowedHosts = [\r\n \"arcgis.com\",\r\n ];\r\n\r\n return allowedHosts.some((host: string) => url.hostname.toLowerCase().endsWith(host));\r\n }\r\n\r\n private async validateEndpointUrl(url: string) {\r\n let valid: boolean|undefined;\r\n try {\r\n valid = await ArcGisAccessClient.validateOAuth2Endpoint(url.toString());\r\n } catch {\r\n // If we reach here, this means we could not validate properly the endpoint;\r\n // we cannot conclude the endpoint is invalid though; it might happen endpoint doesn't support CORS requests,\r\n // but still valid for Oauth process.\r\n }\r\n return valid;\r\n }\r\n\r\n /**\r\n * Get OAuth2 endpoint that must be cause to get the Oauth2 token\r\n * @internal\r\n */\r\n private async getOAuth2Endpoint(mapLayerUrl: string, endpointType: ArcGisOAuth2EndpointType): Promise<ArcGisOAuth2Endpoint | undefined> {\r\n // Return from cache if available\r\n const cachedEndpoint = this._endPointsCache.get(mapLayerUrl);\r\n if (cachedEndpoint !== undefined) {\r\n return (endpointType === ArcGisOAuth2EndpointType.Authorize ? cachedEndpoint.authorizeEndpoint : cachedEndpoint.authorizeEndpoint);\r\n }\r\n\r\n const endpointStr = (endpointType === ArcGisOAuth2EndpointType.Authorize ? \"authorize\" : \"token\");\r\n\r\n const urlObj = new URL(mapLayerUrl);\r\n\r\n if (this.isArcGisHostValid(urlObj)) {\r\n // ArcGIS Online (fixed)\r\n // Doc: https://developers.arcgis.com/documentation/mapping-apis-and-services/security/oauth-2.0/\r\n\r\n if (this.arcGisOnlineClientId === undefined) {\r\n return undefined;\r\n }\r\n\r\n const oauth2Url = `https://www.arcgis.com/sharing/rest/oauth2/${endpointStr}`;\r\n return new ArcGisOAuth2Endpoint(oauth2Url, this.constructLoginUrl(oauth2Url, true), true);\r\n } else {\r\n\r\n // First attempt: derive the Oauth2 token URL from the 'tokenServicesUrl', exposed by the 'info request'\r\n try {\r\n const restUrlFromTokenService = await ArcGisUrl.getRestUrlFromGenerateTokenUrl(urlObj);\r\n\r\n if (restUrlFromTokenService === undefined) {\r\n // We could not derive the token endpoint from 'tokenServicesUrl'.\r\n // ArcGIS Enterprise Format https://<host>:<port>/<subdirectory>/sharing/rest/oauth2/authorize\r\n const regExMatch = mapLayerUrl.match(new RegExp(/([^&\\/]+)\\/rest\\/services\\/.*/, \"i\"));\r\n if (regExMatch !== null && regExMatch.length >= 2) {\r\n const subdirectory = regExMatch[1];\r\n const port = (urlObj.port !== \"80\" && urlObj.port !== \"443\") ? `:${urlObj.port}` : \"\";\r\n const newUrlObj = new URL(`${urlObj.protocol}//${urlObj.hostname}${port}/${subdirectory}/sharing/rest/oauth2/${endpointStr}`);\r\n\r\n // Check again the URL we just composed\r\n const isValidUrl = await this.validateEndpointUrl(newUrlObj.toString());\r\n if (isValidUrl === undefined || isValidUrl ) {\r\n const endpoint = await this.createEndpoint(mapLayerUrl, newUrlObj.toString(), endpointType);\r\n if (endpoint)\r\n return endpoint;\r\n }\r\n }\r\n } else {\r\n const isValidUrl = await this.validateEndpointUrl(restUrlFromTokenService.toString());\r\n if (isValidUrl === undefined || isValidUrl ) {\r\n const endpoint = await this.createEndpoint(mapLayerUrl, `${restUrlFromTokenService.toString()}oauth2/${endpointStr}`, endpointType);\r\n if (endpoint)\r\n return endpoint;\r\n }\r\n }\r\n } catch {\r\n }\r\n }\r\n\r\n // If we reach here, we were not successful creating an endpoint\r\n this._endPointsCache.set(mapLayerUrl, {}); // Cache an empty entry, and avoid making repeated failing requests.\r\n\r\n return undefined; // we could not find any valid oauth2 endpoint\r\n }\r\n\r\n /**\r\n * Construct the complete Authorize url to starts the Oauth process\r\n * @internal\r\n */\r\n private constructLoginUrl(url: string, isArcgisOnline: boolean) {\r\n const urlObj = new URL(url);\r\n\r\n // Set the client id\r\n if (isArcgisOnline) {\r\n const clientId = this.arcGisOnlineClientId;\r\n assert(clientId !== undefined);\r\n if (clientId !== undefined) {\r\n urlObj.searchParams.set(\"client_id\", clientId);\r\n }\r\n\r\n } else {\r\n const clientId = this.getMatchingEnterpriseClientId(url);\r\n assert(clientId !== undefined);\r\n if (undefined !== clientId) {\r\n urlObj.searchParams.set(\"client_id\", clientId);\r\n }\r\n }\r\n\r\n urlObj.searchParams.set(\"response_type\", \"token\");\r\n if (this.expiration !== undefined) {\r\n urlObj.searchParams.set(\"expiration\", `${this.expiration}`);\r\n }\r\n\r\n if (this.redirectUri)\r\n urlObj.searchParams.set(\"redirect_uri\", this.redirectUri);\r\n\r\n return urlObj.toString();\r\n }\r\n\r\n}\r\n"]}
@@ -35,6 +35,8 @@ export declare class ArcGisAccessClient implements MapLayerAccessClient {
35
35
  private initOauthCallbackFunction;
36
36
  unInitialize(): void;
37
37
  getAccessToken(params: MapLayerAccessTokenParams): Promise<MapLayerAccessToken | undefined>;
38
+ /** @internal */
39
+ static validateOAuth2Endpoint(endpointUrl: string): Promise<boolean>;
38
40
  getTokenServiceEndPoint(mapLayerUrl: string): Promise<MapLayerTokenEndpoint | undefined>;
39
41
  invalidateToken(token: MapLayerAccessToken): boolean;
40
42
  get redirectUri(): string | undefined;
@@ -47,8 +49,7 @@ export declare class ArcGisAccessClient implements MapLayerAccessClient {
47
49
  removeEnterpriseClientId(clientId: ArcGisEnterpriseClientId): void;
48
50
  /** @internal */
49
51
  private getOAuthTokenForMapLayerUrl;
50
- private _oauthAuthorizeEndPointsCache;
51
- private _oauthTokenEndPointsCache;
52
+ private _endPointsCache;
52
53
  /**
53
54
  * Get OAuth2 endpoint that must be cause to get the Oauth2 token
54
55
  * @internal
@@ -64,6 +65,7 @@ export declare class ArcGisAccessClient implements MapLayerAccessClient {
64
65
  * @internal
65
66
  */
66
67
  private isArcGisHostValid;
68
+ private validateEndpointUrl;
67
69
  /**
68
70
  * Get OAuth2 endpoint that must be cause to get the Oauth2 token
69
71
  * @internal
@@ -1 +1 @@
1
- {"version":3,"file":"ArcGisAccessClient.d.ts","sourceRoot":"","sources":["../../../src/ArcGis/ArcGisAccessClient.ts"],"names":[],"mappings":"AAIA;;GAEG;AAEH,OAAO,EAAU,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,yBAAyB,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAMnI,YAAY;AACZ,MAAM,WAAW,wBAAwB;IAGvC,cAAc,EAAE,MAAM,CAAC;IAGvB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,YAAY;AACZ,MAAM,WAAW,oBAAoB;IAEnC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAG9B,mBAAmB,CAAC,EAAE,wBAAwB,EAAE,CAAC;CAClD;AAED;;;;EAIE;AACF,MAAM,WAAW,iBAAiB;IAIhC,WAAW,EAAE,MAAM,CAAC;IAGpB,eAAe,CAAC,EAAE,MAAM,CAAC;IAGzB,SAAS,EAAE,oBAAoB,CAAC;CACjC;AAED,YAAY;AACZ,qBAAa,kBAAmB,YAAW,oBAAoB;IAC7D,SAAgB,iBAAiB,kDAAiB;IAClD,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,WAAW,CAAqB;IACxC,OAAO,CAAC,UAAU,CAAmC;IAGrD,OAAO,CAAC,iBAAiB,CAAS;;IAK3B,UAAU,CAAC,WAAW,CAAC,EAAE,iBAAiB,GAAG,OAAO;IAW3D,OAAO,CAAC,yBAAyB;IAoC1B,YAAY;IAMN,cAAc,CAAC,MAAM,EAAE,yBAAyB,GAAG,OAAO,CAAC,mBAAmB,GAAG,SAAS,CAAC;IAgB3F,uBAAuB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,GAAG,SAAS,CAAC;IAkB9F,eAAe,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO;IAQ3D,IAAW,WAAW,uBAErB;IAEM,6BAA6B,CAAC,GAAG,EAAE,MAAM;IA0BhD,IAAW,UAAU,uBAEpB;IAED,IAAW,oBAAoB,IAIW,MAAM,GAAG,SAAS,CAF3D;IAED,IAAW,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAK3D;IAED,IAAW,yBAAyB,2CAEnC;IAEM,qBAAqB,CAAC,cAAc,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;IAiB9D,wBAAwB,CAAC,QAAQ,EAAE,wBAAwB;IASlE,gBAAgB;YACF,2BAA2B;IAczC,OAAO,CAAC,6BAA6B,CAA0B;IAC/D,OAAO,CAAC,yBAAyB,CAA0B;IAE3D;;;KAGC;IACD,OAAO,CAAC,aAAa;IAQrB;;;KAGC;YACa,cAAc;IAO5B;;;MAGE;IACF,OAAO,CAAC,iBAAiB;IAQzB;;;KAGC;YACa,iBAAiB;IAmD/B;;;KAGC;IACD,OAAO,CAAC,iBAAiB;CA8B1B"}
1
+ {"version":3,"file":"ArcGisAccessClient.d.ts","sourceRoot":"","sources":["../../../src/ArcGis/ArcGisAccessClient.ts"],"names":[],"mappings":"AAIA;;GAEG;AAEH,OAAO,EAAU,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,yBAAyB,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAMnI,YAAY;AACZ,MAAM,WAAW,wBAAwB;IAGvC,cAAc,EAAE,MAAM,CAAC;IAGvB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,YAAY;AACZ,MAAM,WAAW,oBAAoB;IAEnC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAG9B,mBAAmB,CAAC,EAAE,wBAAwB,EAAE,CAAC;CAClD;AAED;;;;EAIE;AACF,MAAM,WAAW,iBAAiB;IAIhC,WAAW,EAAE,MAAM,CAAC;IAGpB,eAAe,CAAC,EAAE,MAAM,CAAC;IAGzB,SAAS,EAAE,oBAAoB,CAAC;CACjC;AASD,YAAY;AACZ,qBAAa,kBAAmB,YAAW,oBAAoB;IAC7D,SAAgB,iBAAiB,kDAAiB;IAClD,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,WAAW,CAAqB;IACxC,OAAO,CAAC,UAAU,CAAmC;IAGrD,OAAO,CAAC,iBAAiB,CAAS;;IAK3B,UAAU,CAAC,WAAW,CAAC,EAAE,iBAAiB,GAAG,OAAO;IAW3D,OAAO,CAAC,yBAAyB;IAoC1B,YAAY;IAMN,cAAc,CAAC,MAAM,EAAE,yBAAyB,GAAG,OAAO,CAAC,mBAAmB,GAAG,SAAS,CAAC;IAgBxG,gBAAgB;WACI,sBAAsB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKpE,uBAAuB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,GAAG,SAAS,CAAC;IAQ9F,eAAe,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO;IAQ3D,IAAW,WAAW,uBAErB;IAEM,6BAA6B,CAAC,GAAG,EAAE,MAAM;IA0BhD,IAAW,UAAU,uBAEpB;IAED,IAAW,oBAAoB,IAIW,MAAM,GAAG,SAAS,CAF3D;IAED,IAAW,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAK3D;IAED,IAAW,yBAAyB,2CAEnC;IAEM,qBAAqB,CAAC,cAAc,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;IAiB9D,wBAAwB,CAAC,QAAQ,EAAE,wBAAwB;IASlE,gBAAgB;YACF,2BAA2B;IAezC,OAAO,CAAC,eAAe,CAA+C;IAEtE;;;KAGC;IACD,OAAO,CAAC,aAAa;IAKrB;;;KAGC;YACa,cAAc;IAO5B;;;MAGE;IACF,OAAO,CAAC,iBAAiB;YAQX,mBAAmB;IAYjC;;;KAGC;YACa,iBAAiB;IA8D/B;;;KAGC;IACD,OAAO,CAAC,iBAAiB;CA8B1B"}
@@ -16,11 +16,10 @@ export class ArcGisAccessClient {
16
16
  this.onOAuthProcessEnd = new BeEvent();
17
17
  // Should be kept to 'false'. Debugging purposes only.
18
18
  this._forceLegacyToken = false;
19
- // Derive the Oauth URL from a typical MapLayerURL
19
+ // Mapping between a map-layer URL and its corresponding Oauth endpoint
20
20
  // i.e. https://hostname/server/rest/services/NewYork/NewYork3857/MapServer
21
21
  // => https://hostname/portal/sharing/oauth2/authorize
22
- this._oauthAuthorizeEndPointsCache = new Map();
23
- this._oauthTokenEndPointsCache = new Map();
22
+ this._endPointsCache = new Map();
24
23
  }
25
24
  initialize(oAuthConfig) {
26
25
  if (oAuthConfig) {
@@ -81,20 +80,16 @@ export class ArcGisAccessClient {
81
80
  }
82
81
  return undefined;
83
82
  }
83
+ /** @internal */
84
+ static async validateOAuth2Endpoint(endpointUrl) {
85
+ const data = await fetch(endpointUrl, { method: "GET" });
86
+ return data.status === 400; // Oauth2 API returns 400 (Bad Request) when there are missing parameters
87
+ }
84
88
  async getTokenServiceEndPoint(mapLayerUrl) {
85
- let tokenEndpoint;
86
89
  if (!this._forceLegacyToken) {
87
- // Note: we used to validate the endpoint by making a request, but because of CORS isssues with some servers
88
- // we could not make a reliable validation.
89
- try {
90
- tokenEndpoint = await this.getOAuth2Endpoint(mapLayerUrl, ArcGisOAuth2EndpointType.Authorize);
91
- if (tokenEndpoint) {
92
- }
93
- }
94
- catch {
95
- }
90
+ return this.getOAuth2Endpoint(mapLayerUrl, ArcGisOAuth2EndpointType.Authorize);
96
91
  }
97
- return tokenEndpoint;
92
+ return undefined;
98
93
  }
99
94
  invalidateToken(token) {
100
95
  let found = ArcGisTokenManager.invalidateToken(token);
@@ -184,22 +179,18 @@ export class ArcGisAccessClient {
184
179
  * Get OAuth2 endpoint that must be cause to get the Oauth2 token
185
180
  * @internal
186
181
  */
187
- cacheEndpoint(url, endpoint, obj) {
188
- if (endpoint === ArcGisOAuth2EndpointType.Authorize) {
189
- this._oauthAuthorizeEndPointsCache.set(url, obj);
190
- }
191
- else {
192
- this._oauthTokenEndPointsCache.set(url, obj);
193
- }
182
+ cacheEndpoint(url, endpointType, endPoint) {
183
+ const entry = endpointType === ArcGisOAuth2EndpointType.Authorize ? { authorizeEndpoint: endPoint } : { tokenEndpoint: endPoint };
184
+ this._endPointsCache.set(url, entry);
194
185
  }
195
186
  /**
196
187
  * Get OAuth2 endpoint that must be cause to get the Oauth2 token
197
188
  * @internal
198
189
  */
199
- async createEndpoint(url, endpoint) {
190
+ async createEndpoint(mapLayerUrl, oauthEndpointUrl, endpointType) {
200
191
  // Validate the URL we just composed
201
- const oauthEndpoint = new ArcGisOAuth2Endpoint(url, this.constructLoginUrl(url, false), false);
202
- this.cacheEndpoint(url, endpoint, oauthEndpoint);
192
+ const oauthEndpoint = new ArcGisOAuth2Endpoint(oauthEndpointUrl, this.constructLoginUrl(oauthEndpointUrl, false), false);
193
+ this.cacheEndpoint(mapLayerUrl, endpointType, oauthEndpoint);
203
194
  return oauthEndpoint;
204
195
  }
205
196
  /**
@@ -212,18 +203,30 @@ export class ArcGisAccessClient {
212
203
  ];
213
204
  return allowedHosts.some((host) => url.hostname.toLowerCase().endsWith(host));
214
205
  }
206
+ async validateEndpointUrl(url) {
207
+ let valid;
208
+ try {
209
+ valid = await ArcGisAccessClient.validateOAuth2Endpoint(url.toString());
210
+ }
211
+ catch {
212
+ // If we reach here, this means we could not validate properly the endpoint;
213
+ // we cannot conclude the endpoint is invalid though; it might happen endpoint doesn't support CORS requests,
214
+ // but still valid for Oauth process.
215
+ }
216
+ return valid;
217
+ }
215
218
  /**
216
219
  * Get OAuth2 endpoint that must be cause to get the Oauth2 token
217
220
  * @internal
218
221
  */
219
- async getOAuth2Endpoint(url, endpointType) {
222
+ async getOAuth2Endpoint(mapLayerUrl, endpointType) {
220
223
  // Return from cache if available
221
- const cachedEndpoint = (endpointType === ArcGisOAuth2EndpointType.Authorize ? this._oauthAuthorizeEndPointsCache.get(url) : this._oauthTokenEndPointsCache.get(url));
224
+ const cachedEndpoint = this._endPointsCache.get(mapLayerUrl);
222
225
  if (cachedEndpoint !== undefined) {
223
- return cachedEndpoint;
226
+ return (endpointType === ArcGisOAuth2EndpointType.Authorize ? cachedEndpoint.authorizeEndpoint : cachedEndpoint.authorizeEndpoint);
224
227
  }
225
228
  const endpointStr = (endpointType === ArcGisOAuth2EndpointType.Authorize ? "authorize" : "token");
226
- const urlObj = new URL(url);
229
+ const urlObj = new URL(mapLayerUrl);
227
230
  if (this.isArcGisHostValid(urlObj)) {
228
231
  // ArcGIS Online (fixed)
229
232
  // Doc: https://developers.arcgis.com/documentation/mapping-apis-and-services/security/oauth-2.0/
@@ -240,24 +243,34 @@ export class ArcGisAccessClient {
240
243
  if (restUrlFromTokenService === undefined) {
241
244
  // We could not derive the token endpoint from 'tokenServicesUrl'.
242
245
  // ArcGIS Enterprise Format https://<host>:<port>/<subdirectory>/sharing/rest/oauth2/authorize
243
- const regExMatch = url.match(new RegExp(/([^&\/]+)\/rest\/services\/.*/, "i"));
246
+ const regExMatch = mapLayerUrl.match(new RegExp(/([^&\/]+)\/rest\/services\/.*/, "i"));
244
247
  if (regExMatch !== null && regExMatch.length >= 2) {
245
248
  const subdirectory = regExMatch[1];
246
249
  const port = (urlObj.port !== "80" && urlObj.port !== "443") ? `:${urlObj.port}` : "";
247
250
  const newUrlObj = new URL(`${urlObj.protocol}//${urlObj.hostname}${port}/${subdirectory}/sharing/rest/oauth2/${endpointStr}`);
248
251
  // Check again the URL we just composed
249
- return await this.createEndpoint(newUrlObj.toString(), endpointType);
252
+ const isValidUrl = await this.validateEndpointUrl(newUrlObj.toString());
253
+ if (isValidUrl === undefined || isValidUrl) {
254
+ const endpoint = await this.createEndpoint(mapLayerUrl, newUrlObj.toString(), endpointType);
255
+ if (endpoint)
256
+ return endpoint;
257
+ }
250
258
  }
251
259
  }
252
260
  else {
253
- const endpoint = await this.createEndpoint(`${restUrlFromTokenService.toString()}oauth2/${endpointStr}`, endpointType);
254
- if (endpoint)
255
- return endpoint;
261
+ const isValidUrl = await this.validateEndpointUrl(restUrlFromTokenService.toString());
262
+ if (isValidUrl === undefined || isValidUrl) {
263
+ const endpoint = await this.createEndpoint(mapLayerUrl, `${restUrlFromTokenService.toString()}oauth2/${endpointStr}`, endpointType);
264
+ if (endpoint)
265
+ return endpoint;
266
+ }
256
267
  }
257
268
  }
258
269
  catch {
259
270
  }
260
271
  }
272
+ // If we reach here, we were not successful creating an endpoint
273
+ this._endPointsCache.set(mapLayerUrl, {}); // Cache an empty entry, and avoid making repeated failing requests.
261
274
  return undefined; // we could not find any valid oauth2 endpoint
262
275
  }
263
276
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"ArcGisAccessClient.js","sourceRoot":"","sources":["../../../src/ArcGis/ArcGisAccessClient.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n/** @packageDocumentation\r\n * @module Tiles\r\n */\r\n\r\nimport { assert, BeEvent } from \"@itwin/core-bentley\";\r\nimport { MapLayerAccessClient, MapLayerAccessToken, MapLayerAccessTokenParams, MapLayerTokenEndpoint } from \"@itwin/core-frontend\";\r\nimport { ArcGisOAuth2Token, ArcGisTokenClientType } from \"./ArcGisTokenGenerator\";\r\nimport { ArcGisOAuth2Endpoint, ArcGisOAuth2EndpointType } from \"./ArcGisOAuth2Endpoint\";\r\nimport { ArcGisTokenManager } from \"./ArcGisTokenManager\";\r\nimport { ArcGisUrl } from \"./ArcGisUrl\";\r\n\r\n/** @beta */\r\nexport interface ArcGisEnterpriseClientId {\r\n /* Oauth API endpoint base URL (i.e. https://hostname/portal/sharing/oauth2/authorize)\r\n used to identify uniquely each enterprise server. */\r\n serviceBaseUrl: string;\r\n\r\n /* Application's clientId for this enterprise server.*/\r\n clientId: string;\r\n}\r\n\r\n/** @beta */\r\nexport interface ArcGisOAuthClientIds {\r\n /* Application's OAuth clientId in ArcGIS online */\r\n arcgisOnlineClientId?: string;\r\n\r\n /* Application's OAuth clientId for each enterprise server used. */\r\n enterpriseClientIds?: ArcGisEnterpriseClientId[];\r\n}\r\n\r\n/** @beta\r\n * ArcGIS OAuth configurations parameters.\r\n * See https://developers.arcgis.com/documentation/mapping-apis-and-services/security/arcgis-identity/serverless-web-apps/\r\n * more details.\r\n*/\r\nexport interface ArcGisOAuthConfig {\r\n /* URL to which a user is sent once they complete sign in authorization.\r\n Must match a URI you define in the developer dashboard, otherwise, the authorization will be rejected.\r\n */\r\n redirectUri: string;\r\n\r\n /* Optional expiration after which the token will expire. Defined in minutes with a maximum of two weeks (20160 minutes)*/\r\n tokenExpiration?: number;\r\n\r\n /* Application client Ids */\r\n clientIds: ArcGisOAuthClientIds;\r\n}\r\n\r\n/** @beta */\r\nexport class ArcGisAccessClient implements MapLayerAccessClient {\r\n public readonly onOAuthProcessEnd = new BeEvent();\r\n private _redirectUri: string | undefined;\r\n private _expiration: number | undefined;\r\n private _clientIds: ArcGisOAuthClientIds | undefined;\r\n\r\n // Should be kept to 'false'. Debugging purposes only.\r\n private _forceLegacyToken = false;\r\n\r\n public constructor() {\r\n }\r\n\r\n public initialize(oAuthConfig?: ArcGisOAuthConfig): boolean {\r\n if (oAuthConfig) {\r\n this._redirectUri = oAuthConfig.redirectUri;\r\n this._expiration = oAuthConfig.tokenExpiration;\r\n this._clientIds = oAuthConfig.clientIds;\r\n\r\n this.initOauthCallbackFunction();\r\n }\r\n return true;\r\n }\r\n\r\n private initOauthCallbackFunction() {\r\n (window as any).arcGisOAuth2Callback = (redirectLocation?: Location) => {\r\n let eventSuccess = false;\r\n let stateData;\r\n\r\n if (redirectLocation && redirectLocation.hash.length > 0) {\r\n const locationHash = redirectLocation.hash;\r\n const hashParams = new URLSearchParams(locationHash.substring(1));\r\n const token = hashParams.get(\"access_token\") ?? undefined;\r\n const expiresInStr = hashParams.get(\"expires_in\") ?? undefined;\r\n const userName = hashParams.get(\"username\") ?? undefined;\r\n const ssl = hashParams.get(\"ssl\") === \"true\";\r\n const stateStr = hashParams.get(\"state\") ?? undefined;\r\n const persist = hashParams.get(\"persist\") === \"true\";\r\n if (token !== undefined && expiresInStr !== undefined && userName !== undefined && ssl !== undefined && stateStr !== undefined) {\r\n let endpointOrigin;\r\n try {\r\n const state = JSON.parse(stateStr);\r\n stateData = state?.customData;\r\n endpointOrigin = state?.endpointOrigin;\r\n\r\n } catch {\r\n }\r\n const expiresIn = Number(expiresInStr);\r\n const expiresAt = (expiresIn * 1000) + (+new Date()); // Converts the token expiration delay (seconds) into a timestamp (UNIX time)\r\n if (endpointOrigin !== undefined) {\r\n ArcGisTokenManager.setOAuth2Token(endpointOrigin, { token, expiresAt, ssl, userName, persist });\r\n eventSuccess = true;\r\n }\r\n\r\n }\r\n }\r\n this.onOAuthProcessEnd.raiseEvent(eventSuccess, stateData);\r\n };\r\n }\r\n\r\n public unInitialize() {\r\n this._redirectUri = undefined;\r\n this._expiration = undefined;\r\n (window as any).arcGisOAuth2Callback = undefined;\r\n }\r\n\r\n public async getAccessToken(params: MapLayerAccessTokenParams): Promise<MapLayerAccessToken | undefined> {\r\n // First lookup Oauth2 tokens, otherwise check try \"legacy tokens\" if credentials were provided\r\n\r\n if (!this._forceLegacyToken) {\r\n const oauth2Token = await this.getOAuthTokenForMapLayerUrl(params.mapLayerUrl.toString());\r\n if (oauth2Token)\r\n return oauth2Token;\r\n }\r\n\r\n if (params.userName && params.password) {\r\n return ArcGisTokenManager.getToken(params.mapLayerUrl.toString(), params.userName, params.password, { client: ArcGisTokenClientType.referer });\r\n }\r\n\r\n return undefined;\r\n }\r\n\r\n public async getTokenServiceEndPoint(mapLayerUrl: string): Promise<MapLayerTokenEndpoint | undefined> {\r\n let tokenEndpoint: ArcGisOAuth2Endpoint | undefined;\r\n if (!this._forceLegacyToken) {\r\n // Note: we used to validate the endpoint by making a request, but because of CORS isssues with some servers\r\n // we could not make a reliable validation.\r\n try {\r\n tokenEndpoint = await this.getOAuth2Endpoint(mapLayerUrl, ArcGisOAuth2EndpointType.Authorize);\r\n if (tokenEndpoint) {\r\n\r\n }\r\n } catch {\r\n\r\n }\r\n }\r\n\r\n return tokenEndpoint;\r\n }\r\n\r\n public invalidateToken(token: MapLayerAccessToken): boolean {\r\n let found = ArcGisTokenManager.invalidateToken(token);\r\n if (!found) {\r\n found = ArcGisTokenManager.invalidateOAuth2Token(token);\r\n }\r\n return found;\r\n }\r\n\r\n public get redirectUri() {\r\n return this._redirectUri;\r\n }\r\n\r\n public getMatchingEnterpriseClientId(url: string) {\r\n const clientIds = this.arcGisEnterpriseClientIds;\r\n if (!clientIds) {\r\n return undefined;\r\n }\r\n\r\n let clientId: string | undefined;\r\n let defaultClientId: string | undefined;\r\n for (const entry of clientIds) {\r\n if (entry.serviceBaseUrl === \"\") {\r\n defaultClientId = entry.clientId;\r\n } else {\r\n if (url.toLowerCase().startsWith(entry.serviceBaseUrl)) {\r\n clientId = entry.clientId;\r\n }\r\n }\r\n }\r\n\r\n // If we could not find a match with serviceBaseUrl, and a default clientId\r\n // was specified (i.e empty url), then use default clientId\r\n if (clientId === undefined && defaultClientId !== undefined) {\r\n clientId = defaultClientId;\r\n }\r\n return clientId;\r\n }\r\n\r\n public get expiration() {\r\n return this._expiration;\r\n }\r\n\r\n public get arcGisOnlineClientId() {\r\n return this._clientIds?.arcgisOnlineClientId;\r\n }\r\n\r\n public set arcGisOnlineClientId(clientId: string | undefined) {\r\n if (this._clientIds === undefined) {\r\n this._clientIds = { arcgisOnlineClientId: clientId };\r\n }\r\n this._clientIds.arcgisOnlineClientId = clientId;\r\n }\r\n\r\n public get arcGisEnterpriseClientIds() {\r\n return this._clientIds?.enterpriseClientIds;\r\n }\r\n\r\n public setEnterpriseClientId(serviceBaseUrl: string, clientId: string) {\r\n\r\n if (this._clientIds?.enterpriseClientIds) {\r\n const foundIdx = this._clientIds.enterpriseClientIds.findIndex((entry) => entry.serviceBaseUrl === serviceBaseUrl);\r\n if (foundIdx !== -1) {\r\n this._clientIds.enterpriseClientIds[foundIdx].clientId = clientId;\r\n } else {\r\n this._clientIds.enterpriseClientIds.push({ serviceBaseUrl, clientId });\r\n }\r\n } else {\r\n if (this._clientIds === undefined) {\r\n this._clientIds = {};\r\n }\r\n this._clientIds.enterpriseClientIds = [{ serviceBaseUrl, clientId }];\r\n }\r\n }\r\n\r\n public removeEnterpriseClientId(clientId: ArcGisEnterpriseClientId) {\r\n\r\n if (this._clientIds?.enterpriseClientIds) {\r\n this._clientIds.enterpriseClientIds = this._clientIds?.enterpriseClientIds?.filter((item) => item.serviceBaseUrl !== clientId.serviceBaseUrl);\r\n }\r\n\r\n }\r\n\r\n /// //////////\r\n /** @internal */\r\n private async getOAuthTokenForMapLayerUrl(mapLayerUrl: string): Promise<ArcGisOAuth2Token | undefined> {\r\n try {\r\n const oauthEndpoint = await this.getOAuth2Endpoint(mapLayerUrl, ArcGisOAuth2EndpointType.Authorize);\r\n if (oauthEndpoint !== undefined) {\r\n const oauthEndpointUrl = new URL(oauthEndpoint.getUrl());\r\n return ArcGisTokenManager.getOAuth2Token(oauthEndpointUrl.origin);\r\n }\r\n } catch { }\r\n return undefined;\r\n }\r\n\r\n // Derive the Oauth URL from a typical MapLayerURL\r\n // i.e. \t https://hostname/server/rest/services/NewYork/NewYork3857/MapServer\r\n // => https://hostname/portal/sharing/oauth2/authorize\r\n private _oauthAuthorizeEndPointsCache = new Map<string, any>();\r\n private _oauthTokenEndPointsCache = new Map<string, any>();\r\n\r\n /**\r\n * Get OAuth2 endpoint that must be cause to get the Oauth2 token\r\n * @internal\r\n */\r\n private cacheEndpoint(url: string, endpoint: ArcGisOAuth2EndpointType, obj: ArcGisOAuth2Endpoint) {\r\n if (endpoint === ArcGisOAuth2EndpointType.Authorize) {\r\n this._oauthAuthorizeEndPointsCache.set(url, obj);\r\n } else {\r\n this._oauthTokenEndPointsCache.set(url, obj);\r\n }\r\n }\r\n\r\n /**\r\n * Get OAuth2 endpoint that must be cause to get the Oauth2 token\r\n * @internal\r\n */\r\n private async createEndpoint(url: string, endpoint: ArcGisOAuth2EndpointType): Promise<ArcGisOAuth2Endpoint | undefined> {\r\n // Validate the URL we just composed\r\n const oauthEndpoint = new ArcGisOAuth2Endpoint(url, this.constructLoginUrl(url, false), false);\r\n this.cacheEndpoint(url, endpoint, oauthEndpoint);\r\n return oauthEndpoint;\r\n }\r\n\r\n /**\r\n * Returns whether the ArcGis host is valid\r\n * @internal\r\n */\r\n private isArcGisHostValid(url: URL): boolean {\r\n const allowedHosts = [\r\n \"arcgis.com\",\r\n ];\r\n\r\n return allowedHosts.some((host: string) => url.hostname.toLowerCase().endsWith(host));\r\n }\r\n\r\n /**\r\n * Get OAuth2 endpoint that must be cause to get the Oauth2 token\r\n * @internal\r\n */\r\n private async getOAuth2Endpoint(url: string, endpointType: ArcGisOAuth2EndpointType): Promise<ArcGisOAuth2Endpoint | undefined> {\r\n // Return from cache if available\r\n const cachedEndpoint = (endpointType === ArcGisOAuth2EndpointType.Authorize ? this._oauthAuthorizeEndPointsCache.get(url) : this._oauthTokenEndPointsCache.get(url));\r\n if (cachedEndpoint !== undefined) {\r\n return cachedEndpoint;\r\n }\r\n\r\n const endpointStr = (endpointType === ArcGisOAuth2EndpointType.Authorize ? \"authorize\" : \"token\");\r\n\r\n const urlObj = new URL(url);\r\n\r\n if (this.isArcGisHostValid(urlObj)) {\r\n // ArcGIS Online (fixed)\r\n // Doc: https://developers.arcgis.com/documentation/mapping-apis-and-services/security/oauth-2.0/\r\n\r\n if (this.arcGisOnlineClientId === undefined) {\r\n return undefined;\r\n }\r\n\r\n const oauth2Url = `https://www.arcgis.com/sharing/rest/oauth2/${endpointStr}`;\r\n return new ArcGisOAuth2Endpoint(oauth2Url, this.constructLoginUrl(oauth2Url, true), true);\r\n } else {\r\n\r\n // First attempt: derive the Oauth2 token URL from the 'tokenServicesUrl', exposed by the 'info request'\r\n try {\r\n const restUrlFromTokenService = await ArcGisUrl.getRestUrlFromGenerateTokenUrl(urlObj);\r\n if (restUrlFromTokenService === undefined) {\r\n // We could not derive the token endpoint from 'tokenServicesUrl'.\r\n // ArcGIS Enterprise Format https://<host>:<port>/<subdirectory>/sharing/rest/oauth2/authorize\r\n const regExMatch = url.match(new RegExp(/([^&\\/]+)\\/rest\\/services\\/.*/, \"i\"));\r\n if (regExMatch !== null && regExMatch.length >= 2) {\r\n const subdirectory = regExMatch[1];\r\n const port = (urlObj.port !== \"80\" && urlObj.port !== \"443\") ? `:${urlObj.port}` : \"\";\r\n const newUrlObj = new URL(`${urlObj.protocol}//${urlObj.hostname}${port}/${subdirectory}/sharing/rest/oauth2/${endpointStr}`);\r\n\r\n // Check again the URL we just composed\r\n return await this.createEndpoint(newUrlObj.toString(), endpointType);\r\n }\r\n } else {\r\n const endpoint = await this.createEndpoint(`${restUrlFromTokenService.toString()}oauth2/${endpointStr}`, endpointType);\r\n if (endpoint)\r\n return endpoint;\r\n }\r\n } catch {\r\n\r\n }\r\n\r\n }\r\n return undefined; // we could not find any valid oauth2 endpoint\r\n }\r\n\r\n /**\r\n * Construct the complete Authorize url to starts the Oauth process\r\n * @internal\r\n */\r\n private constructLoginUrl(url: string, isArcgisOnline: boolean) {\r\n const urlObj = new URL(url);\r\n\r\n // Set the client id\r\n if (isArcgisOnline) {\r\n const clientId = this.arcGisOnlineClientId;\r\n assert(clientId !== undefined);\r\n if (clientId !== undefined) {\r\n urlObj.searchParams.set(\"client_id\", clientId);\r\n }\r\n\r\n } else {\r\n const clientId = this.getMatchingEnterpriseClientId(url);\r\n assert(clientId !== undefined);\r\n if (undefined !== clientId) {\r\n urlObj.searchParams.set(\"client_id\", clientId);\r\n }\r\n }\r\n\r\n urlObj.searchParams.set(\"response_type\", \"token\");\r\n if (this.expiration !== undefined) {\r\n urlObj.searchParams.set(\"expiration\", `${this.expiration}`);\r\n }\r\n\r\n if (this.redirectUri)\r\n urlObj.searchParams.set(\"redirect_uri\", this.redirectUri);\r\n\r\n return urlObj.toString();\r\n }\r\n\r\n}\r\n"]}
1
+ {"version":3,"file":"ArcGisAccessClient.js","sourceRoot":"","sources":["../../../src/ArcGis/ArcGisAccessClient.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n/** @packageDocumentation\r\n * @module Tiles\r\n */\r\n\r\nimport { assert, BeEvent } from \"@itwin/core-bentley\";\r\nimport { MapLayerAccessClient, MapLayerAccessToken, MapLayerAccessTokenParams, MapLayerTokenEndpoint } from \"@itwin/core-frontend\";\r\nimport { ArcGisOAuth2Token, ArcGisTokenClientType } from \"./ArcGisTokenGenerator\";\r\nimport { ArcGisOAuth2Endpoint, ArcGisOAuth2EndpointType } from \"./ArcGisOAuth2Endpoint\";\r\nimport { ArcGisTokenManager } from \"./ArcGisTokenManager\";\r\nimport { ArcGisUrl } from \"./ArcGisUrl\";\r\n\r\n/** @beta */\r\nexport interface ArcGisEnterpriseClientId {\r\n /* Oauth API endpoint base URL (i.e. https://hostname/portal/sharing/oauth2/authorize)\r\n used to identify uniquely each enterprise server. */\r\n serviceBaseUrl: string;\r\n\r\n /* Application's clientId for this enterprise server.*/\r\n clientId: string;\r\n}\r\n\r\n/** @beta */\r\nexport interface ArcGisOAuthClientIds {\r\n /* Application's OAuth clientId in ArcGIS online */\r\n arcgisOnlineClientId?: string;\r\n\r\n /* Application's OAuth clientId for each enterprise server used. */\r\n enterpriseClientIds?: ArcGisEnterpriseClientId[];\r\n}\r\n\r\n/** @beta\r\n * ArcGIS OAuth configurations parameters.\r\n * See https://developers.arcgis.com/documentation/mapping-apis-and-services/security/arcgis-identity/serverless-web-apps/\r\n * more details.\r\n*/\r\nexport interface ArcGisOAuthConfig {\r\n /* URL to which a user is sent once they complete sign in authorization.\r\n Must match a URI you define in the developer dashboard, otherwise, the authorization will be rejected.\r\n */\r\n redirectUri: string;\r\n\r\n /* Optional expiration after which the token will expire. Defined in minutes with a maximum of two weeks (20160 minutes)*/\r\n tokenExpiration?: number;\r\n\r\n /* Application client Ids */\r\n clientIds: ArcGisOAuthClientIds;\r\n}\r\n\r\ninterface EndPointsCacheEntry {\r\n authorizeEndpoint?: ArcGisOAuth2Endpoint;\r\n tokenEndpoint?: ArcGisOAuth2Endpoint;\r\n}\r\n\r\ntype MapLayerUrl = string;\r\n\r\n/** @beta */\r\nexport class ArcGisAccessClient implements MapLayerAccessClient {\r\n public readonly onOAuthProcessEnd = new BeEvent();\r\n private _redirectUri: string | undefined;\r\n private _expiration: number | undefined;\r\n private _clientIds: ArcGisOAuthClientIds | undefined;\r\n\r\n // Should be kept to 'false'. Debugging purposes only.\r\n private _forceLegacyToken = false;\r\n\r\n public constructor() {\r\n }\r\n\r\n public initialize(oAuthConfig?: ArcGisOAuthConfig): boolean {\r\n if (oAuthConfig) {\r\n this._redirectUri = oAuthConfig.redirectUri;\r\n this._expiration = oAuthConfig.tokenExpiration;\r\n this._clientIds = oAuthConfig.clientIds;\r\n\r\n this.initOauthCallbackFunction();\r\n }\r\n return true;\r\n }\r\n\r\n private initOauthCallbackFunction() {\r\n (window as any).arcGisOAuth2Callback = (redirectLocation?: Location) => {\r\n let eventSuccess = false;\r\n let stateData;\r\n\r\n if (redirectLocation && redirectLocation.hash.length > 0) {\r\n const locationHash = redirectLocation.hash;\r\n const hashParams = new URLSearchParams(locationHash.substring(1));\r\n const token = hashParams.get(\"access_token\") ?? undefined;\r\n const expiresInStr = hashParams.get(\"expires_in\") ?? undefined;\r\n const userName = hashParams.get(\"username\") ?? undefined;\r\n const ssl = hashParams.get(\"ssl\") === \"true\";\r\n const stateStr = hashParams.get(\"state\") ?? undefined;\r\n const persist = hashParams.get(\"persist\") === \"true\";\r\n if (token !== undefined && expiresInStr !== undefined && userName !== undefined && ssl !== undefined && stateStr !== undefined) {\r\n let endpointOrigin;\r\n try {\r\n const state = JSON.parse(stateStr);\r\n stateData = state?.customData;\r\n endpointOrigin = state?.endpointOrigin;\r\n\r\n } catch {\r\n }\r\n const expiresIn = Number(expiresInStr);\r\n const expiresAt = (expiresIn * 1000) + (+new Date()); // Converts the token expiration delay (seconds) into a timestamp (UNIX time)\r\n if (endpointOrigin !== undefined) {\r\n ArcGisTokenManager.setOAuth2Token(endpointOrigin, { token, expiresAt, ssl, userName, persist });\r\n eventSuccess = true;\r\n }\r\n\r\n }\r\n }\r\n this.onOAuthProcessEnd.raiseEvent(eventSuccess, stateData);\r\n };\r\n }\r\n\r\n public unInitialize() {\r\n this._redirectUri = undefined;\r\n this._expiration = undefined;\r\n (window as any).arcGisOAuth2Callback = undefined;\r\n }\r\n\r\n public async getAccessToken(params: MapLayerAccessTokenParams): Promise<MapLayerAccessToken | undefined> {\r\n // First lookup Oauth2 tokens, otherwise check try \"legacy tokens\" if credentials were provided\r\n\r\n if (!this._forceLegacyToken) {\r\n const oauth2Token = await this.getOAuthTokenForMapLayerUrl(params.mapLayerUrl.toString());\r\n if (oauth2Token)\r\n return oauth2Token;\r\n }\r\n\r\n if (params.userName && params.password) {\r\n return ArcGisTokenManager.getToken(params.mapLayerUrl.toString(), params.userName, params.password, { client: ArcGisTokenClientType.referer });\r\n }\r\n\r\n return undefined;\r\n }\r\n\r\n /** @internal */\r\n public static async validateOAuth2Endpoint(endpointUrl: string): Promise<boolean> {\r\n const data = await fetch(endpointUrl, { method: \"GET\" });\r\n return data.status === 400; // Oauth2 API returns 400 (Bad Request) when there are missing parameters\r\n }\r\n\r\n public async getTokenServiceEndPoint(mapLayerUrl: string): Promise<MapLayerTokenEndpoint | undefined> {\r\n if (!this._forceLegacyToken) {\r\n return this.getOAuth2Endpoint(mapLayerUrl, ArcGisOAuth2EndpointType.Authorize);\r\n }\r\n\r\n return undefined;\r\n }\r\n\r\n public invalidateToken(token: MapLayerAccessToken): boolean {\r\n let found = ArcGisTokenManager.invalidateToken(token);\r\n if (!found) {\r\n found = ArcGisTokenManager.invalidateOAuth2Token(token);\r\n }\r\n return found;\r\n }\r\n\r\n public get redirectUri() {\r\n return this._redirectUri;\r\n }\r\n\r\n public getMatchingEnterpriseClientId(url: string) {\r\n const clientIds = this.arcGisEnterpriseClientIds;\r\n if (!clientIds) {\r\n return undefined;\r\n }\r\n\r\n let clientId: string | undefined;\r\n let defaultClientId: string | undefined;\r\n for (const entry of clientIds) {\r\n if (entry.serviceBaseUrl === \"\") {\r\n defaultClientId = entry.clientId;\r\n } else {\r\n if (url.toLowerCase().startsWith(entry.serviceBaseUrl)) {\r\n clientId = entry.clientId;\r\n }\r\n }\r\n }\r\n\r\n // If we could not find a match with serviceBaseUrl, and a default clientId\r\n // was specified (i.e empty url), then use default clientId\r\n if (clientId === undefined && defaultClientId !== undefined) {\r\n clientId = defaultClientId;\r\n }\r\n return clientId;\r\n }\r\n\r\n public get expiration() {\r\n return this._expiration;\r\n }\r\n\r\n public get arcGisOnlineClientId() {\r\n return this._clientIds?.arcgisOnlineClientId;\r\n }\r\n\r\n public set arcGisOnlineClientId(clientId: string | undefined) {\r\n if (this._clientIds === undefined) {\r\n this._clientIds = { arcgisOnlineClientId: clientId };\r\n }\r\n this._clientIds.arcgisOnlineClientId = clientId;\r\n }\r\n\r\n public get arcGisEnterpriseClientIds() {\r\n return this._clientIds?.enterpriseClientIds;\r\n }\r\n\r\n public setEnterpriseClientId(serviceBaseUrl: string, clientId: string) {\r\n\r\n if (this._clientIds?.enterpriseClientIds) {\r\n const foundIdx = this._clientIds.enterpriseClientIds.findIndex((entry) => entry.serviceBaseUrl === serviceBaseUrl);\r\n if (foundIdx !== -1) {\r\n this._clientIds.enterpriseClientIds[foundIdx].clientId = clientId;\r\n } else {\r\n this._clientIds.enterpriseClientIds.push({ serviceBaseUrl, clientId });\r\n }\r\n } else {\r\n if (this._clientIds === undefined) {\r\n this._clientIds = {};\r\n }\r\n this._clientIds.enterpriseClientIds = [{ serviceBaseUrl, clientId }];\r\n }\r\n }\r\n\r\n public removeEnterpriseClientId(clientId: ArcGisEnterpriseClientId) {\r\n\r\n if (this._clientIds?.enterpriseClientIds) {\r\n this._clientIds.enterpriseClientIds = this._clientIds?.enterpriseClientIds?.filter((item) => item.serviceBaseUrl !== clientId.serviceBaseUrl);\r\n }\r\n\r\n }\r\n\r\n /// //////////\r\n /** @internal */\r\n private async getOAuthTokenForMapLayerUrl(mapLayerUrl: string): Promise<ArcGisOAuth2Token | undefined> {\r\n try {\r\n const oauthEndpoint = await this.getOAuth2Endpoint(mapLayerUrl, ArcGisOAuth2EndpointType.Authorize);\r\n if (oauthEndpoint !== undefined) {\r\n const oauthEndpointUrl = new URL(oauthEndpoint.getUrl());\r\n return ArcGisTokenManager.getOAuth2Token(oauthEndpointUrl.origin);\r\n }\r\n } catch { }\r\n return undefined;\r\n }\r\n\r\n // Mapping between a map-layer URL and its corresponding Oauth endpoint\r\n // i.e. \t https://hostname/server/rest/services/NewYork/NewYork3857/MapServer\r\n // => https://hostname/portal/sharing/oauth2/authorize\r\n\r\n private _endPointsCache = new Map<MapLayerUrl, EndPointsCacheEntry>();\r\n\r\n /**\r\n * Get OAuth2 endpoint that must be cause to get the Oauth2 token\r\n * @internal\r\n */\r\n private cacheEndpoint(url: MapLayerUrl, endpointType: ArcGisOAuth2EndpointType, endPoint: ArcGisOAuth2Endpoint) {\r\n const entry = endpointType === ArcGisOAuth2EndpointType.Authorize ? {authorizeEndpoint: endPoint} : {tokenEndpoint: endPoint};\r\n this._endPointsCache.set(url, entry);\r\n }\r\n\r\n /**\r\n * Get OAuth2 endpoint that must be cause to get the Oauth2 token\r\n * @internal\r\n */\r\n private async createEndpoint(mapLayerUrl: MapLayerUrl, oauthEndpointUrl: string, endpointType: ArcGisOAuth2EndpointType): Promise<ArcGisOAuth2Endpoint | undefined> {\r\n // Validate the URL we just composed\r\n const oauthEndpoint = new ArcGisOAuth2Endpoint(oauthEndpointUrl, this.constructLoginUrl(oauthEndpointUrl, false), false);\r\n this.cacheEndpoint(mapLayerUrl, endpointType, oauthEndpoint);\r\n return oauthEndpoint;\r\n }\r\n\r\n /**\r\n * Returns whether the ArcGis host is valid\r\n * @internal\r\n */\r\n private isArcGisHostValid(url: URL): boolean {\r\n const allowedHosts = [\r\n \"arcgis.com\",\r\n ];\r\n\r\n return allowedHosts.some((host: string) => url.hostname.toLowerCase().endsWith(host));\r\n }\r\n\r\n private async validateEndpointUrl(url: string) {\r\n let valid: boolean|undefined;\r\n try {\r\n valid = await ArcGisAccessClient.validateOAuth2Endpoint(url.toString());\r\n } catch {\r\n // If we reach here, this means we could not validate properly the endpoint;\r\n // we cannot conclude the endpoint is invalid though; it might happen endpoint doesn't support CORS requests,\r\n // but still valid for Oauth process.\r\n }\r\n return valid;\r\n }\r\n\r\n /**\r\n * Get OAuth2 endpoint that must be cause to get the Oauth2 token\r\n * @internal\r\n */\r\n private async getOAuth2Endpoint(mapLayerUrl: string, endpointType: ArcGisOAuth2EndpointType): Promise<ArcGisOAuth2Endpoint | undefined> {\r\n // Return from cache if available\r\n const cachedEndpoint = this._endPointsCache.get(mapLayerUrl);\r\n if (cachedEndpoint !== undefined) {\r\n return (endpointType === ArcGisOAuth2EndpointType.Authorize ? cachedEndpoint.authorizeEndpoint : cachedEndpoint.authorizeEndpoint);\r\n }\r\n\r\n const endpointStr = (endpointType === ArcGisOAuth2EndpointType.Authorize ? \"authorize\" : \"token\");\r\n\r\n const urlObj = new URL(mapLayerUrl);\r\n\r\n if (this.isArcGisHostValid(urlObj)) {\r\n // ArcGIS Online (fixed)\r\n // Doc: https://developers.arcgis.com/documentation/mapping-apis-and-services/security/oauth-2.0/\r\n\r\n if (this.arcGisOnlineClientId === undefined) {\r\n return undefined;\r\n }\r\n\r\n const oauth2Url = `https://www.arcgis.com/sharing/rest/oauth2/${endpointStr}`;\r\n return new ArcGisOAuth2Endpoint(oauth2Url, this.constructLoginUrl(oauth2Url, true), true);\r\n } else {\r\n\r\n // First attempt: derive the Oauth2 token URL from the 'tokenServicesUrl', exposed by the 'info request'\r\n try {\r\n const restUrlFromTokenService = await ArcGisUrl.getRestUrlFromGenerateTokenUrl(urlObj);\r\n\r\n if (restUrlFromTokenService === undefined) {\r\n // We could not derive the token endpoint from 'tokenServicesUrl'.\r\n // ArcGIS Enterprise Format https://<host>:<port>/<subdirectory>/sharing/rest/oauth2/authorize\r\n const regExMatch = mapLayerUrl.match(new RegExp(/([^&\\/]+)\\/rest\\/services\\/.*/, \"i\"));\r\n if (regExMatch !== null && regExMatch.length >= 2) {\r\n const subdirectory = regExMatch[1];\r\n const port = (urlObj.port !== \"80\" && urlObj.port !== \"443\") ? `:${urlObj.port}` : \"\";\r\n const newUrlObj = new URL(`${urlObj.protocol}//${urlObj.hostname}${port}/${subdirectory}/sharing/rest/oauth2/${endpointStr}`);\r\n\r\n // Check again the URL we just composed\r\n const isValidUrl = await this.validateEndpointUrl(newUrlObj.toString());\r\n if (isValidUrl === undefined || isValidUrl ) {\r\n const endpoint = await this.createEndpoint(mapLayerUrl, newUrlObj.toString(), endpointType);\r\n if (endpoint)\r\n return endpoint;\r\n }\r\n }\r\n } else {\r\n const isValidUrl = await this.validateEndpointUrl(restUrlFromTokenService.toString());\r\n if (isValidUrl === undefined || isValidUrl ) {\r\n const endpoint = await this.createEndpoint(mapLayerUrl, `${restUrlFromTokenService.toString()}oauth2/${endpointStr}`, endpointType);\r\n if (endpoint)\r\n return endpoint;\r\n }\r\n }\r\n } catch {\r\n }\r\n }\r\n\r\n // If we reach here, we were not successful creating an endpoint\r\n this._endPointsCache.set(mapLayerUrl, {}); // Cache an empty entry, and avoid making repeated failing requests.\r\n\r\n return undefined; // we could not find any valid oauth2 endpoint\r\n }\r\n\r\n /**\r\n * Construct the complete Authorize url to starts the Oauth process\r\n * @internal\r\n */\r\n private constructLoginUrl(url: string, isArcgisOnline: boolean) {\r\n const urlObj = new URL(url);\r\n\r\n // Set the client id\r\n if (isArcgisOnline) {\r\n const clientId = this.arcGisOnlineClientId;\r\n assert(clientId !== undefined);\r\n if (clientId !== undefined) {\r\n urlObj.searchParams.set(\"client_id\", clientId);\r\n }\r\n\r\n } else {\r\n const clientId = this.getMatchingEnterpriseClientId(url);\r\n assert(clientId !== undefined);\r\n if (undefined !== clientId) {\r\n urlObj.searchParams.set(\"client_id\", clientId);\r\n }\r\n }\r\n\r\n urlObj.searchParams.set(\"response_type\", \"token\");\r\n if (this.expiration !== undefined) {\r\n urlObj.searchParams.set(\"expiration\", `${this.expiration}`);\r\n }\r\n\r\n if (this.redirectUri)\r\n urlObj.searchParams.set(\"redirect_uri\", this.redirectUri);\r\n\r\n return urlObj.toString();\r\n }\r\n\r\n}\r\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@itwin/map-layers-auth",
3
- "version": "4.3.0-dev.9",
3
+ "version": "4.4.0-dev.1",
4
4
  "description": "Extension that adds a Map Layers Widget",
5
5
  "main": "lib/cjs/map-layers-auth.js",
6
6
  "module": "lib/esm/map-layers-auth.js",
@@ -39,13 +39,13 @@
39
39
  "sinon-chai": "^3.2.0",
40
40
  "source-map-support": "^0.5.6",
41
41
  "typescript": "~5.0.2",
42
- "@itwin/build-tools": "4.3.0-dev.9",
43
- "@itwin/core-bentley": "4.3.0-dev.9",
44
- "@itwin/core-common": "4.3.0-dev.9",
45
- "@itwin/core-frontend": "4.3.0-dev.9"
42
+ "@itwin/core-frontend": "4.4.0-dev.1",
43
+ "@itwin/build-tools": "4.4.0-dev.1",
44
+ "@itwin/core-bentley": "4.4.0-dev.1",
45
+ "@itwin/core-common": "4.4.0-dev.1"
46
46
  },
47
47
  "peerDependencies": {
48
- "@itwin/core-bentley": "4.3.0-dev.9"
48
+ "@itwin/core-bentley": "4.4.0-dev.1"
49
49
  },
50
50
  "nyc": {
51
51
  "extends": "./node_modules/@itwin/build-tools/.nycrc",