This tutorial demonstrates how to implement user authentication in your client applications using the ArcGIS
class in ArcGIS REST JS. This will allow users of your application to sign in with their ArcGIS account, granting your application access to the privileges and items associated with it.
Prerequisites
You need an ArcGIS Location Platform, ArcGIS Online, or ArcGIS Enterprise account.
Steps
Create OAuth credentials
A set of OAuth credentials are required for user authentication. These credentials are created as an item in your organization's portal.
-
Sign in to your portal.
-
Click Content > My content > New item and select Developer credentials.
-
In the Credential types menu, select OAuth credentials.
-
Add a redirect URL to your OAuth credentials in the format
"https
or:// <server >[ :port]/callback.html" http
. For example, if you are running your application on://my-arcgis-app :/auth https
add://localhost :8080 https
, to the list of redirect URLs. You will create the://localhost :8080/callback.html callback.html
page later in this tutorial. -
In the Privileges and Item access menus, click Next. These properties do not apply to user authentication.
-
Review your selections and, when you are ready, click Generate credentials.
Scaffold HTML
Begin by creating a basic HTML page containing a button directing the user to the authorization page or pop-up. This will be the primary application page.
-
Create an
HTML
file to be used for your application. Add references to thearcgis-rest-request
package and Calcite components.index.htmlUse dark colors for code blocks <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no" /> <title>User authentication starter app (ArcGIS REST JS)</title> <!-- ArcGIS REST JS used for user authentication. --> <script src="https://unpkg.com/@esri/arcgis-rest-request@4.2.1/dist/bundled/request.umd.min.js"></script> <!-- Calcite components used for authentication buttons. --> <script type="module" src=https://js.arcgis.com/calcite-components/1.4.3/calcite.esm.js></script> <link rel="stylesheet" type="text/css" href=https://js.arcgis.com/calcite-components/1.4.3/calcite.css /> </head> <body> </body> </html>
-
Create "Sign in" and "Sign out" buttons with the
calcite-button
component. Add astyle
tag with CSS to position them properly on the screen.index.htmlUse dark colors for code blocks </head> <body> <calcite-panel class="auth-buttons"> <calcite-button id="sign-in">Sign in with ArcGIS</calcite-button> <calcite-button id="sign-out" class="hide" appearance="outline-fill">Sign out</calcite-button> </calcite-panel> </body>
Create an authentication script
The authentication code in this tutorial is implemented in a separate block. Create a <script
to handle user authentication, and a second <script
to handle your main app logic.
-
Create a
<script
tag to handle user authentication. Define a method called> handle
that will contain the authentication logic.Sign In index.htmlUse dark colors for code blocks <calcite-panel class="auth-buttons"> <calcite-button id="sign-in">Sign in with ArcGIS</calcite-button> <calcite-button id="sign-out" class="hide" appearance="outline-fill">Sign out</calcite-button> </calcite-panel> <script> /* User authentication script */ const handleSignIn = async (initApp, destroyApp) => { } </script>
-
Create another
<script
to handle your main app logic. Define two methods called> init
andApp destroy
that will be called when the user signs in and out, respectively.App index.htmlUse dark colors for code blocks <calcite-panel class="auth-buttons"> <calcite-button id="sign-in">Sign in with ArcGIS</calcite-button> <calcite-button id="sign-out" class="hide" appearance="outline-fill">Sign out</calcite-button> </calcite-panel> <script> /* User authentication script */ const handleSignIn = async (initApp, destroyApp) => { } </script> <script> /* Main script */ const initApp = (session) => { console.log(`Successfully authenticated as ${session.username}.\nAccess token: ${session.token}`); // This method is called after the user signs in. Write your main app logic here. } const destroyApp = () => { // This method is called after the user signs out return; } </script>
-
Call
handle
at the bottom of your main script. Pass yourSign In init
andApp destroy
methods to be called within the authentication script.App index.htmlUse dark colors for code blocks <calcite-panel class="auth-buttons"> <calcite-button id="sign-in">Sign in with ArcGIS</calcite-button> <calcite-button id="sign-out" class="hide" appearance="outline-fill">Sign out</calcite-button> </calcite-panel> <script> /* User authentication script */ const handleSignIn = async (initApp, destroyApp) => { } </script> <script> /* Main script */ const initApp = (session) => { console.log(`Successfully authenticated as ${session.username}.\nAccess token: ${session.token}`); // This method is called after the user signs in. Write your main app logic here. } const destroyApp = () => { // This method is called after the user signs out return; } // Handle user authentication handleSignIn(initApp,destroyApp); </script>
Set credential values
-
Go to the item page of the OAuth credentials you created earlier.
-
Paste the Client ID and redirect URL into your application.
index.htmlUse dark colors for code blocks <script> /* User authentication script */ const handleSignIn = async (initApp, destroyApp) => { // Your client ID from OAuth credentials const clientId = 'YOUR_CLIENT_ID'; // The redirect URL registered in your OAuth credentials const redirectUri = 'YOUR_REDIRECT_URL'; } </script>
Begin OAuth authentication
-
Add an event listener to the
sign-in
button that will trigger OAuth authentication on click.index.htmlUse dark colors for code blocks <script> /* User authentication script */ const handleSignIn = async (initApp, destroyApp) => { // Your client ID from OAuth credentials const clientId = 'YOUR_CLIENT_ID'; // The redirect URL registered in your OAuth credentials const redirectUri = 'YOUR_REDIRECT_URL'; // Sign in logic const signInButton = document.getElementById('sign-in'); signInButton.addEventListener('click',()=>{ }) } </script>
-
Call
ArcGIS
to begin OAuth authentication. Pass yourIdentity Manager.begin O Auth2 client
andId redirect
. This method will open a new window at the authorization endpoint that prompts users to sign in with an ArcGIS account.Uri index.htmlUse dark colors for code blocks // Sign in logic const signInButton = document.getElementById('sign-in'); signInButton.addEventListener('click',()=>{ // Use ArcGIS REST JS to handle OAuth2.0 authentication arcgisRest.ArcGISIdentityManager.beginOAuth2({ clientId: clientId, redirectUri: redirectUri, popup: true }) })
Upon signing in successfully, this window will redirect the browser to the provided
redirect
address.Uri
Create a callback page
Once the user has signed in, the browser will be redirected to the address of the provided redirect URI. Create a new HTML page at this address called callback.html
to complete OAuth authentication.
-
Create a new page called
callback.html
and import REST JS. Make sure the location of this page matches the redirect URL you provided to your OAuth credentials.callback.htmlUse dark colors for code blocks <!DOCTYPE html> <head> <title>User authentication OAuth2.0 callback (ArcGIS REST JS)</title> </head> <body> <script type="module"> import { ArcGISIdentityManager } from 'https://esm.run/@esri/arcgis-rest-request@4'; </script> </body> </html>
-
Paste your Client ID and redirect URL into the application. These should be identical to the values in
index.html
.callback.htmlUse dark colors for code blocks <!DOCTYPE html> <head> <title>User authentication OAuth2.0 callback (ArcGIS REST JS)</title> </head> <body> <script type="module"> import { ArcGISIdentityManager } from 'https://esm.run/@esri/arcgis-rest-request@4'; // Your client ID from OAuth credentials const clientId = 'YOUR_CLIENT_ID'; // The redirect URL registered in your OAuth credentials const redirectUri = 'YOUR_REDIRECT_URL'; </script> </body> </html>
-
Call
ArcGIS
to complete OAuth authentication. Pass yourIdentity Manager.complete O Auth2 client
andId redirect
. This method receives the authorization code generated when a user signs in and uses it to request an access token.Uri callback.htmlUse dark colors for code blocks // Your client ID from OAuth credentials const clientId = 'YOUR_CLIENT_ID'; // The redirect URL registered in your OAuth credentials const redirectUri = 'YOUR_REDIRECT_URL'; ArcGISIdentityManager.completeOAuth2({ clientId, redirectUri })
Handle app state
Once OAuth2.0 authorization is complete, the begin
call in index.html
will resolve to a valid user session. Create a signed in state for your app that triggers once a user signs in.
-
In
index.html
, add athen
method toArcGIS
that is called when the promise resolves. This allows you to access information about the signed-in user's session.Identity Manager.begin O Auth2 index.htmlUse dark colors for code blocks // Sign in logic const signInButton = document.getElementById('sign-in'); signInButton.addEventListener('click',()=>{ // Use ArcGIS REST JS to handle OAuth2.0 authentication arcgisRest.ArcGISIdentityManager.beginOAuth2({ clientId: clientId, redirectUri: redirectUri, popup: true }) .then((newSession) => { }); })
-
Create an
update
method to handle updates to the app state. Call it and pass in the session info.App State index.htmlUse dark colors for code blocks const handleSignIn = async (initApp, destroyApp) => { // Your client ID from OAuth credentials const clientId = 'YOUR_CLIENT_ID'; // The redirect URL registered in your OAuth credentials const redirectUri = 'YOUR_REDIRECT_URL'; // Handle signed in and signed out app states const updateAppState = (sessionInfo) => { } // Sign in logic const signInButton = document.getElementById('sign-in'); signInButton.addEventListener('click',()=>{ // Use ArcGIS REST JS to handle OAuth2.0 authentication arcgisRest.ArcGISIdentityManager.beginOAuth2({ clientId: clientId, redirectUri: redirectUri, popup: true }) .then((newSession) => { updateAppState(newSession); }); }) }
-
Update the calcite buttons when a user is signed in, and call the passed
init
method to trigger your main app logic.App index.htmlUse dark colors for code blocks const handleSignIn = async (initApp, destroyApp) => { // Your client ID from OAuth credentials const clientId = 'YOUR_CLIENT_ID'; // The redirect URL registered in your OAuth credentials const redirectUri = 'YOUR_REDIRECT_URL'; // Handle signed in and signed out app states const updateAppState = (sessionInfo) => { if (sessionInfo) { // Signed in button state signOutButton.innerHTML = `Sign out: ${sessionInfo.username}`; signOutButton.classList.remove('hide'); signInButton.classList.add('hide'); // Method called when user signs in initApp(sessionInfo); } }
-
Add an event listener to the
sign-out
button that updates the app state when the user clicks "Sign out".index.htmlUse dark colors for code blocks // Sign in logic const signInButton = document.getElementById('sign-in'); signInButton.addEventListener('click',()=>{ // Use ArcGIS REST JS to handle OAuth2.0 authentication arcgisRest.ArcGISIdentityManager.beginOAuth2({ clientId: clientId, redirectUri: redirectUri, popup: true }) .then((newSession) => { updateAppState(newSession); }); }) // Sign out logic const signOutButton = document.getElementById('sign-out'); signOutButton.addEventListener('click', () => updateAppState(null));
-
Update the calcite buttons when a user signs out, and call the passed
destroy
method to trigger your main app logic.App index.htmlUse dark colors for code blocks // Handle signed in and signed out app states const updateAppState = (sessionInfo) => { if (sessionInfo) { // Signed in button state signOutButton.innerHTML = `Sign out: ${sessionInfo.username}`; signOutButton.classList.remove('hide'); signInButton.classList.add('hide'); // Method called when user signs in initApp(sessionInfo); } else { // Signed out button state signOutButton.classList.add('hide'); signInButton.classList.remove('hide'); // Method called when user signs out destroyApp(); } }
Create a session from local storage
ArcGIS REST JS does not include tools for persisting a session after retrieving session information. You must decide how to implement persisting the session and specify where the user goes after they authorize your application.
-
Create a
serialized
function that checks if there is a session in local storage.Session index.htmlUse dark colors for code blocks // Sign out logic const signOutButton = document.getElementById('sign-out'); signOutButton.addEventListener('click', () => updateAppState(null)); // Check the browser's local storage for existing sessions const serializedSession = localStorage.getItem("__ARCGIS_REST_USER_SESSION__");
-
If a session is found, use the
ArcGIS
method to parse theIdentity Manager.deserialize serialized
data and update the app state.Session index.htmlUse dark colors for code blocks // Check the browser's local storage for existing sessions const serializedSession = localStorage.getItem("__ARCGIS_REST_USER_SESSION__"); if (serializedSession !== null && serializedSession !== "undefined") { const session = arcgisRest.ArcGISIdentityManager.deserialize(serializedSession); updateAppState(session); }
-
In your
update
method, set the session in local storage when a user signs in. Clear the session from local storage when a user signs out.App State index.htmlUse dark colors for code blocks // Handle signed in and signed out app states const updateAppState = (sessionInfo) => { if (sessionInfo) { // Set user session in browser storage localStorage.setItem("__ARCGIS_REST_USER_SESSION__", JSON.stringify(sessionInfo)); // Signed in button state signOutButton.innerHTML = `Sign out: ${sessionInfo.username}`; signOutButton.classList.remove('hide'); signInButton.classList.add('hide'); // Method called when user signs in initApp(sessionInfo); } else { // Clear user session localStorage.removeItem("__ARCGIS_REST_USER_SESSION__"); // Signed out button state signOutButton.classList.add('hide'); signInButton.classList.remove('hide'); // Method called when user signs out destroyApp(); } }
Run the app
Run the application and navigate to your localhost, for example: https
.
-
You should see a blank page with a blue "Sign in" button:
-
Clicking the button should open a pop-up window that prompts you to enter the credentials of an ArcGIS account.
If this step does not work, your
client
orId redirect
are not configured correctly.Uri -
Successfully signing in with an ArcGIS account will change the app state to "Signed in":
You should also see a console message that prints the access token associated with your session. You can use this access token in requests to secure resources such as basemaps, data layers, and location services.
What's next
Learn how to use additional ArcGIS location services in these tutorials: