diff --git a/packages/arcgis-rest-auth/src/UserSession.ts b/packages/arcgis-rest-auth/src/UserSession.ts index 69221068e0..6d1580e63e 100644 --- a/packages/arcgis-rest-auth/src/UserSession.ts +++ b/packages/arcgis-rest-auth/src/UserSession.ts @@ -651,10 +651,9 @@ export class UserSession implements IAuthenticationManager { // if a non-federated server was passed explicitly, it should be trusted. if (options.server) { // if the url includes more than '/arcgis/', trim the rest - const [serverRoot] = options.server - .toLowerCase() - .split(/\/rest(\/admin)?\/services\//); - this.trustedServers[serverRoot] = { + const root = this.getServerRootUrl(options.server); + + this.trustedServers[root] = { token: options.token, expires: options.tokenExpires }; @@ -776,6 +775,21 @@ export class UserSession implements IAuthenticationManager { return Promise.reject(new ArcGISAuthError("Unable to refresh token.")); } + /** + * Determines the root of the ArcGIS Server or Portal for a given URL. + * + * @param url the URl to determine the root url for. + */ + public getServerRootUrl(url: string) { + const [root] = url.split(/\/rest(\/admin)?\/services\//); + const [match, protocol, domainAndPath] = root.match(/(https?:\/\/)(.+)/); + const [domain, ...path] = domainAndPath.split("/"); + + // only the domain is lowercased becasue in some cases an org id might be + // in the path which cannot be lowercased. + return `${protocol}${domain.toLowerCase()}/${path.join("/")}`; + } + /** * Validates that a given URL is properly federated with our current `portal`. * Attempts to use the internal `trustedServers` cache first. @@ -786,7 +800,7 @@ export class UserSession implements IAuthenticationManager { ) { // requests to /rest/services/ and /rest/admin/services/ are both valid // Federated servers may have inconsistent casing, so lowerCase it - const [root] = url.toLowerCase().split(/\/rest(\/admin)?\/services\//); + const root = this.getServerRootUrl(url); const existingToken = this.trustedServers[root]; if ( diff --git a/packages/arcgis-rest-auth/test/UserSession.test.ts b/packages/arcgis-rest-auth/test/UserSession.test.ts index e19b76aa0e..7e8cae3069 100644 --- a/packages/arcgis-rest-auth/test/UserSession.test.ts +++ b/packages/arcgis-rest-auth/test/UserSession.test.ts @@ -1133,6 +1133,51 @@ describe("UserSession", () => { }); }); + describe("getServerRootUrl()", () => { + it("should lowercase domain names", () => { + const session = new UserSession({ + clientId: "id", + token: "token", + tokenExpires: TOMORROW + }); + + const root = session.getServerRootUrl( + "https://PNP00035.esri.com/server/rest/services/Hosted/perimeters_dd83/FeatureServer" + ); + expect(root).toEqual("https://pnp00035.esri.com/server"); + }); + + it("should not lowercase path names", () => { + const session = new UserSession({ + clientId: "id", + token: "token", + tokenExpires: TOMORROW + }); + + const root = session.getServerRootUrl( + "https://pnp00035.esri.com/tiles/LkFyxb9zDq7vAOAm/arcgis/rest/services/NB_Stereographic/VectorTileServer" + ); + expect(root).toEqual( + "https://pnp00035.esri.com/tiles/LkFyxb9zDq7vAOAm/arcgis" + ); + }); + + it("should respect the original https/http protocol", () => { + const session = new UserSession({ + clientId: "id", + token: "token", + tokenExpires: TOMORROW + }); + + const root = session.getServerRootUrl( + "http://pnp00035.esri.com/tiles/LkFyxb9zDq7vAOAm/arcgis/rest/services/NB_Stereographic/VectorTileServer" + ); + expect(root).toEqual( + "http://pnp00035.esri.com/tiles/LkFyxb9zDq7vAOAm/arcgis" + ); + }); + }); + describe("non-federated server", () => { it("shouldnt fetch a fresh token if the current one isnt expired.", done => { const MOCK_USER_SESSION = new UserSession({