UNPKG

@arcgis/core

Version:

ArcGIS Maps SDK for JavaScript: A complete 2D and 3D mapping and data visualization API

3 lines (2 loc) • 33.9 kB
/* COPYRIGHT Esri - https://js.arcgis.com/5.0.19/LICENSE.txt */ import e from"../config.js";import t from"../request.js";import r from"../core/Error.js";import{Evented as s}from"../core/Evented.js";import{on as i}from"../core/events.js";import{fixJson as n}from"../core/lang.js";import{getDeepValue as o}from"../core/object.js";import{createResolver as a,onAbort as h,isAborted as l}from"../core/promiseUtils.js";import{urlToObject as c,hasSameOrigin as d,Url as u,queryToObject as p,base64UrlEncode as _,objectToQuery as f,normalize as g,getProxyRule as m,makeAbsolute as v,addQueryParameters as S}from"../core/urlUtils.js";import w from"./Credential.js";import I from"./IdentityModal.js";import k from"./OAuthCredential.js";import A from"./OAuthInfo.js";import U from"./ServerInfo.js";import{isSecureProxyService as y,normalizeArcGISOnlineOrgDomain as P}from"../portal/support/urlUtils.js";const x={},O=e=>{const t=new u(e.owningSystemUrl).host,r=new u(e.server).host,s=/.+\.arcgis\.com$/i;return s.test(t)&&s.test(r)},T=(e,t)=>!!(O(e)&&t&&t.some(t=>t.test(e.server)));let R=null,C=null;try{R=window.localStorage,C=window.sessionStorage}catch{}class D extends s{constructor(){super(),this._portalConfig=globalThis.esriGeowConfig,this.serverInfos=[],this.oAuthInfos=[],this.credentials=[],this._soReqs=[],this._xoReqs=[],this._portals=[],this._defaultOAuthInfo=null,this._defaultTokenValidity=60,this.dialog=null,this.tokenValidity=null,this.normalizeWebTierAuth=!1,this._appOrigin="null"!==window.origin?window.origin:window.location.origin,this._appUrlObj=c(window.location.href),this._busy=null,this._rejectOnPersistedPageShow=!1,this._oAuthLocationParams=null,this._gwTokenUrl="/sharing/rest/generateToken",this._agsRest="/rest/services",this._agsPortal=/\/sharing(\/|$)/i,this._agsAdmin=/(https?:\/\/[^/]+\/[^/]+)\/admin\/?(\/.*)?$/i,this._adminSvcs=/\/rest\/admin\/services(\/|$)/i,this._gwDomains=[{regex:/^https?:\/\/www\.arcgis\.com/i,customBaseUrl:"maps.arcgis.com",tokenServiceUrl:"https://www.arcgis.com/sharing/rest/generateToken"},{regex:/^https?:\/\/(?:dev|[a-z\d-]+\.mapsdev)\.arcgis\.com/i,customBaseUrl:"mapsdev.arcgis.com",tokenServiceUrl:"https://dev.arcgis.com/sharing/rest/generateToken"},{regex:/^https?:\/\/(?:devext|[a-z\d-]+\.mapsdevext)\.arcgis\.com/i,customBaseUrl:"mapsdevext.arcgis.com",tokenServiceUrl:"https://devext.arcgis.com/sharing/rest/generateToken"},{regex:/^https?:\/\/(?:qaext|[a-z\d-]+\.mapsqa)\.arcgis\.com/i,customBaseUrl:"mapsqa.arcgis.com",tokenServiceUrl:"https://qaext.arcgis.com/sharing/rest/generateToken"},{regex:/^https?:\/\/[a-z\d-]+\.maps\.arcgis\.com/i,customBaseUrl:"maps.arcgis.com",tokenServiceUrl:"https://www.arcgis.com/sharing/rest/generateToken"}],this._legacyFed=[],this._regexSDirUrl=/http.+\/rest\/services\/?/gi,this._regexServerType=/(\/(FeatureServer|GPServer|GeoDataServer|GeocodeServer|GeoenrichmentServer|GeometryServer|GlobeServer|ImageServer|KnowledgeGraphServer|MapServer|MissionServer|MobileServer|NAServer|NetworkDiagramServer|OGCFeatureServer|ParcelFabricServer|RelationalCatalogServer|SceneServer|StreamServer|UtilityNetworkServer|ValidationServer|VectorTileServer|VersionManagementServer|VideoServer|3DTilesServer)).*/gi,this._gwUser=/http.+\/users\/([^/]+).*/i,this._gwItem=/http.+\/items\/([^/]+).*/i,this._gwGroup=/http.+\/groups\/([^/]+).*/i,this._rePortalTokenSvc=/\/sharing(\/rest)?\/generatetoken/i,this._createDefaultOAuthInfo=!0,this._hasTestedIfAppIsOnPortal=!1,this._getPlatformSelfError=null,this._getOAuthLocationParams(),window.addEventListener("pageshow",e=>{this._pageShowHandler(e)})}registerServers(e){const t=this.serverInfos;t?(e=e.filter(e=>!this.findServerInfo(e.server)),this.serverInfos=t.concat(e)):this.serverInfos=e,e.forEach(e=>{e.owningSystemUrl&&this._portals.push(e.owningSystemUrl),e.hasPortal&&this._portals.push(e.server)})}registerOAuthInfos(e){const t=this.oAuthInfos;if(t){for(const r of e){const e=this.findOAuthInfo(r.portalUrl);e&&t.splice(t.indexOf(e),1)}this.oAuthInfos=t.concat(e)}else this.oAuthInfos=e}registerToken(e){e={...e};const t=this._sanitizeUrl(e.server),r=this._isServerRsrc(t);let s,i=this.findServerInfo(t),n=!0;i||(i=new U,i.server=this._getServerInstanceRoot(t),r?i.hasServer=!0:(i.tokenServiceUrl=this._getTokenSvcUrl(t),i.hasPortal=!0),this.registerServers([i])),s=this._findCredential(t),s?(delete e.server,Object.assign(s,e),n=!1):(s=new w({userId:e.userId,server:i.server??void 0,token:e.token,expires:e.expires,ssl:e.ssl,scope:r?"server":"portal"}),s.resources=[t],this.credentials.push(s)),s.emitTokenChange(!1),n||s.refreshServerTokens()}toJSON(){return n({serverInfos:this.serverInfos.map(e=>e.toJSON()),oAuthInfos:this.oAuthInfos.map(e=>e.toJSON()),credentials:this.credentials.map(e=>e.toJSON())})}initialize(e){if(!e)return;"string"==typeof e&&(e=JSON.parse(e));const t=e.serverInfos,r=e.oAuthInfos,s=e.credentials;if(t){const e=[];t.forEach(t=>{t.server&&t.tokenServiceUrl&&e.push(t.declaredClass?t:new U(t))}),e.length&&this.registerServers(e)}if(r){const e=[];r.forEach(t=>{t.appId&&e.push(t.declaredClass?t:new A(t))}),e.length&&this.registerOAuthInfos(e)}s&&s.forEach(e=>{e.server&&e.token&&e.expires&&e.expires>Date.now()&&((e=e.declaredClass?e:new w(e)).emitTokenChange(),this.credentials.push(e))})}findServerInfo(e){let t;e=this._sanitizeUrl(e);for(const r of this.serverInfos)if(this._hasSameServerInstance(r.server,e)){t=r;break}return t}findOAuthInfo(e){let t;e=this._sanitizeUrl(e);for(const r of this.oAuthInfos)if(this._hasSameServerInstance(r.portalUrl,e)){t=r;break}return t}findCredential(e,t){if(!e)return;let r;e=this._sanitizeUrl(e);const s=this._isServerRsrc(e)?"server":"portal";if(t){for(const i of this.credentials)if(this._hasSameServerInstance(i.server,e)&&t===i.userId&&i.scope===s){r=i;break}}else for(const i of this.credentials)if(this._hasSameServerInstance(i.server,e)&&-1!==this._getIdenticalSvcIdx(e,i)&&i.scope===s){r=i;break}return r}getCredential(e,t){let s,i=!1,n=!0;t&&(i=!(!t.token&&!t.credential),s=t.error,n=!1!==t.prompt),t={...t},e=this._sanitizeUrl(e);const o=new AbortController,c=a();if(t.signal&&h(t.signal,()=>{o.abort()}),h(o,()=>{c.reject(new r("identity-manager:user-aborted","ABORTED"))}),l(o))return c.promise;t.signal=o.signal;const u=this._isAdminResource(e),p=i?this.findCredential(e):null;let _;if(p&&498===s?.details?.httpStatus)p.destroy();else if(p)return _=new r("identity-manager:not-authorized","You are currently signed in as: '"+p.userId+"'. You do not have access to this resource: "+e,{error:s}),c.reject(_),c.promise;const f=this._findCredential(e,t);if(f)return c.resolve(f),c.promise;let g=this.findServerInfo(e);if(g)!g.hasPortal&&g.server&&g.owningSystemUrl&&this._hasSameServerInstance(g.server,g.owningSystemUrl)&&(g.hasPortal=!0),!g.hasServer&&this._isServerRsrc(e)&&(g._restInfoPms=this._getTokenSvcUrl(e),g.hasServer=!0);else{const t=this._getTokenSvcUrl(e);if(!t)return _=new r("identity-manager:unknown-resource","Unknown resource - could not find token service endpoint."),c.reject(_),c.promise;g=new U,g.server=this._getServerInstanceRoot(e),"string"==typeof t?(g.tokenServiceUrl=t,g.hasPortal=!0):(g._restInfoPms=t,g.hasServer=!0),this.registerServers([g])}return g.hasPortal&&void 0===g._selfReq&&(n||d(g.tokenServiceUrl,this._appOrigin)||this._gwDomains.some(e=>e.tokenServiceUrl===g.tokenServiceUrl))&&(g._selfReq={owningTenant:t?.owningTenant,selfDfd:this._getPortalSelf(g.tokenServiceUrl.replace(this._rePortalTokenSvc,"/sharing/rest/portals/self"),e)}),this._enqueue(e,g,t,c,u)}getResourceName(e){return this._isRESTService(e)?e.replace(this._regexSDirUrl,"").replace(this._regexServerType,"")||"":this._gwUser.test(e)&&e.replace(this._gwUser,"$1")||this._gwItem.test(e)&&e.replace(this._gwItem,"$1")||this._gwGroup.test(e)&&e.replace(this._gwGroup,"$1")||""}generateToken(e,s,i){const n=this._rePortalTokenSvc.test(e.tokenServiceUrl),o=new u(this._appOrigin),a=e.shortLivedTokenValidity;let h,l,c,p,_,f,g,m;s&&(m=this.tokenValidity||a||this._defaultTokenValidity,m>a&&a>0&&(m=a)),i&&(h=i.isAdmin,l=i.serverUrl,c=i.token,f=i.signal,g=i.ssl,e.customParameters=i.customParameters),h?p=e.adminTokenServiceUrl:(p=e.tokenServiceUrl,_=new u(p.toLowerCase()),e.webTierAuth&&i?.serverUrl&&!g&&"http"===o.scheme&&(d(o.uri,p,!0)||"https"===_.scheme&&o.host===_.host&&"7080"===o.port&&"7443"===_.port)&&(p=p.replace(/^https:/i,"http:").replace(/:7443/i,":7080")));const v={query:{request:"getToken",username:s?.username,password:s?.password,serverUrl:l,token:c,expiration:m,referer:h||n?this._appOrigin:null,client:h?"referer":null,f:"json",...e.customParameters},method:"post",authMode:"anonymous",useProxy:this._useProxy(e,i),signal:f};n||(v.withCredentials=!1);return t(p,v).then(t=>{const i=t.data;if(!i?.token)return new r("identity-manager:authentication-failed","Unable to generate token");const n=e.server;return x[n]||(x[n]={}),s&&(x[n][s.username]=s.password),i.validity=m,i})}isBusy(){return!!this._busy}async checkSignInStatus(e){return(await this.checkAppAccess(e,"")).credential}checkAppAccess(e,s,i){let n=!1;return this.getCredential(e,{prompt:!1}).then(o=>{let a;const h={f:"json"};if("portal"===o.scope)if(s&&(this._doPortalSignIn(e)||i?.force))a=o.server+"/sharing/rest/oauth2/validateAppAccess",h.client_id=s;else{if(!o.token)return{credential:o};a=o.server+"/sharing/rest"}else{if(!o.token)return{credential:o};a=o.server+"/rest/services"}return o.token&&(h.token=o.token),t(a,{query:h,authMode:"anonymous"}).then(e=>{if(!1===e.data.valid)throw new r("identity-manager:not-authorized",`You are currently signed in as: '${o.userId}'.`,e.data);return n=!!e.data.viewOnlyUserTypeApp,{credential:o}}).catch(e=>{if("identity-manager:not-authorized"===e.name)throw e;const t=e.details?.httpStatus;if(498===t)throw o.destroy(),new r("identity-manager:not-authenticated","User is not signed in.");if(400===t)throw new r("identity-manager:invalid-request","Bad request");return{credential:o}})}).then(e=>({credential:e.credential,viewOnly:n}))}setOAuthResponseHash(e){e&&(e.startsWith("#")&&(e=e.slice(1)),this._processOAuthPopupParams(p(e)))}setOAuthRedirectionHandler(e){this._oAuthRedirectFunc=e}setProtocolErrorHandler(e){this._protocolFunc=e}signIn(e,t,s={}){const i=a(),n=()=>{c?.remove(),d?.remove(),this.dialog?.destroy(),this.dialog=c=d=null},o=()=>{n(),this._oAuthDfd=null,i.reject(new r("identity-manager:user-aborted","ABORTED"))};s.signal&&h(s.signal,()=>{o()});const l=new I({open:!0,resource:this.getResourceName(e),server:t.server});this.dialog=l,this.emit("dialog-create");let c=l.on("cancel",o),d=l.on("submit",e=>{this.generateToken(t,e,{isAdmin:s.isAdmin,signal:s.signal}).then(r=>{n();const o=new w({userId:e.username,server:t.server??void 0,token:r.token,expires:null!=r.expires?Number(r.expires):null,ssl:!!r.ssl,isAdmin:s.isAdmin,validity:r.validity});i.resolve(o)}).catch(e=>{l.error=e,l.signingIn=!1})});return i.promise}oAuthSignIn(e,t,s,i){this._oAuthDfd=a();const n=this._oAuthDfd;let o;i?.signal&&h(i.signal,()=>{const e=this._oAuthDfd&&this._oAuthDfd.oAuthWin_;e&&!e.closed?e.close():this.dialog&&u()}),n.resUrl_=e,n.sinfo_=t,n.oinfo_=s;const l=s._oAuthCred;if(l.storage&&("authorization-code"===s.flowType||"auto"===s.flowType&&t.currentVersion>=8.4)){let e=crypto.getRandomValues(new Uint8Array(32));o=_(e),l.codeVerifier=o,e=crypto.getRandomValues(new Uint8Array(32)),l.stateUID=_(e),l.save()||(l.codeVerifier=o=null)}else l.codeVerifier=null;let c,d;this._getCodeChallenge(o).then(r=>{const n=!i||!1!==i.oAuthPopupConfirmation;if(!s.popup||!n)return void this._doOAuthSignIn(e,t,s,r);const o=new I({oAuthPrompt:!0,server:t.server,open:!0});this.dialog=o,this.emit("dialog-create"),c=o.on("cancel",u),d=o.on("submit",()=>{p(),this._doOAuthSignIn(e,t,s,r)})});const u=()=>{p(),this._oAuthDfd=null,n.reject(new r("identity-manager:user-aborted","ABORTED"))},p=()=>{c?.remove(),d?.remove(),this.dialog?.destroy(),this.dialog=null};return n.promise}async refreshToken(e){const t=this.findServerInfo(e.server),r=t?.owningSystemUrl,s=!!r&&"server"===e.scope,i=s&&T(t,this._legacyFed),n=t.webTierAuth,o=n&&this.normalizeWebTierAuth,a=x[e.server],h=a?.[e.userId];let l,c=e.resources&&e.resources[0],d=s?this.findServerInfo(r):null,u={username:e.userId,password:h};if(n&&!o)return;s&&!d&&this.serverInfos.some(e=>(this._isIdProvider(r,e.server)&&(d=e),!!d));const p=d?this.findCredential(d.server,e.userId):null;if(!s||p){if(!i){if(s)l={serverUrl:c,token:p?.token,ssl:p?.ssl};else if(o)u=null,l={ssl:e.ssl};else{if(!h){let r;return c&&(c=this._sanitizeUrl(c),e._enqueued=1,r=this._enqueue(c,t,null,null,e.isAdmin,e),r.then(()=>{e._enqueued=0,e.refreshServerTokens()}).catch(()=>{e._enqueued=0})),r}e.isAdmin&&(l={isAdmin:!0})}return this.generateToken(s?d:t,s?null:u,l).then(t=>{e.token=t.token,e.expires=null!=t.expires?Number(t.expires):null,e.creationTime=Date.now(),e.validity=t.validity,e.emitTokenChange(),e.refreshServerTokens()}).catch(()=>{})}p?.refreshToken()}}refreshServerTokens(e){"portal"===e.scope&&this.credentials.forEach(t=>{const r=this.findServerInfo(t.server),s=r?.owningSystemUrl;t!==e&&t.userId===e.userId&&s&&"server"===t.scope&&(this._hasSameServerInstance(e.server,s)||this._isIdProvider(s,e.server))&&(T(r,this._legacyFed)?(t.token=e.token,t.expires=e.expires,t.creationTime=e.creationTime,t.validity=e.validity,t.emitTokenChange()):t.refreshToken())})}destroyCredentials(){if(this.credentials){this.credentials.slice().forEach(e=>{e.destroy()})}this.emit("credentials-destroy")}enablePostMessageAuth(e="https://www.arcgis.com/sharing/rest"){this._postMessageAuthHandle&&this._postMessageAuthHandle.remove(),this._postMessageAuthHandle=i(window,"message",t=>{if((t.origin===this._appOrigin||t.origin.endsWith(".arcgis.com"))&&"arcgis:auth:requestCredential"===t.data?.type){const r=t.source;this.getCredential(e).then(e=>{r.postMessage({type:"arcgis:auth:credential",credential:{expires:e.expires,server:e.server,ssl:e.ssl,token:e.token,userId:e.userId}},t.origin)}).catch(e=>{r.postMessage({type:"arcgis:auth:error",error:{name:e.name,message:e.message}},t.origin)})}})}disablePostMessageAuth(){this._postMessageAuthHandle&&(this._postMessageAuthHandle.remove(),this._postMessageAuthHandle=null)}_getOAuthLocationParams(){let e=window.location.hash;if(e){e.startsWith("#")&&(e=e.slice(1));const t=p(e);let r=!1;if(t.access_token&&t.expires_in&&t.state&&t.hasOwnProperty("username"))try{t.state=JSON.parse(t.state),t.state.portalUrl&&(this._oAuthLocationParams=t,r=!0)}catch{}else if(t.error&&t.error_description&&(console.log("IdentityManager OAuth Error: ",t.error," - ",t.error_description),"access_denied"===t.error&&(r=!0,t.state)))try{t.state=JSON.parse(t.state)}catch{}r&&(window.location.hash=t.state?.hash||"")}let t=window.location.search;if(t){t.startsWith("?")&&(t=t.slice(1));const e=p(t);let r=!1;if(e.code&&e.state)try{e.state=JSON.parse(e.state),e.state.portalUrl&&e.state.uid&&(this._oAuthLocationParams=e,r=!0)}catch{}else if(e.error&&e.error_description&&(console.log("IdentityManager OAuth Error: ",e.error," - ",e.error_description),"access_denied"===e.error&&(r=!0,e.state)))try{e.state=JSON.parse(e.state)}catch{}if(r){const t={...e};["code","error","error_description","message_code","persist","state"].forEach(e=>{delete t[e]});const r=f(t),s=window.location.pathname+(r?`?${r}`:"")+(e.state?.hash||"");window.history.replaceState(window.history.state,"",s)}}}_getOAuthToken(e,r,s,i,n){return e=e.replace(/^http:/i,"https:"),t(`${e}/sharing/rest/oauth2/token`,{authMode:"anonymous",method:"post",query:i&&n?{grant_type:"authorization_code",code:r,redirect_uri:i,client_id:s,code_verifier:n}:{grant_type:"refresh_token",refresh_token:r,client_id:s}}).then(e=>e.data)}async _getCodeChallenge(e){if(e&&globalThis.isSecureContext){const t=(new TextEncoder).encode(e),r=await crypto.subtle.digest("SHA-256",t);return _(new Uint8Array(r))}return null}_pageShowHandler(e){if(e.persisted&&this.isBusy()&&this._rejectOnPersistedPageShow){const e=new r("identity-manager:user-aborted","ABORTED");this._errbackFunc(e)}}_findCredential(e,t){let r,s,i,n,o=-1;const a=t?.token,h=t?.resource,l=this._isServerRsrc(e)?"server":"portal",c=this.credentials.filter(t=>this._hasSameServerInstance(t.server,e)&&t.scope===l);if(e=h||e,c.length)if(1===c.length){if(r=c[0],i=this.findServerInfo(r.server),s=i?.owningSystemUrl,n=s?this.findCredential(s,r.userId):void 0,o=this._getIdenticalSvcIdx(e,r),!a)return-1===o&&r.resources.push(e),this._addResource(e,n),r;-1!==o&&(r.resources.splice(o,1),this._removeResource(e,n))}else{let t,r;if(c.some(a=>(r=this._getIdenticalSvcIdx(e,a),-1!==r&&(t=a,i=this.findServerInfo(t.server),s=i?.owningSystemUrl,n=s?this.findCredential(s,t.userId):void 0,o=r,!0))),a)t&&(t.resources.splice(o,1),this._removeResource(e,n));else if(t)return this._addResource(e,n),t}}_findOAuthInfo(e){let t=this.findOAuthInfo(e);if(!t)for(const r of this.oAuthInfos)if(this._isIdProvider(r.portalUrl,e)){t=r;break}return t}_addResource(e,t){t&&-1===this._getIdenticalSvcIdx(e,t)&&t.resources.push(e)}_removeResource(e,t){let r=-1;t&&(r=this._getIdenticalSvcIdx(e,t),r>-1&&t.resources.splice(r,1))}_useProxy(e,t){return t?.isAdmin&&!d(e.adminTokenServiceUrl,this._appOrigin)||!this._isPortalDomain(e.tokenServiceUrl)&&"10.1"===String(e.currentVersion)&&!d(e.tokenServiceUrl,this._appOrigin)}_getOrigin(e){const t=new u(e);return t.scheme+"://"+t.host+(null!=t.port?":"+t.port:"")}_getServerInstanceRoot(e){const t=e.toLowerCase();let r=t.indexOf(this._agsRest);return-1===r&&this._isAdminResource(e)&&(r=this._agsAdmin.test(e)?e.replace(this._agsAdmin,"$1").length:e.search(this._adminSvcs)),-1!==r||y(t)||(r=t.indexOf("/sharing")),-1===r&&t.endsWith("/")&&(r=t.length-1),r>-1?e.slice(0,r):e}_hasSameServerInstance(e,t){return e.endsWith("/")&&(e=e.slice(0,-1)),e=e.toLowerCase(),t=this._getServerInstanceRoot(t).toLowerCase(),e=P(e),t=P(t),(e=e.slice(Math.max(0,e.indexOf(":"))))===(t=t.slice(Math.max(0,t.indexOf(":"))))}_sanitizeUrl(t){const r=(e.request.proxyUrl||"").toLowerCase(),s=r?t.toLowerCase().indexOf(r+"?"):-1;return-1!==s&&(t=t.slice(s+r.length+1)),t=g(t),c(t).path}_isRESTService(e){return e.includes(this._agsRest)}_isAdminResource(e){return this._agsAdmin.test(e)||this._adminSvcs.test(e)}_isServerRsrc(e){return this._isRESTService(e)||this._isAdminResource(e)}_isIdenticalService(e,t){let r=!1;if(this._isRESTService(e)&&this._isRESTService(t)){const s=this._getSuffix(e).toLowerCase(),i=this._getSuffix(t).toLowerCase();if(r=s===i,!r){const e=/(.*)\/(MapServer|FeatureServer|UtilityNetworkServer).*/gi;r=s.replaceAll(e,"$1")===i.replaceAll(e,"$1")}}else this._isAdminResource(e)&&this._isAdminResource(t)?r=!0:this._isServerRsrc(e)||this._isServerRsrc(t)||!this._isPortalDomain(e)||(r=!0);return r}_isPortalDomain(t){const r=new u(t.toLowerCase()),s=this._portalConfig;let i=this._gwDomains.some(e=>e.regex.test(r.uri));return!i&&s&&(i=this._hasSameServerInstance(this._getServerInstanceRoot(s.restBaseUrl),r.uri)),i||e.portalUrl&&(i=d(r,e.portalUrl,!0)),i||(i=this._portals.some(e=>this._hasSameServerInstance(e,r.uri))),i=i||this._agsPortal.test(r.path),i}_isIdProvider(e,t){let r=-1,s=-1;this._gwDomains.forEach((i,n)=>{-1===r&&i.regex.test(e)&&(r=n),-1===s&&i.regex.test(t)&&(s=n)});let i=!1;if(r>-1&&s>-1&&(0===r||4===r?0!==s&&4!==s||(i=!0):1===r?1!==s&&2!==s||(i=!0):2===r?2===s&&(i=!0):3===r&&3===s&&(i=!0)),!i){const r=this.findServerInfo(t),s=r?.owningSystemUrl;s&&O(r)&&this._isPortalDomain(s)&&this._isIdProvider(e,s)&&(i=!0)}return i}_getIdenticalSvcIdx(e,t){let r=-1;for(let s=0;s<t.resources.length;s++){const i=t.resources[s];if(this._isIdenticalService(e,i)){r=s;break}}return r}_getSuffix(e){return e.replace(this._regexSDirUrl,"").replace(this._regexServerType,"$1")}_getTokenSvcUrl(e){let r,s,i;if(this._isRESTService(e)||this._isAdminResource(e)){const i=this._getServerInstanceRoot(e);return r=i+"/admin/generateToken",s=t(e=i+"/rest/info",{query:{f:"json"}}).then(e=>e.data),{adminUrl:r,promise:s}}if(this._isPortalDomain(e)){let t="";if(this._gwDomains.some(r=>(r.regex.test(e)&&(t=r.tokenServiceUrl),!!t)),t||this._portals.some(r=>(this._hasSameServerInstance(r,e)&&(t=r+this._gwTokenUrl),!!t)),t||(i=e.toLowerCase().indexOf("/sharing"),-1!==i&&(t=e.slice(0,i)+this._gwTokenUrl)),t||(t=this._getOrigin(e)+this._gwTokenUrl),t){const r=new u(e).port;/^http:\/\//i.test(e)&&"7080"===r&&(t=t.replace(/:7080/i,":7443")),t=t.replace(/http:/i,"https:")}return t}}_processOAuthResponseParams(e,t,r){const s=t._oAuthCred;if(e.code){const i=s.codeVerifier;return s.codeVerifier=null,s.stateUID=null,s.save(),this._getOAuthToken(r.server,e.code,t.appId,this._getRedirectURI(t,!0),i).then(i=>{const n=new w({userId:i.username,server:r.server??void 0,token:i.access_token,expires:Date.now()+1e3*i.expires_in,ssl:i.ssl,oAuthState:e.state,_oAuthCred:s});return t.userId=n.userId,s.storage=i.persist?R:C,s.refreshToken=i.refresh_token,s.token=null,s.expires=i.refresh_token_expires_in?Date.now()+1e3*i.refresh_token_expires_in:null,s.userId=n.userId,s.ssl=n.ssl,s.save(),n})}const i=new w({userId:e.username,server:r.server??void 0,token:e.access_token,expires:Date.now()+1e3*Number(e.expires_in),ssl:"true"===e.ssl,oAuthState:e.state,_oAuthCred:s});return t.userId=i.userId,s.storage=e.persist?R:C,s.refreshToken=null,s.token=i.token,s.expires=i.expires,s.userId=i.userId,s.ssl=i.ssl,s.save(),Promise.resolve(i)}_processOAuthPopupParams(e){const t=this._oAuthDfd;if(this._oAuthDfd=null,t)if(clearInterval(this._oAuthIntervalId),this._oAuthOnPopupHandle?.remove(),e.error){const s="access_denied"===e.error,i=new r(s?"identity-manager:user-aborted":"identity-manager:authentication-failed",s?"ABORTED":"OAuth: "+e.error+" - "+e.error_description);t.reject(i)}else this._processOAuthResponseParams(e,t.oinfo_,t.sinfo_).then(e=>{t.resolve(e)}).catch(e=>{t.reject(e)})}_setOAuthResponseQueryString(e){e&&(e.startsWith("?")&&(e=e.slice(1)),this._processOAuthPopupParams(p(e)))}async _exchangeToken(e,r,s){return(await t(`${e}/sharing/rest/oauth2/exchangeToken`,{authMode:"anonymous",method:"post",query:{f:"json",client_id:r,token:s}})).data.token}async _getPlatformSelf(e,r){if(this._getPlatformSelfError&&Date.now()-this._getPlatformSelfError[1]<1e3)throw this._getPlatformSelfError[0];e=e.replace(/^http:/i,"https:");try{const s=await t(`${e}/sharing/rest/oauth2/platformSelf`,{authMode:"anonymous",headers:{"X-Esri-Auth-Client-Id":r,"X-Esri-Auth-Redirect-Uri":window.location.href.replace(/#.*$/,"")},method:"post",query:{f:"json",expiration:30},withCredentials:!0});return this._getPlatformSelfError=null,s.data}catch(s){throw"OAUTH_0066"===s.details?.messageCode&&(this._getPlatformSelfError=[s,Date.now()]),s}}_getPortalSelf(e,r){let s;if(this._gwDomains.some(t=>(t.regex.test(e)&&(s=t.customBaseUrl),!!s)),s)return Promise.resolve({allSSL:!0,currentVersion:"8.4",customBaseUrl:s,portalMode:"multitenant",supportsOAuth:!0});this._appOrigin.startsWith("https:")?e=e.replace(/^http:/i,"https:").replace(/:7080/i,":7443"):/^http:/i.test(r)&&(e=e.replace(/^https:/i,"http:").replace(/:7443/i,":7080"));return t(e,{query:{f:"json"},authMode:"anonymous",withCredentials:!0}).then(e=>e.data)}_doPortalSignIn(e){const t=this._portalConfig,r=window.location.href,s=this.findServerInfo(e);return!(!t&&!this._isPortalDomain(r)||!(s?s.hasPortal||s.owningSystemUrl&&this._isPortalDomain(s.owningSystemUrl):this._isPortalDomain(e))||!(this._isIdProvider(r,e)||t&&(this._hasSameServerInstance(this._getServerInstanceRoot(t.restBaseUrl),e)||this._isIdProvider(t.restBaseUrl,e))||d(r,e,!0)))}_checkProtocol(e,t,s,i){let n=!0;const o=i?t.adminTokenServiceUrl:t.tokenServiceUrl;if(o.trim().toLowerCase().startsWith("https:")&&!this._appOrigin.startsWith("https:")&&m(o)&&(n=!!this._protocolFunc&&!!this._protocolFunc({resourceUrl:e,serverInfo:t}),!n)){s(new r("identity-manager:aborted","Aborted the Sign-In process to avoid sending password over insecure connection."))}return n}_enqueue(e,t,r,s,i,n){return s||(s=a()),s.resUrl_=e,s.sinfo_=t,s.options_=r,s.admin_=i,s.refresh_=n,this._busy?this._hasSameServerInstance(this._getServerInstanceRoot(e),this._busy.resUrl_)?(this._oAuthDfd&&this._oAuthDfd.oAuthWin_&&this._oAuthDfd.oAuthWin_.focus(),this._soReqs.push(s)):this._xoReqs.push(s):this._doSignIn(s),s.promise}_doSignIn(e){this._busy=e,this._rejectOnPersistedPageShow=!1;const t=t=>{const r=e.options_?.resource,s=e.resUrl_,i=e.refresh_;let n=!1;this.credentials.includes(t)||(i&&this.credentials.includes(i)?(i.userId=t.userId,i.token=t.token,i.expires=t.expires,i.validity=t.validity,i.ssl=t.ssl,i.creationTime=t.creationTime,n=!0,t=i):this.credentials.push(t)),t.resources||(t.resources=[]),t.resources.includes(r||s)||t.resources.push(r||s),t.scope=this._isServerRsrc(s)?"server":"portal",t.emitTokenChange();const o=this._soReqs,a={};this._soReqs=[],o.forEach(e=>{if(!this._isIdenticalService(s,e.resUrl_)){const r=this._getSuffix(e.resUrl_);a[r]||(a[r]=!0,t.resources.push(e.resUrl_))}}),e.resolve(t),o.forEach(e=>{this._hasSameServerInstance(this._getServerInstanceRoot(s),e.resUrl_)?e.resolve(t):this._soReqs.push(e)}),this._busy=e.resUrl_=e.sinfo_=e.refresh_=null,n||this.emit("credential-create",{credential:t}),this._soReqs.length?this._doSignIn(this._soReqs.shift()):this._xoReqs.length&&this._doSignIn(this._xoReqs.shift())},s=t=>{e.reject(t),this._busy=e.resUrl_=e.sinfo_=e.refresh_=null,this._soReqs.length?this._doSignIn(this._soReqs.shift()):this._xoReqs.length&&this._doSignIn(this._xoReqs.shift())},n=(o,a,l,c)=>{const u=e.sinfo_,p=!e.options_||!1!==e.options_.prompt,_=u.hasPortal&&this._findOAuthInfo(e.resUrl_);let f,g;if(o)t(new w({userId:o,server:u.server??void 0,token:l??void 0,expires:null!=c?Number(c):null,ssl:!!a}));else if(window!==window.parent&&this._appUrlObj.query?.["arcgis-auth-origin"]&&this._appUrlObj.query?.["arcgis-auth-portal"]&&this._hasSameServerInstance(this._getServerInstanceRoot(this._appUrlObj.query["arcgis-auth-portal"]),e.resUrl_)){window.parent.postMessage({type:"arcgis:auth:requestCredential"},this._appUrlObj.query["arcgis-auth-origin"]);const n=i(window,"message",e=>{e.source===window.parent&&e.data&&("arcgis:auth:credential"===e.data.type?(n.remove(),e.data.credential.expires<Date.now()?s(new r("identity-manager:credential-request-failed","Parent application's token has expired.")):t(new w(e.data.credential))):"arcgis:auth:error"===e.data.type&&(n.remove(),"tokenExpiredError"===e.data.error.name?s(new r("identity-manager:credential-request-failed","Parent application's token has expired.")):s(r.fromJSON(e.data.error))))});h(e.options_?.signal,()=>{n.remove()})}else if(_){let i=_._oAuthCred;if(!i){const e=new k(_,R),t=new k(_,C);e.isValid()&&t.isValid()?e.expires>t.expires?(i=e,t.destroy()):(i=t,e.destroy()):i=e.isValid()?e:t,_._oAuthCred=i}if(i.isValid()){f=new w({userId:i.userId??void 0,server:u.server??void 0,token:i.token??void 0,expires:i.expires,ssl:i.ssl??void 0,_oAuthCred:i});const r=_.appId!==i.appId&&this._doPortalSignIn(e.resUrl_);r||i.refreshToken?(e._pendingDfd=i.refreshToken?this._getOAuthToken(u.server,i.refreshToken,i.appId).then(e=>(f.expires=Date.now()+1e3*e.expires_in,f.token=e.access_token,f)):Promise.resolve(f),e._pendingDfd.then(e=>r?this._exchangeToken(e.server,_.appId,e.token).then(t=>(e.token=t,e)).catch(()=>e):e).then(e=>{t(e)}).catch(e=>{const t=e.details?.httpStatus;t>0&&404!==t?(i.destroy(),n()):s(e)})):t(f)}else if(this._oAuthLocationParams&&this._hasSameServerInstance(_.portalUrl,this._oAuthLocationParams.state.portalUrl)&&(this._oAuthLocationParams.access_token||this._oAuthLocationParams.code&&this._oAuthLocationParams.state.uid===i.stateUID&&i.codeVerifier)){const r=this._oAuthLocationParams;this._oAuthLocationParams=null,e._pendingDfd=this._processOAuthResponseParams(r,_,u).then(e=>{t(e)}).catch(s)}else{const i=()=>{p?e._pendingDfd=this.oAuthSignIn(e.resUrl_,u,_,e.options_).then(t,s):(g=new r("identity-manager:not-authenticated","User is not signed in."),s(g))};this._doPortalSignIn(e.resUrl_)?e._pendingDfd=this._getPlatformSelf(u.server,_.appId).then(e=>{d(e.portalUrl,this._appOrigin,!0)?(f=new w({userId:e.username,server:u.server??void 0,expires:Date.now()+1e3*e.expires_in,token:e.token}),t(f)):i()}).catch(i):i()}}else if(p){if(this._checkProtocol(e.resUrl_,u,s,e.admin_)){let r=e.options_;e.admin_&&(r=r||{},r.isAdmin=!0),e._pendingDfd=this.signIn(e.resUrl_,u,r).then(t,s)}}else g=new r("identity-manager:not-authenticated","User is not signed in."),s(g)},a=()=>{const r=e.sinfo_,i=r.owningSystemUrl,n=e.options_;let o,a,h,l;if(n&&(o=n.token,a=n.error,h=n.prompt),l=this._findCredential(i,{token:o,resource:e.resUrl_}),!l)for(const e of this.credentials)if(this._isIdProvider(i,e.server)){l=e;break}if(l){const i=this.findCredential(e.resUrl_,l.userId);if(i)t(i);else if(T(r,this._legacyFed)){const e=l.toJSON();e.server=r.server,e.resources=null,t(new w(e))}else{(e._pendingDfd=this.generateToken(this.findServerInfo(l.server),null,{serverUrl:e.resUrl_,token:l.token,signal:e.options_.signal,ssl:l.ssl})).then(s=>{t(new w({userId:l?.userId,server:r.server??void 0,token:s.token,expires:null!=s.expires?Number(s.expires):null,ssl:!!s.ssl,isAdmin:e.admin_,validity:s.validity}))},s)}}else{this._busy=null,o&&(e.options_.token=null);(e._pendingDfd=this.getCredential(i.replace(/\/?$/,"/sharing"),{resource:e.resUrl_,owningTenant:r.owningTenant,signal:e.options_.signal,token:o,error:a,prompt:h})).then(()=>{this._enqueue(e.resUrl_,e.sinfo_,e.options_,e,e.admin_)},t=>{e.resUrl_=e.sinfo_=e.refresh_=null,e.reject(t)})}};this._errbackFunc=s;const l=e.sinfo_.owningSystemUrl,c=this._isServerRsrc(e.resUrl_),u=e.sinfo_._restInfoPms;u?u.promise.then(t=>{const r=e.sinfo_;if(r._restInfoPms){r.adminTokenServiceUrl=r._restInfoPms.adminUrl,r._restInfoPms=null,r.tokenServiceUrl=(o("authInfo.tokenServicesUrl",t)||o("authInfo.tokenServiceUrl",t)||o("tokenServiceUrl",t))??null,r.shortLivedTokenValidity=o("authInfo.shortLivedTokenValidity",t)??null,r.currentVersion=t.currentVersion,r.owningTenant=t.owningTenant;const e=r.owningSystemUrl=t.owningSystemUrl;e&&this._portals.push(e)}c&&r.owningSystemUrl?a():n()},()=>{e.sinfo_._restInfoPms=null;const t=new r("identity-manager:server-identification-failed","Unknown resource - could not find token service endpoint.");s(t)}):c&&l?a():e.sinfo_._selfReq?e.sinfo_._selfReq.selfDfd.then(t=>{const r={};let s,i,n,o;return t&&(s=t.user?.username,r.username=s,r.allSSL=t.allSSL,i=t.supportsOAuth,o=parseFloat(t.currentVersion),"multitenant"===t.portalMode&&(n=t.customBaseUrl),e.sinfo_.currentVersion=o),e.sinfo_.webTierAuth=!!s,s&&this.normalizeWebTierAuth?this.generateToken(e.sinfo_,null,{ssl:r.allSSL}).catch(()=>null).then(e=>(r.portalToken=e?.token,r.tokenExpiration=e?.expires,r)):!s&&i&&o>=4.4&&!this._findOAuthInfo(e.resUrl_)?this._generateOAuthInfo({portalUrl:e.sinfo_.server,customBaseUrl:n,owningTenant:e.sinfo_._selfReq.owningTenant}).catch(()=>null).then(()=>r):r}).catch(()=>null).then(t=>{e.sinfo_._selfReq=null,t?n(t.username,t.allSSL,t.portalToken,t.tokenExpiration):n()}):n()}_generateOAuthInfo(e){let r,s=null,i=e.portalUrl;const n=e.customBaseUrl,o=e.owningTenant,a=!this._defaultOAuthInfo&&this._createDefaultOAuthInfo&&!this._hasTestedIfAppIsOnPortal;if(a){s=this._appUrlObj.path;const e=s.search(/\/(apps|home)\//);s=e>-1?s.slice(0,e):null}return a&&s?(this._hasTestedIfAppIsOnPortal=!0,r=t(s+"/sharing/rest",{query:{f:"json"}}).then(()=>{this._defaultOAuthInfo=new A({appId:"arcgisonline",popupCallbackUrl:s+"/home/oauth-callback.html"})})):r=Promise.resolve(),r.then(()=>{if(this._defaultOAuthInfo)return i=i.replace(/^http:/i,"https:"),t(i+"/sharing/rest/oauth2/validateRedirectUri",{query:{accountId:o,client_id:this._defaultOAuthInfo.appId,redirect_uri:v(this._defaultOAuthInfo.popupCallbackUrl),f:"json"}}).then(e=>{if(e.data.valid){const t=this._defaultOAuthInfo.clone();e.data.urlKey&&n?t.portalUrl="https://"+e.data.urlKey.toLowerCase()+"."+n:t.portalUrl=i,t.popup=window!==window.top||!(d(i,this._appOrigin)||this._gwDomains.some(e=>e.regex.test(i)&&e.regex.test(this._appOrigin))),this.oAuthInfos.push(t)}})})}_doOAuthSignIn(e,t,s,n){const o=s._oAuthCred,a={portalUrl:s.portalUrl};!s.popup&&s.preserveUrlHash&&window.location.hash&&(a.hash=window.location.hash),o.stateUID&&(a.uid=o.stateUID);const h={client_id:s.appId,response_type:o.codeVerifier?"code":"token",state:JSON.stringify(a),expiration:s.expiration,locale:s.locale,redirect_uri:this._getRedirectURI(s,!!o.codeVerifier)};s.forceLogin&&(h.force_login=!0),s.forceUserId&&s.userId&&(h.prepopulatedusername=s.userId),!s.popup&&this._doPortalSignIn(e)&&(h.redirectToUserOrgUrl=!0),o.codeVerifier&&(h.code_challenge=n||o.codeVerifier,h.code_challenge_method=n?"S256":"plain");const l=s.portalUrl.replace(/^http:/i,"https:")+"/sharing/oauth2/authorize",c=l+"?"+f(h);if(s.popup){const e=window.open(c,"esriJSAPIOAuth",s.popupWindowFeatures);if(e)e.focus(),this._oAuthDfd.oAuthWin_=e,this._oAuthIntervalId=setInterval(()=>{if(e.closed){clearInterval(this._oAuthIntervalId),this._oAuthOnPopupHandle.remove();const e=this._oAuthDfd;if(e){const t=new r("identity-manager:user-aborted","ABORTED");e.reject(t)}}},500),this._oAuthOnPopupHandle=i(window,["arcgis:auth:hash","arcgis:auth:location:search"],e=>{"arcgis:auth:hash"===e.type?this.setOAuthResponseHash(e.detail):this._setOAuthResponseQueryString(e.detail)});else{const e=new r("identity-manager:popup-blocked","ABORTED");this._oAuthDfd.reject(e)}}else this._rejectOnPersistedPageShow=!0,this._oAuthRedirectFunc?this._oAuthRedirectFunc({authorizeParams:h,authorizeUrl:l,resourceUrl:e,serverInfo:t,oAuthInfo:s}):window.location.href=c}_getRedirectURI(e,t){const r=window.location.href.replace(/#.*$/,"");if(e.popup)return v(e.popupCallbackUrl);if(t){const e=c(r);return e.query&&["code","error","error_description","message_code","persist","state"].forEach(t=>{delete e.query[t]}),S(e.path,e.query)}return r}}D.prototype.declaredClass="esri.identity.IdentityManagerBase";export{D as IdentityManagerBase};