Working with secure ArcGIS services

Layers and tasks in ArcGIS Runtime SDK for Android communicate with ArcGIS for Server web services. These services can be secured to permit access to only authorized users. An ArcGIS for Server instance can use one of two authentication modes: token-based authentication or HTTP (including Windows) authentication. Both modes are supported by the runtime.

If you're the administrator of an ArcGIS for Server system and want to restrict access to your ArcGIS web services, information is available in Securing your ArcGIS Server site (Windows) and Securing your ArcGIS Server site (Linux) in the ArcGIS for Server online help.

Token-based authentication

Services secured with token-based authentication require that a token be included in each request for a map, query, and so on. To use a secure service through the API, you need to know the credentials (username and password) or tokens to access the service. The server administrator can provide this information. Once you know the credentials or tokens to use, you need to pass them to the layer or the task through a UserCredentials object in the Java code or hardcode the tokens in the layout XML by including a long-term token directly in the URL. The following code examples demonstrate several different ways to access secure services.

Instantiate the layer or task with credentials through the UserCredentials object in Java code as shown in the following example:

UserCredentials creds = new UserCredentials();
creds.setUserAccount("username", "password ");
// The following line can be omitted if the default token service is used.
ArcGISDynamicMapServiceLayer layer = new ArcGISDynamicMapServiceLayer(

Alternatively, instead of passing in the username and password, you can pass in a token obtained from the corresponding token service as shown in the following example:

UserCredentials creds = new UserCredentials();
creds.setUserToken("token", "referer");
Locator al = new Locator(

The API will automatically try to discover the URL of the token service where tokens can be acquired. If you know this information in advance, you can provide it to the UserCredentials object as shown in the previous example so that it does not make any unnecessary network requests to discover the same information.

Using self-signed certificates

To safeguard content exchanged over the network, HTTPS should be used whenever supported by the service. HTTPS connections use Secure Sockets Layer (SSL) to encrypt information that is exchanged over the network and digital certificates to verify identities of the parties involved. The ArcGIS API for Android supports certificates issued by a trusted certificate authority as well as self-signed certificates. If you want to trust a server that is using a self-signed certificate, you can choose one of two workflows supported by ArcGIS API for Android based on your business requirement.

Workflow 1

You can trust a certain server using self-signed certificates by importing the server's certificate and pre-loading the trusted certificate on the client side. This workflow enables server authentication when supplied with a truststore file containing one or several trusted certificates. See the following code example:

// Load self-signed certificate
KeyStore keyStore = KeyStore.getInstance("BKS");
InputStream is = this.getResources().openRawResource(;
keyStore.load(is, "xxx".toCharArray());
// Populate Security Info
UserCredentials creds = new UserCredentials();
creds.setUserAccount("username", "password");
ArcGISFeatureLayer layer = new ArcGISFeatureLayer(

Workflow 2

This workflow allows users to trust a server using self-signed certificates without pre-loading the server certificate. To do so, create an instance of OnSelfSignedCertificateListener and register it to SelfSignedCertificateHandler, which is a final class. OnSelfSignedCertificateListener will be fired when the server is using a self-signed certificate. Return true from OnSelfSignedCertificateListener if you want to trust the server. The following code snippet shows this workflow:

public boolean getUserPermission() {
// Set listener to handle self-signed certificate
  new OnSelfSignedCertificateListener() {
    public boolean checkServerTrusted(X509Certificate[] chain, String authType) {
      try {
      } catch (Exception e) {
        return getUserPermission();

      return true;

HTTP/Windows authentication

When a request is made to a service secured with HTTP authentication (HTTP basic or HTTP digest), user credentials must be supplied to the service through the UserCredentials object. See the following code example:

UserCredentials creds = new UserCredentials();
creds.setUserAccount("xxx", "xxx");                         
Geoprocessor gp = new Geoprocessor(

Exception handling

When a layer fails to load to a map due to security, both the layer and the map will send out an EsriSecurityException error. Users can listen to the status changed events on MapView or Layer to handle the error. You can listen to the LAYER_LOADING_FAILED on MapView or INITIALIZATION_FAILED on Layer and get the error detail through the getError() method on STATUS. A layer can be re-initialized with a given credential. If the layer is re-initialized successfully, it will be reloaded into the map automatically. The following is an example of exception handling through MapView:

MapView map;
ArcGISFeatureLayer fl;

public void onCreate(Bundle savedInstanceState) {
  map = new MapView(this);
  String url = ...;
  fl = new ArcGISFeatureLayer(url, MODE.ONDEMAND);
  // Handle status change event on MapView
  map.setOnStatusChangedListener(new OnStatusChangedListener() {
    private static final long serialVersionUID = 1L;

    public void onStatusChanged(Object source, STATUS status) {
      // Check if a layer is failed to be loaded due to security
      if (status == STATUS.LAYER_LOADING_FAILED) {
        if ((status.getError()) instanceof EsriSecurityException) {
          EsriSecurityException securityEx = (EsriSecurityException) status.getError();
          if (securityEx.getCode() == EsriSecurityException.AUTHENTICATION_FAILED)
            Toast.makeText(map.getContext(), "Authentication Failed!", 
          else if (securityEx.getCode() == EsriSecurityException.TOKEN_INVALID)
            Toast.makeText(map.getContext(), "Invalid Token!", Toast.LENGTH_SHORT).show();
          else if (securityEx.getCode() == EsriSecurityException.TOKEN_SERVICE_NOT_FOUND)
            Toast.makeText(map.getContext(), "Token Service Not Found!", 
          else if (securityEx.getCode() == EsriSecurityException.UNTRUSTED_SERVER_CERTIFICATE)
            Toast.makeText(map.getContext(), "Untrusted Host!", Toast.LENGTH_SHORT).show();
          if (source instanceof ArcGISFeatureLayer) {
            // Set user credential through username and password
            UserCredentials creds = new UserCredentials();
            creds.setUserAccount("username", "password");

When an operational layer of a web map is fails to load due to security, the map will send out an EsriSecurityException error. Users can listen to the WebMap loading events to handle the error as shown in the following code example:

MapView map;

public void onCreate(Bundle savedInstanceState) {
  OnWebMapLoadListener listener = new OnWebMapLoadListener() {

    public MapLoadAction<UserCredentials> onWebMapLoadError(MapView source,
      WebMap webmap, WebMapLayer wmlayer, Layer layer, Throwable error,
      UserCredentials credentials) {
      if (error instanceof EsriSecurityException) {
        UserCredentials creds;
        creds = new UserCredentials();
        creds.setUserAccount("username", "password");

        if (credentials != null && (credentials.getUserName() == creds.getUserName() 
            && credentials.getPassword() == creds.getPassword())) 
          return null;
        return new MapLoadAction<UserCredentials>(Action.CONTINUE_OPEN_WITH_THE_PARAMETER, creds);
      return null;

   public void onWebMapLayerAdd(MapView source, WebMap webmap,
     WebMapLayer wmlayer, Layer layer, UserCredentials credentials) {


  String url = ...;
  map = new MapView(this, url, "", "", "", listener);

Public key infrastructure

A public key infrastructure (PKI) is a set of policies and services used to support authentication and secure communication over insecure networks. In a PKI, the identity of a user, organization, or software agent is represented by a pair of digital keys. Users in a PKI are required to authenticate themselves by presenting their digital keys and are never issued a user name and password. PKI uses a mathematical technique called public key cryptography to generate the digital keys that represent a user or organization.

Using ArcGIS for Server in a PKI

ArcGIS for Server will leverage the PKI solution in COTS Web Servers (IIS, WebLogic and Websphere, and so on) through the use of the ArcGIS Web Adaptor. When a request is made for a resource on ArcGIS for Server, the web server will authenticate the user by validating the client certificate provided. The request (along with the user name) is then forwarded to ArcGIS for Server via the Web Adaptor. ArcGIS for Server verifies that the specified user has access to the requested resource before sending back the appropriate response.

Learn how to enable SSL using a new CA-signed certificate

Accessing PKI services

Accessing PKI services from an Android device is OS dependent. You can install certificates on your device from Settings > Security > Install certificates from storage. At issue is the fact that you may not be able to access certificates installed in this manner from devices with v3.x (Honeycomb) or earlier. Version 4.0.x Ice Cream Sandwich (ICS) introduces a new KeyChain class to access these certificates. If you're using a pre-ICS device, you can access some of the installed certificates in a keystore located in the following locations:

  • Pre ICS > /system/etc/security/cacerts.bks
  • ICS or later > /system/etc/security/cacerts

You can read the certificate there; however, some devices don't list the one you just installed. In this case, you can access your certificate from anywhere on the device that is accessible by the API. To support all devices with API 2.2 and later, the KeyStore class is used, which maintains keys and their owners. See the following code example:

Access PKI from sdcard location

KeyStore keystore = KeyStore.getInstance("BKS");
certInputStream = new FileInputStream("/sdcard/cert/example.bks"); 
keystore.load(is, "web.adf".toCharArray());
UserCredentials.setTrustStore(keystore, "web.adf", keystore);