- Intro
- Class Api
- Functional Api
- Advanced
- Access Control
- Permissions
- OperationStack
- Metrics
- Queries & Filters
- Catalogs & Collections
- Composing Workflows
- Developers
- Legacy
Authentication and Hub Classes
The Hub Classes are all instantiated via a set of common factory functions:
Factory Function | Description/Use-Case |
---|---|
.load(Partial<entity>, context) |
Use when application already has an object literal |
.fetch(identifier, context) |
Fetch the backing entity by id, slug or domain (Site only) |
.create(Partial<entity>, context) |
Create an instance for a new entity |
In all these functions, context
refers to an IArcGISContext
object literal, which is a collection of platform and user information an application needs in order to make requests to the right services, pass the correct authentication and easily determine other user/org specific properties.
The ArcGISContext
class provides a simple container for "context", thereby making it easier for applications and components to write simpler, more consistent code, and to easily leverage shared libraries like ArcGIS Rest JS, Hub.js, Solutions.js etc.
In addition to the portal and sharing api urls, ArcGISContext
also provides easy access to authentication status, the active UserSession
, IPortal
and IUser
objects, as well as a number of computed properties driven by those objects.
See IArcGISContext
for the list of properties and their descriptions.
Application State
In the past, this sort of "state" information has typically been managed using one-off patterns, specific to the application itself. With Esri's move towards building web components that are reusable across applications, we saw a need for a consistent means to pass this information into components. What's more, this solution needed to work well with modern, "reactive-style" web frameworks - i.e. React/Vue/Ember/Angular.
These frameworks are designed to operate effectively and efficiently with immutable data, and the ArcGISContext
class was designed to be used in this manner.
References and Immutable Objects
The question then becomes, how can we pass a reference to a long-lived object, which can react to a user signing in/out of an application, and still have immutablilty?
The solution to this was split those two things apart. The ArcGISContextManager
is the long-lived object, which exposes the immutable ArcGISContext
instance via the .context
property.
As users sign in/out of the application, the app calls ArcGISContextManager.setAuthentication(...)
or ArcGISContextManager.clearAuthentication()
as needed. When those methods are called the .context
instance is replaced with a new, immutable, object.
The application can then pass that updated .context
into it's normal state/change tracking system, and the application will re-render as needed.
ArcGISContextManager Class
This class should be created by your application - i.e. the React/Ember/Vue etc and maintained for the lifetime of the application. As your application allows the user to sign in/out, your app should call the .setAuthentication(...)
or .clearAuthentication()
methods as needed. If your application needs to store the session into localStorage or other type of store, ArcGISContextManager.serialize()
will return the current context as an encoded string. When the app boots, and loads this string from whatever store it chose to use, it can then use ArcGISContextManager.deserialize(encodedContextString)
to get a fully re-hydrated ArcGISContextManager
instance.
Example
// Create a context manager, passing in no additional information
// This will default to using https://www.arcgis.com as the portal url
const ctxMgr = await ArcGISContextManager.create();
ctxMgr.context.isAuthenticated; // false
// the context then has a number of properties accessible
ctxMgr.context.sharingApiUrl; //=> https://www.arcgis.com/sharing/rest
ctxMgr.context.hubUrl; //=> https://hub.arcgis.com
// all properties are getters so
// attempting to change values will throw
ctxMgr.context.portal = "https://dcdev.maps.arcgis.com"; //=> throws
// now let's load a session from localStorage (for example)
const session = UserSession.deserialize(localStorage.getItem("_context"));
// we can set this on the context manager, and it will fetch the
// IPortal from portal/self and the IUser from users/self
await ctxMgr.setAuthentication(session);
// at this point ctxMgr.context is now a *new* object
ctxMgr.context.isAuthenticated; // true
ctxMgr.context.portalUrl; //=> https://dcdev.maps.arcgis.com
ctxMgr.context.sharingApiUrl; //=> https://dcdev.maps.arcgis.com/sharing/rest
ctxMgr.context.currentUser; //=> {username: "dave", ...} IUser
ctxMgr.context.portal; //=> {id: "BcRx2", ...} IPortal
JSAPI Example
// load a session from localStorage
const session = UserSession.deserialize(localStorage.getItem("_context"));
// create a context manager
const ctxMgr = await ArcGISContextManager.create({ authentication: session });
// else where in the code, register the session with the identity manager
esriId.registerToken(ctxMgr.context.session.toCredential());
// do things w/ JSAPI
Framework Integration
Integration of ArcGISContext
within an application will vary depending on the framework in use. The next section provides general guidance, followed by details of how the ArcGIS Hub Team uses ArcGISContext
in Ember.
General Guidance
The ArcGISContextManager
should be created as early in the application lifecycle as possible, and should exist for the lifetime of the application.
When adding web components in a template, the context
property on the element should be set to the .context
property of the ArcGISContextManager
When the authentication status changes, the application should call the .setAuthentication(session: UserSession)
or .clearAuthentication()
methods on the context manager instance. This will replace the object that backs the .context
property. Depending on how the framework handles change tracking, the application may also need to set that context onto some state management system so that the application knows that the context has changed and it can re-render as needed.
Ember.js
In Ember we create the ArcGISContextManager
in the application route's beforeModel
hook, as that's the very first thing to run as the app boots up. We store the context manager on an Ember Service. In Ember, services are singletons that exist for the lifetime of the application, and can easily be accessed from routes, controllers, components or even other services.
When users sign in/out, the application gets a reference to the context manager from the service, and calls the necessary methods.
In order to work with Ember's change tracking system, we also set a reference to the .context
on the service itself. This allows the rest of the application to bind to the service.context
property without any additional complexity.
ArcGISContext
This class is simply holds some properties and then exposes a large set of read only properties to streamline access to commonly accessed information or structures.
In the case that an application opts not to use ArcGISContextManager
, the ArcGISContext
class could be manually created, and takes an IArcGISContextOptions
in the constructor.
Questions and Answers
Q: Should hub.js functions take an IArcGISContext
?
A: No. Hub.js function parameters should expect one of the lower level interfaces - IHubRequestOptions
, IUserRequestOptions
or IRequestOptions
. The ArcGISContext
should be used in components which need to easily access any of those interfaces, or other platform configuration properties, in order to make calls to modules from hub.js, or arcgis-rest-js.
Q: Should my application bind to ArcGISContextManager.context
directly?
A: This depends on your application framework. For Ember's tracking system, when the authentication changes, we call the cooresponding methods on the ArcGISContextManager
, and then set the context
onto a property on a service. The rest of the application reads the context from the service. This enables Ember's change tracking system to be aware of the change and thus computed properties re-fire and templates know to re-render.