ArcGIS Authentication
Use this skill for implementing authentication, OAuth, API keys, and identity management.
OAuth 2.0 Authentication
Basic OAuth Setup
import OAuthInfo from "@arcgis/core/identity/OAuthInfo.js"; import esriId from "@arcgis/core/identity/IdentityManager.js"; import Portal from "@arcgis/core/portal/Portal.js";
// Create OAuthInfo with your app ID const oauthInfo = new OAuthInfo({ appId: "YOUR_APP_ID", // Register at developers.arcgis.com popup: false // false = redirect, true = popup window });
// Register with IdentityManager esriId.registerOAuthInfos([oauthInfo]);
Check Sign-In Status
async function checkSignIn() { try { await esriId.checkSignInStatus(oauthInfo.portalUrl + "/sharing"); // User is signed in const portal = new Portal({ authMode: "immediate" }); await portal.load(); console.log("Signed in as:", portal.user.username); return portal; } catch { // User is not signed in console.log("Not signed in"); return null; } }
Sign In
async function signIn() { try { const credential = await esriId.getCredential( oauthInfo.portalUrl + "/sharing" ); console.log("Credential obtained:", credential); return credential; } catch (error) { console.error("Sign in failed:", error); } }
Sign Out
function signOut() { esriId.destroyCredentials(); window.location.reload(); }
Complete OAuth Flow
import OAuthInfo from "@arcgis/core/identity/OAuthInfo.js"; import esriId from "@arcgis/core/identity/IdentityManager.js"; import Portal from "@arcgis/core/portal/Portal.js";
const oauthInfo = new OAuthInfo({ appId: "YOUR_APP_ID" });
esriId.registerOAuthInfos([oauthInfo]);
// Check if already signed in esriId.checkSignInStatus(oauthInfo.portalUrl + "/sharing") .then(() => { // Already signed in, load portal const portal = new Portal({ authMode: "immediate" }); return portal.load(); }) .then((portal) => { console.log("Welcome,", portal.user.fullName); displayUserContent(portal); }) .catch(() => { // Not signed in, show sign-in button showSignInButton(); });
function showSignInButton() { const btn = document.getElementById("signInBtn"); btn.onclick = () => { esriId.getCredential(oauthInfo.portalUrl + "/sharing") .then(() => { window.location.reload(); }); }; }
OAuth Component
<!-- Using OAuth component --> <arcgis-oauth app-id="YOUR_APP_ID"></arcgis-oauth>
<script type="module"> const oauthComponent = document.querySelector("arcgis-oauth");
oauthComponent.addEventListener("arcgisSignIn", (event) => { console.log("Signed in:", event.detail.credential); });
oauthComponent.addEventListener("arcgisSignOut", () => { console.log("Signed out"); }); </script>
API Keys
Configure API Key
import esriConfig from "@arcgis/core/config.js";
// Set API key for accessing services esriConfig.apiKey = "YOUR_API_KEY";
// Now basemaps and services will use the API key const map = new Map({ basemap: "arcgis/streets" // Requires API key });
API Key in HTML
<script> // Set before loading the SDK window.esriConfig = { apiKey: "YOUR_API_KEY" }; </script> <script src="https://js.arcgis.com/4.34/"></script>
Enterprise Portal Authentication
Configure for Enterprise Portal
const oauthInfo = new OAuthInfo({ appId: "YOUR_APP_ID", portalUrl: "https://your-portal.com/portal", popup: true });
esriId.registerOAuthInfos([oauthInfo]);
Set Portal URL Globally
import esriConfig from "@arcgis/core/config.js";
esriConfig.portalUrl = "https://your-portal.com/portal";
Token-Based Authentication
Get Token Manually
const credential = await esriId.getCredential("https://services.arcgis.com/..."); console.log("Token:", credential.token); console.log("Expires:", new Date(credential.expires));
Register Token
esriId.registerToken({ server: "https://services.arcgis.com/", token: "YOUR_TOKEN" });
Portal User Information
import Portal from "@arcgis/core/portal/Portal.js";
const portal = new Portal({ authMode: "immediate" }); await portal.load();
// User info console.log("Username:", portal.user.username); console.log("Full name:", portal.user.fullName); console.log("Email:", portal.user.email); console.log("Role:", portal.user.role); console.log("Thumbnail:", portal.user.thumbnailUrl);
// Organization info console.log("Org name:", portal.name); console.log("Org ID:", portal.id);
Query User Items
import Portal from "@arcgis/core/portal/Portal.js"; import PortalQueryParams from "@arcgis/core/portal/PortalQueryParams.js";
const portal = new Portal({ authMode: "immediate" }); await portal.load();
// Query user's items
const queryParams = new PortalQueryParams({
query: owner:${portal.user.username},
sortField: "modified",
sortOrder: "desc",
num: 20
});
const result = await portal.queryItems(queryParams);
result.results.forEach(item => { console.log(item.title, item.type, item.id); });
Credential Persistence
// Clear stored credentials esriId.destroyCredentials();
// Find a specific credential const credential = esriId.findCredential("https://services.arcgis.com/...");
Handling Authentication Errors
// Global handler for authentication challenges esriId.on("credential-create", (event) => { console.log("New credential created:", event.credential); });
// Handle layer authentication errors layer.on("layerview-create-error", (event) => { if (event.error.name === "identity-manager:not-authorized") { console.log("Authentication required for this layer"); signIn(); } });
Trusted Servers
import esriConfig from "@arcgis/core/config.js";
// Add servers that should receive credentials automatically esriConfig.request.trustedServers.push("https://services.arcgis.com"); esriConfig.request.trustedServers.push("https://your-server.com");
CORS and Proxy
import esriConfig from "@arcgis/core/config.js";
// Configure proxy for cross-origin requests esriConfig.request.proxyUrl = "/proxy/";
// Configure proxy rules esriConfig.request.proxyRules.push({ urlPrefix: "https://services.arcgis.com", proxyUrl: "/proxy/" });
Reference Samples
-
identity-oauth-basic
-
Basic OAuth2 authentication setup
-
identity-oauth-component
-
OAuth component-based authentication
Common Pitfalls
App ID registration: App ID must be registered with correct redirect URIs
Popup blockers: OAuth popup-based sign-in fails on mobile browsers.
// Anti-pattern: using popup flow on mobile OAuthInfo.create({ appId: "YOUR_APP_ID", popup: true // Blocked by most mobile browsers });
// Correct: use redirect flow for mobile, popup for desktop const isMobile = /iPhone|iPad|Android/i.test(navigator.userAgent); OAuthInfo.create({ appId: "YOUR_APP_ID", popup: !isMobile // Redirect flow on mobile, popup on desktop });
Impact: On mobile browsers (Safari, Chrome for iOS/Android), the OAuth popup is silently blocked. The user sees no sign-in dialog and cannot authenticate, with no error message explaining why.
Token expiration: Tokens expire - handle refresh or re-authentication
CORS errors: Configure trusted servers or use proxy for cross-origin
Portal URL trailing slash: A trailing slash in the portal URL causes token validation to fail.
// Anti-pattern: portal URL with trailing slash const portal = new Portal({ url: "https://myorg.maps.arcgis.com/" // Trailing slash }); await portal.load(); // Token validation may fail
// Correct: portal URL without trailing slash const portal = new Portal({ url: "https://myorg.maps.arcgis.com" // No trailing slash }); await portal.load();
Impact: The portal URL with a trailing slash does not match the token's server URL during validation. Authentication silently fails, or the user is prompted to sign in repeatedly because the token is never accepted.