UNPKG

@esri/arcgis-rest-request

Version:

Common methods and utilities for @esri/arcgis-rest-js packages.

615 lines (613 loc) 28.8 kB
import type { ServerResponse } from "http"; import { IRequestOptions } from "./utils/IRequestOptions.js"; import { IAuthenticationManager } from "./utils/IAuthenticationManager.js"; import { ITokenRequestOptions } from "./utils/ITokenRequestOptions.js"; import { IAppAccess } from "./validate-app-access.js"; import { AuthenticationManagerBase } from "./AuthenticationManagerBase.js"; import { IOAuthState } from "./types/oauthState.js"; /** * Options for {@linkcode ArcGISIdentityManager.fromToken}. */ export interface IFromTokenOptions { /** * The token you want to create the {@linkcode ArcGISIdentityManager} instance with. */ token: string; /** * Date when this token will expire. */ tokenExpires?: Date; /** * The portal that the token was generated from. Defaults to `https://www.arcgis.com/sharing/rest`. Required if you are not using the default portal. */ portal?: string; /** * If the token is for a specific instance of ArcGIS Server, set `portal` to `null` or `undefined` and set `server` the URL of the ArcGIS Server. */ server?: string; /** * Optionally set the username. Recommended if available. */ username?: string; /** * Optional client ID. Used for refreshing expired tokens. */ clientId?: string; /** * Optional set a valid redirect URL for the registered client ID. Used internally to refresh expired tokens. */ redirectUri?: string; } /** * Options for {@linkcode ArcGISIdentityManager.signIn}. */ export interface ISignInOptions { username: string; password: string; portal?: string; referer?: string; } export type AuthenticationProvider = "arcgis" | "facebook" | "google" | "github" | "apple"; /** * Represents a [credential](https://developers.arcgis.com/javascript/latest/api-reference/esri-identity-Credential.html) * object used to access a secure ArcGIS resource. */ export interface ICredential { expires: number; server: string; ssl: boolean; token: string; userId: string; } /** * Represents the [`ServerInfo`](https://developers.arcgis.com/javascript/latest/api-reference/esri-identity-ServerInfo.html) class * in the ArcGIS API for JavaScript. */ export interface IServerInfo { server: string; hasPortal: boolean; hasServer: boolean; } /** * Options for static OAuth 2.0 helper methods on `ArcGISIdentityManager`. */ export interface IOAuth2Options { /** * Client ID of your application. Can be obtained by registering an application * on [ArcGIS for Developers](https://developers.arcgis.com/documentation/core-concepts/security-and-authentication/signing-in-arcgis-online-users/#registering-your-application), * [ArcGIS Online](http://doc.arcgis.com/en/arcgis-online/share-maps/add-items.htm#ESRI_SECTION1_0D1B620254F745AE84F394289F8AF44B) or on your instance of ArcGIS Enterprise. */ clientId: string; /** * A valid URL to redirect to after a user authorizes your application. Can be set on [ArcGIS for Developers](https://developers.arcgis.com/documentation/core-concepts/security-and-authentication/signing-in-arcgis-online-users/#registering-your-application), * [ArcGIS Online](http://doc.arcgis.com/en/arcgis-online/share-maps/add-items.htm#ESRI_SECTION1_0D1B620254F745AE84F394289F8AF44B) or on your instance of ArcGIS Enterprise. */ redirectUri: string; /** * The ArcGIS Online or ArcGIS Enterprise portal you want to use for authentication. Defaults to `https://www.arcgis.com/sharing/rest` for the ArcGIS Online portal. */ portal?: string; /** * ArcGIS Authentication is used by default. Specifying an alternative will take users directly to the corresponding provider's OAuth page. */ provider?: AuthenticationProvider; /** * The requested validity in minutes for a refresh token/access token. Defaults to 20160 (2 weeks). * * When using PKCE or server-based OAuth this will control the duration of the refresh token. In this scenario, access tokens will always have a 30 minute validity. * * When using implicit auth (`pkce: false`) in {@linkcode ArcGISIdentityManager.beginOAuth2}, this controls the duration of the access token and no refresh token will be granted. */ expiration?: number; /** * If `true` will use the PKCE oAuth 2.0 extension spec in to authorize the user and obtain a token. A value of `false` will use the deprecated oAuth 2.0 implicit grant type. * * This option is only for when building browser-based applications. */ pkce?: boolean; /** * Determines whether to open the authorization window in a new tab/window or in the current window. * * This option is only for when building browser-based applications. */ popup?: boolean; /** * The window features passed to [window.open()](https://developer.mozilla.org/en-US/docs/Web/API/Window/open) when `popup` is true. Defaults to `height=400,width=600,menubar=no,location=yes,resizable=yes,scrollbars=yes,status=yes` * * This option is only for when building browser-based applications. */ popupWindowFeatures?: string; /** * The locale assumed to render the login page. * * This option is only for when building browser-based applications. */ locale?: string; /** * Sets the color theme of the oAuth 2.0 authorization screen. Will use the system preference or a light theme by default. */ style?: "" | "light" | "dark"; /** * Custom value for oAuth 2.0 state. A random identifier will be generated if this is not passed. You may also pass a plain object and the `id` property will be used as the state value. If an object is passed, all properties will be serialized and made available when the {@linkcode ArcGISIdentityManager.completeOAuth2} method is called. If a string is passed, it will be available as the `id` property and an additional `originalUrl` property will be added containing the URL of the page that initiated the oAuth 2.0 process. */ state?: string | IOAuthState; [key: string]: any; } /** * Options for the {@linkcode ArcGISIdentityManager} constructor. */ export interface IArcGISIdentityManagerOptions { /** * Client ID of your application. Can be obtained by registering an application * on [ArcGIS for Developers](https://developers.arcgis.com/documentation/core-concepts/security-and-authentication/signing-in-arcgis-online-users/#registering-your-application), * [ArcGIS Online](http://doc.arcgis.com/en/arcgis-online/share-maps/add-items.htm#ESRI_SECTION1_0D1B620254F745AE84F394289F8AF44B) or on your instance of ArcGIS Enterprise. */ clientId?: string; /** * A valid URL to redirect to after a user authorizes your application. Can be set on [ArcGIS for Developers](https://developers.arcgis.com/documentation/core-concepts/security-and-authentication/signing-in-arcgis-online-users/#registering-your-application), * [ArcGIS Online](http://doc.arcgis.com/en/arcgis-online/share-maps/add-items.htm#ESRI_SECTION1_0D1B620254F745AE84F394289F8AF44B) or on your instance of ArcGIS Enterprise. */ redirectUri?: string; /** * OAuth 2.0 refresh token. */ refreshToken?: string; /** * Expiration date of the `refreshToken` */ refreshTokenExpires?: Date; /** * The authenticated user's username. Guaranteed to be unique across ArcGIS Online or your instance of ArcGIS Enterprise. */ username?: string; /** * Password for this user. Used in CLI apps where users cannot do OAuth 2.0. */ password?: string; /** * OAuth 2.0 access token. */ token?: string; /** * Expiration date for the `token` */ tokenExpires?: Date; /** * The ArcGIS Online or ArcGIS Enterprise portal you want to use for authentication. Defaults to `https://www.arcgis.com/sharing/rest` for the ArcGIS Online portal. */ portal?: string; /** * This value is set to true automatically if the ArcGIS Organization requires that requests be made over https. */ ssl?: boolean; /** * ArcGIS Authentication is used by default. Specifying an alternative will take users directly to the corresponding provider's OAuth page. */ provider?: AuthenticationProvider; /** * Duration of requested token validity in minutes. Used when requesting tokens with `username` and `password` or when validating the identity of unknown servers. Defaults to two weeks. */ tokenDuration?: number; /** * An unfederated ArcGIS Server instance known to recognize credentials supplied manually. * * ```js * { * server: "https://sampleserver6.arcgisonline.com/arcgis", * token: "SOSlV3v..", * tokenExpires: new Date(1545415669763) * } * ``` */ server?: string; /** * The referer to use when getting the token with `.signIn()` */ referer?: string; /** * The OAuth 2.0 state object that was provided when the oAuth 2.0 process was initiated. */ state?: IOAuthState; } /** * Used to authenticate both ArcGIS Online and ArcGIS Enterprise users. `ArcGISIdentityManager` includes helper methods for [OAuth 2.0](https://developers.arcgis.com/documentation/mapping-apis-and-services/security/oauth-2.0/) in both browser and server applications. * * **It is not recommended to construct `ArcGISIdentityManager` directly**. Instead there are several static methods used for specific workflows. The 2 primary workflows relate to oAuth 2.0: * * * {@linkcode ArcGISIdentityManager.beginOAuth2} and {@linkcode ArcGISIdentityManager.completeOAuth2} for oAuth 2.0 in browser-only environment. * * {@linkcode ArcGISIdentityManager.authorize} and {@linkcode ArcGISIdentityManager.exchangeAuthorizationCode} for oAuth 2.0 for server-enabled application. * * Other more specialized helpers for less common workflows also exist: * * * {@linkcode ArcGISIdentityManager.fromToken} for when you have an existing token from another source and would like create an `ArcGISIdentityManager` instance. * * {@linkcode ArcGISIdentityManager.fromCredential} for creating an `ArcGISIdentityManager` instance from a `Credentials` object in the ArcGIS JS API `IdentityManager` * * {@linkcode ArcGISIdentityManager.signIn} for authenticating directly with a user's username and password for environments with a user interface for oAuth 2.0. * * Once a manager is created there are additional utilities: * * * {@linkcode ArcGISIdentityManager.serialize} can be used to create a JSON object representing an instance of `ArcGISIdentityManager` * * {@linkcode ArcGISIdentityManager.deserialize} will create a new `ArcGISIdentityManager` from a JSON object created with {@linkcode ArcGISIdentityManager.serialize} * * {@linkcode ArcGISIdentityManager.destroy} or {@linkcode ArcGISIdentityManager.signOut} will invalidate any tokens in use by the `ArcGISIdentityManager`. */ export declare class ArcGISIdentityManager extends AuthenticationManagerBase implements IAuthenticationManager { /** * The current ArcGIS Online or ArcGIS Enterprise `token`. */ get token(): string; /** * The expiration time of the current `token`. */ get tokenExpires(): Date; /** * The current token to ArcGIS Online or ArcGIS Enterprise. */ get refreshToken(): string; /** * The expiration time of the current `refreshToken`. */ get refreshTokenExpires(): Date; /** * Returns `true` if these credentials can be refreshed and `false` if it cannot. */ get canRefresh(): boolean; /** * Begins a new browser-based OAuth 2.0 sign in. If `options.popup` is `true` the authentication window will open in a new tab/window. Otherwise, the user will be redirected to the authorization page in their current tab/window and the function will return `undefined`. * * If `popup` is `true` (the default) this method will return a `Promise` that resolves to an `ArcGISIdentityManager` instance and you must call {@linkcode ArcGISIdentityManager.completeOAuth2()} on the page defined in the `redirectUri`. Otherwise it will return undefined and the {@linkcode ArcGISIdentityManager.completeOAuth2()} method will return a `Promise` that resolves to an `ArcGISIdentityManager` instance. * * A {@linkcode ArcGISAccessDeniedError} error will be thrown if the user denies the request on the authorization screen. * * This option is only for when building browser-based applications. */ static beginOAuth2(options: IOAuth2Options, win?: any): Promise<ArcGISIdentityManager> | undefined; /** * Completes a browser-based OAuth 2.0 sign in. If `options.popup` is `true` the user * will be returned to the previous window and the popup will close. Otherwise a new `ArcGISIdentityManager` will be returned. You must pass the same values for `clientId`, `popup`, `portal`, and `pkce` as you used in `beginOAuth2()`. * * A {@linkcode ArcGISAccessDeniedError} error will be thrown if the user denies the request on the authorization screen. * This option is only for when building browser-based applications. */ static completeOAuth2(options: IOAuth2Options, win?: any): Promise<ArcGISIdentityManager>; /** * Request credentials information from the parent application * * When an application is embedded into another application via an IFrame, the embedded app can * use `window.postMessage` to request credentials from the host application. This function wraps * that behavior. * * The ArcGIS API for Javascript has this built into the Identity Manager as of the 4.19 release. * * Note: The parent application will not respond if the embedded app's origin is not: * - the same origin as the parent or *.arcgis.com (JSAPI) * - in the list of valid child origins (REST-JS) * * * @param parentOrigin origin of the parent frame. Passed into the embedded application as `parentOrigin` query param * This option is only for when building browser-based applications. */ static fromParent(parentOrigin: string, win?: any): Promise<any>; /** * Begins a new server-based OAuth 2.0 sign in. This will redirect the user to * the ArcGIS Online or ArcGIS Enterprise authorization page. * * This method is only for when using Node.js and is not available in browser-based applications. */ static authorize(options: IOAuth2Options, response: ServerResponse): void; /** * Completes the server-based OAuth 2.0 sign in process by exchanging the `authorizationCode` * for a `access_token`. * * This method is only for when using Node.js and is not available in browser-based applications. */ static exchangeAuthorizationCode(options: IOAuth2Options, authorizationCode: string): Promise<ArcGISIdentityManager>; /** * Deserializes a JSON string previously created with {@linkcode ArcGISIdentityManager.serialize} to an {@linkcode ArcGISIdentityManager} instance. * * ```js * // create an ArcGISIdentityManager instance * const serializedString = manager.serialize(); * localStorage.setItem("arcgis-identity-manager", serializedString); * * // later, you can retrieve the manager from localStorage * const serializedString = localStorage.getItem("arcgis-identity-manager"); * const manager = ArcGISIdentityManager.deserialize(serializedString); * ``` * * @param str A JSON string representing an instance of `ArcGISIdentityManager`. This can be created with {@linkcode ArcGISIdentityManager.serialize}. */ static deserialize(str: string): ArcGISIdentityManager; /** * Translates authentication from the format used in the [`IdentityManager` class in the ArcGIS API for JavaScript](https://developers.arcgis.com/javascript/latest/api-reference/esri-identity-Credential.html). * * You will need to call both [`IdentityManger.findCredential`](https://developers.arcgis.com/javascript/latest/api-reference/esri-identity-IdentityManager.html#findCredential) and [`IdentityManger.findServerInfo`](https://developers.arcgis.com/javascript/latest/api-reference/esri-identity-IdentityManager.html#findServerInfo) to obtain both parameters for this method. * * This method can be used with {@linkcode ArcGISIdentityManager.toCredential} to interop with the ArcGIS API for JavaScript. * * ```js * require(["esri/id"], (esriId) => { * const credential = esriId.findCredential("https://www.arcgis.com/sharing/rest"); * const serverInfo = esriId.findServerInfo("https://www.arcgis.com/sharing/rest"); * * const manager = ArcGISIdentityManager.fromCredential(credential, serverInfo); * }); * ``` * * @returns ArcGISIdentityManager */ static fromCredential(credential: ICredential, serverInfo: IServerInfo): ArcGISIdentityManager; /** * Handle the response from the parent * @param event DOM Event */ private static parentMessageHandler; /** * Revokes all active tokens for a provided {@linkcode ArcGISIdentityManager}. The can be considered the equivalent to signing the user out of your application. */ static destroy(manager: ArcGISIdentityManager): Promise<import("./revoke-token.js").IRevokeTokenResponse>; /** * Create a {@linkcode ArcGISIdentityManager} from an existing token. Useful for when you have a users token from a different authentication system and want to get a {@linkcode ArcGISIdentityManager}. */ static fromToken(options: IFromTokenOptions): Promise<ArcGISIdentityManager>; /** * Initialize a {@linkcode ArcGISIdentityManager} with a user's `username` and `password`. **This method is intended ONLY for applications without a user interface such as CLI tools.**. * * If possible you should use {@linkcode ArcGISIdentityManager.beginOAuth2} to authenticate users in a browser or {@linkcode ArcGISIdentityManager.authorize} for authenticating users with a web server. */ static signIn(options: ISignInOptions): Promise<ArcGISIdentityManager>; /** * Client ID being used for authentication if provided in the `constructor`. */ readonly clientId: string; /** * The currently authenticated user's password if provided in the `constructor`. */ readonly password: string; /** * The current portal the user is authenticated with. */ readonly portal: string; /** * This value is set to true automatically if the ArcGIS Organization requires that requests be made over https. */ readonly ssl: boolean; /** * The authentication provider to use. */ readonly provider: AuthenticationProvider; /** * Determines how long new tokens requested are valid. */ readonly tokenDuration: number; /** * A valid redirect URI for this application if provided in the `constructor`. */ readonly redirectUri: string; /** * An unfederated ArcGIS Server instance known to recognize credentials supplied manually. * * ```js * { * server: "https://sampleserver6.arcgisonline.com/arcgis", * token: "SOSlV3v..", * tokenExpires: new Date(1545415669763) * } * ``` */ readonly server: string; /** * The referer to use when getting the token with `.signIn()` */ readonly referer: string; /** * The state object that was provided to the OAuth 2.0 process. */ readonly state: IOAuthState; /** * Hydrated by a call to [getPortal()](#getPortal-summary). */ private _portalInfo; private _token; private _tokenExpires; private _refreshToken; private _refreshTokenExpires; private _pendingPortalRequest; /** * Internal object to keep track of pending token requests. Used to prevent * duplicate token requests. */ private _pendingTokenRequests; /** * Internal list of tokens to 3rd party servers (federated servers) that have * been created via `generateToken`. The object key is the root URL of the server. */ private federatedServers; /** * Internal list of 3rd party domains that should receive all cookies (credentials: "include"). * Used to for PKI and IWA workflows in high security environments. */ private trustedDomains; private _hostHandler; constructor(options: IArcGISIdentityManagerOptions); /** * Returns authentication in a format useable in the [`IdentityManager.registerToken()` method in the ArcGIS API for JavaScript](https://developers.arcgis.com/javascript/latest/api-reference/esri-identity-IdentityManager.html#registerToken). * * This method can be used with {@linkcode ArcGISIdentityManager.fromCredential} to interop with the ArcGIS API for JavaScript. * * ```js * require(["esri/id"], (esriId) => { * esriId.registerToken(manager.toCredential()); * }) * ``` * * @returns ICredential */ toCredential(): ICredential; /** * Returns information about the currently logged in user's [portal](https://developers.arcgis.com/rest/users-groups-and-items/portal-self.htm). Subsequent calls will *not* result in additional web traffic. * * ```js * manager.getPortal() * .then(response => { * console.log(portal.name); // "City of ..." * }) * ``` * * @param requestOptions - Options for the request. NOTE: `rawResponse` is not supported by this operation. * @returns A Promise that will resolve with the data from the response. */ getPortal(requestOptions?: IRequestOptions): Promise<any>; /** * Gets an appropriate token for the given URL. If `portal` is ArcGIS Online and * the request is to an ArcGIS Online domain `token` will be used. If the request * is to the current `portal` the current `token` will also be used. However if * the request is to an unknown server we will validate the server with a request * to our current `portal`. */ getToken(url: string, requestOptions?: ITokenRequestOptions): Promise<string>; /** * Get application access information for the current user * see `validateAppAccess` function for details * * @param clientId application client id */ validateAppAccess(clientId: string): Promise<IAppAccess>; /** * Converts the `ArcGISIdentityManager` instance to a JSON object. This is called when the instance is serialized to JSON with [`JSON.stringify()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify). * * ```js * import { ArcGISIdentityManager } from '@esri/arcgis-rest-request'; * * const session = ArcGISIdentityManager.fromCredentials({ * clientId: "abc123", * clientSecret: "••••••" * }) * * const json = JSON.stringify(session); * ``` * * @returns A plain object representation of the instance. */ toJSON(): IArcGISIdentityManagerOptions & { type: string; }; /** * Serializes the `ArcGISIdentityManager` instance to a JSON string. * * ```js * // create an ArcGISIdentityManager instance * const serializedString = manager.serialize(); * localStorage.setItem("arcgis-identity-manager", serializedString); * * // later, you can retrieve the manager from localStorage * const serializedString = localStorage.getItem("arcgis-identity-manager"); * const manager = ArcGISIdentityManager.deserialize(serializedString); * ``` * * @returns The serialized JSON string. */ serialize(): string; /** * For a "Host" app that embeds other platform apps via iframes, after authenticating the user * and creating a ArcGISIdentityManager, the app can then enable "post message" style authentication by calling * this method. * * Internally this adds an event listener on window for the `message` event * * @param validChildOrigins Array of origins that are allowed to request authentication from the host app */ enablePostMessageAuth(validChildOrigins: string[], win?: any): any; /** * For a "Host" app that has embedded other platform apps via iframes, when the host needs * to transition routes, it should call `ArcGISIdentityManager.disablePostMessageAuth()` to remove * the event listener and prevent memory leaks */ disablePostMessageAuth(win?: any): void; /** * Manually refreshes the current `token` and `tokenExpires`. */ refreshCredentials(requestOptions?: ITokenRequestOptions): Promise<this>; /** * Determines the root of the ArcGIS Server or Portal for a given URL. * * @param url the URl to determine the root url for. */ getServerRootUrl(url: string): string; /** * Returns the proper [`credentials`] option for `fetch` for a given domain. * See [trusted server](https://enterprise.arcgis.com/en/portal/latest/administer/windows/configure-security.htm#ESRI_SECTION1_70CC159B3540440AB325BE5D89DBE94A). * Used internally by underlying request methods to add support for specific security considerations. * * @param url The url of the request * @returns "include" or "same-origin" */ getDomainCredentials(url: string): RequestCredentials; /** * Convenience method for {@linkcode ArcGISIdentityManager.destroy} for this instance of `ArcGISIdentityManager` */ signOut(): Promise<import("./revoke-token.js").IRevokeTokenResponse>; /** * Return a function that closes over the validOrigins array and * can be used as an event handler for the `message` event * * @param validOrigins Array of valid origins */ private createPostMessageHandler; /** * Validates that a given URL is properly federated with our current `portal`. * Attempts to use the internal `federatedServers` cache first. */ private getTokenForServer; /** * Generates a token for a given `serverUrl` using a given `tokenServicesUrl`. */ private generateTokenForServer; /** * Returns an unexpired token for the current `portal`. */ private getFreshToken; /** * Refreshes the current `token` and `tokenExpires` with `username` and * `password`. */ private refreshWithUsernameAndPassword; /** * Refreshes the current `token` and `tokenExpires` with `refreshToken`. */ private refreshWithRefreshToken; /** * Update the stored {@linkcode ArcGISIdentityManager.token} and {@linkcode ArcGISIdentityManager.tokenExpires} properties. This method is used internally when refreshing tokens. * You may need to call this if you want update the token with a new token from an external source. * * @param newToken The new token to use for this instance of `ArcGISIdentityManager`. * @param newTokenExpiration The new expiration date of the token. * @returns */ updateToken(newToken: string, newTokenExpiration: Date): this; /** * Exchanges an unexpired `refreshToken` for a new one, also updates `token` and * `tokenExpires`. */ exchangeRefreshToken(requestOptions?: ITokenRequestOptions): Promise<this>; /** * ensures that the authorizedCrossOriginDomains are obtained from the portal and cached * so we can check them later. * * @returns this */ private fetchAuthorizedDomains; } /** * @deprecated - Use {@linkcode ArcGISIdentityManager}. * @internal * */ declare function UserSession(options: IArcGISIdentityManagerOptions): ArcGISIdentityManager; declare namespace UserSession { var beginOAuth2: (options: IOAuth2Options, win?: any) => Promise<ArcGISIdentityManager>; var completeOAuth2: (options: IOAuth2Options, win?: any) => Promise<ArcGISIdentityManager>; var fromParent: (parentOrigin: string, win?: any) => Promise<any>; var authorize: (options: IOAuth2Options, response: ServerResponse<import("http").IncomingMessage>) => void; var exchangeAuthorizationCode: (options: IOAuth2Options, authorizationCode: string) => Promise<ArcGISIdentityManager>; var fromCredential: (credential: ICredential, serverInfo: IServerInfo) => ArcGISIdentityManager; var deserialize: (str: string) => ArcGISIdentityManager; } export { UserSession };