ArcGIS Developer Foundation study materials
ArcGIS Developer Foundation study resources

API Key Editing Failure in a 40-Technician Field App

ArcGIS Developer Foundation · Put your knowledge to work in context.

All case studies

API Key Editing Failure in a 40-Technician Field App

A regional water utility built an internal JavaScript Maps SDK app for 40 field technicians who record valve inspections in a hosted feature layer in ArcGIS Online. The layer is shared with the FieldOps group, editor tracking is enabled, and the workflow is view-assigned-valves then applyEdits on Save. The developer generated an API key from a developer account that belongs to the group, scoped it to the item, and embedded it in the client configuration. Basemaps and layer drawing work correctly. When a technician taps Save, applyEdits returns HTTP 403 with the message that the user does not have permissions to access this resource or perform this operation. During testing, edits made by the developer account were stamped with the developer's username in created_by, and one technician's tablet showed another technician's name after a token change. The project lead wants per-technician attribution for audit, the ability to lock completed inspections so only the owning technician can edit them, and sessions that survive a 10-hour shift without forcing a re-login.

1. The read path works but applyEdits fails with 403. What is the root cause, and what authentication pattern should replace the API key?

Read the worked answer

The 403 is a symptom of identity, not scope. An API key identifies the application; with item scoping it can enable read access to that item, but it carries no end-user principal. applyEdits is authorized against the privileges of a user, and with only an API key there is no user to authorize. Editor tracking likewise has no username to stamp, which is exactly why records show the developer's account.

The correct pattern is OAuth 2.0 user authentication: register the app in the ArcGIS developer dashboard (or the portal, for Enterprise) with the exact redirect URI, implement the authorization-code flow with PKCE for a public client, and request only the privileges the workflow needs. ArcGIS Identity Manager, or an equivalent library, stores the access token and refresh token and attaches the token to each request, preferably in the X-Esri-Authorization header rather than in the URL.

Do not substitute app login (client credentials). It is legitimate for a trusted backend job, but every edit would again be attributed to one app account, so per-technician audit stays broken.

Verify by signing in as technician A, creating a feature, signing in as B, and updating it, then checking created_by and edited_by. Also confirm the token actually carries the feature edit privilege, since a token without it produces the same 403.

2. How do you guarantee created_by and edited_by reflect the technician, and enforce owner-only edits on completed inspections?

Read the worked answer

Two mechanisms must line up: attribution and authorization.

Attribution: editor tracking populates created_by and edited_by from the authenticated user behind the token. It is set at insert and, when the layer is configured to maintain it, on each update. If a technician's edits show another name, the token is not that technician's; look for a shared cached token, a device-level credential, or a backend proxy replaying a single app token.

Authorization: enable the layer setting that restricts editors to their own features. Ownership is assigned to the creator at insert, and an administrator can reassign it when someone leaves or when work is handed over, so build that into the runbook. Keep a separate nullable field such as inspected_by if you need a business-level record distinct from the login identity.

Caveats worth testing: ownership enforcement is a layer property, not something the client enforces, so a modified client cannot bypass it; and if a dispatcher creates an inspection on behalf of a technician, the dispatcher becomes the owner, which may be the wrong outcome for the lock requirement.

Run a two-account test plus an admin reassignment before rollout, and confirm the lock behaves correctly for records created before the setting was enabled.

3. Sessions must last a 10-hour shift, and the iPads are sometimes shared. How do you handle token lifecycle and prevent credential leakage?

Read the worked answer

Use short-lived access tokens plus refresh tokens, and distinguish error classes. On 498 (invalid token) and 499 (token required), attempt one silent refresh; if the refresh token is expired or revoked, send the user to sign-in. On 403, do not retry; it is a privilege problem and retrying only adds load.

Renew proactively: refresh when the token is within a few minutes of expiry, and single-flight the refresh so a burst of queued requests does not trigger a burst of refresh calls that invalidate each other.

Storage: on a public client there is no client secret, so the refresh token is the crown jewel. Keep it in the platform keychain or secure storage, not localStorage or IndexedDB. Never place tokens in query strings, logs, screenshots, or crash reports; query strings end up in proxy logs and analytics tools.

For shared iPads, an explicit sign-out must revoke the refresh token and clear cached layer data and pending edits. If pending edits exist, queue them locally and replay after the next successful authentication rather than discarding an inspector's work. Managed devices or per-user OS accounts reduce the shared-credential risk that app-level controls alone cannot fix.