Many premium ArcGIS Online services such as routing and GeoEnrichment (see available services below) require access tokens. Client secrets should never be exposed in any client-side application, whether your app is browser-based, a native app, or a hybrid. In order to implement a secure app you do not want to expose the token in a client-side app where it could be hijacked and used without your knowledge.

One method to mitigate this security risk is to use a proxy service that will store and manage your credentials and provide authentication. Your client-side app sends security sensitive requests to a proxy service, the proxy adds the necessary secrets, and then forwards the request to the service. The service sends the reply back to your proxy and your proxy forwards the reply back to your app. Other benefits are controls over rate limits and allowed referrers (whitelisting) to prevent runaway usage but enable publically accessible version of these premium services.

Esri provides two methods you can choose from to deploy a proxy service for your app:

  1. ArcGIS Online hosted proxy service configured on the ArcGIS for Developers website providing publically accessible endpoints for many premium services.
  2. A self-hosted resource proxy built in PHP, .NET, or Java that can proxy any ArcGIS service. Esri provides the source code on github.

ArcGIS Online hosted proxy

To use the proxy services hosted by Esri follow these steps:

  1. Create a new application or go to an existing application on your application page.

  2. If the app was not previously registered, select Register Application.

  3. Click on the Services tab.

  4. Select the service you wish to proxy and enter a rate limit for the number requests you want to allow over a given period.

    Proxy Service Configuration

  5. You can also set a whitelist of allowed referrers that can access this proxy. We recommend whitelisting your application domains in development and production.

  6. You can now use the new proxy URL that you are given to access the premium service you selected.

Available services

You can proxy the following services with this method:

Service Proxy Value
Geocoding geocode
Geoenrichment geoenrichment
Routing route
Routing (Async) asyncRoute
Routing Utilities routingUtilities
Closest Facility closestFacility
Closest Facility (Async) asyncClosestFacility
Service Area serviceArea
Service Area (Async) asyncServiceArea
Location Allocation asyncLocationAllocation
Vehicle Routing Problem syncVRP
Vehicle Routing Problem (Async) asyncVRP
Origin Destination Cost Matrix Service asyncODCostMatrix
World Traffic traffic
Elevation elevation
Elevation elevationSync
Hydrology hydrology

Self-hosted proxy service

Esri maintains source code to implement a server-side proxy service with PHP, .NET, and Java. These proxy services can be configured with your Client ID and Client Secret and when used with either the ArcGIS Runtime SDKs, ArcGIS API for JavaScript or Esri Leaflet will allow you to consume premium services with the token exchange handled by the proxy. Each project includes installation instructions and information regarding system requirements. Follow these instructions to setup and configure the proxy service on your web server.

This proxy services allow you to use an ArcGIS Online service that requires a token for secure access without storing that token with the client app where it could potentially be compromised by a hacker. Non-secure services that do not require a token are also serviced by the proxy. The proxy service also supports a whitelist based on the HTTP Referer header and service rate limiting.

Proxy service configuration

Below is a sample proxy configuration (proxy.config) that allows access to both the routing and GeoEnrichment services. There are several mechanisms available for restricting access to these resources:

  1. Set which HTTP Referrers should be allowed to access these resources with the allowedReferers attribute.
  2. On a service by service basis, configure a rateLimit and rateLimitPeriod (in minutes) to limit request frequency during the rate limit period.
<ProxyConfig
    mustMatch="true"
    logFile="proxy_log_xml.log"
    allowedReferers="example.com">

  <serverUrls>
    <serverUrl
      url="geoenrich.arcgis.com"
      oauth2Endpoint="https://www.arcgis.com/sharing/oauth2"
      clientId="6Xo1d-example-9Kn2"
      clientSecret="5a5d50-example-c867b6efcf969bdcc6a2"
      rateLimit="120"
      rateLimitPeriod="60"
      matchAll="true"/>

    <serverUrl
      url="route.arcgis.com"
      matchAll="true"
      oauth2Endpoint="https://www.arcgis.com/sharing/oauth2"
      clientId="6Xo1d-example-9Kn2"
      clientSecret="5a5d50-example-c867b6efcf969bdcc6a2"
      rateLimit="120"
      rateLimitPeriod="60"/>

  </serverUrls>
</ProxyConfig>

Assuming the proxy is hosted at URL /proxy.php you can send it the following request:

/proxy.php?http://geoenrich.arcgis.com/arcgis/rest/services/World/GeoenrichmentServer/Geoenrichment/enrich?studyAreas=[{"geometry":{"x":-117.1956,"y":34.0572}}]

Assuming the request came from one of your allowedReferers and the geoenrich.arcgis.com resource was under its rate limit, your request would succeed without requiring a token (because the token was supplied by the proxy service.)

Using proxies

Support for proxy services is provided with ArcGIS API for JavaScript and Esri Leaflet.

ArcGIS API for JavaScript

The ArcGIS API for JavaScript can be configured to automatically route all requests through a proxy when the request matches a given URL pattern. The following code would route all requests matching geoenrich.arcgis.com through the proxy at /proxy.php.

 urlUtils.addProxyRule({
   urlPrefix: "geoenrich.arcgis.com",
   proxyUrl: "/proxy.php"
});

Learn more about configuring proxies in the ArcGIS API for JavaScript.

Esri Leaflet

Esri Leaflet also supports using proxies with L.esri.Services.Service.

var geoenrichment = L.esri.Services.Service('https://geoenrich.arcgis.com/arcgis/rest/services/World/geoenrichmentserver/GeoEnrichment/', {
    proxy: '/proxy.php'
});

// now all requests made using this service will be routed through the proxy.
geoenrichment.get('enrich', {
  studyAreas: [{
    "geometry":{
      "x":-117.1956,
      "y":34.0572
      }
    }
  ]
}, callback);