Skip To Content

Use ArcGIS token authentication

In this topic

You can access services that have been secured using ArcGIS tokens in your ArcGIS Runtime SDK for .NET app by authenticating with the portal on which they are hosted. To authenticate, your code must provide a valid user name and password for the user. In return, you receive a token that can be included in all requests for secured content on the portal.

This topic describes some of the options you have for implementing ArcGIS token authentication in your app. Generally, you need to:

  • Anticipate or respond to attempts to access secured resources
  • Incude login information in your code or display a UI so the user can provide their user name and password
  • Generate and store credentials for portals from which you will read secured content

When working with any type of security, IdentityManager is a vital component. See the Security topic for more information about working with the identity manager.

Note:

Accessing secured services has major differences between the three APIs that make up ArcGIS Runtime SDK for .NET (particularly in the Windows Store API versus Desktop and Phone). Consult the documentation for each platform for which you need to work with secured content.

Use a hard-coded login

In the most basic scenario, you can provide a user name and password in your app code to authenticate for the secured resource you need to access. While this may sometimes be a valid use case and spares your user from interacting with a login dialog box, it's not very secure. A malicious user can retrieve login information by decompiling your app code or by viewing the HTTP traffic from your app.

In the following example, the IdentityManager is used to generate a credential for the specified portal. A user name and password are hard coded into the call to GenerateCredentialAsync. The credential is then stored with the IdentityManager before a secured resource hosted by the portal is accessed.

try
{
    var opts = new GenerateTokenOptions();
    opts.TokenAuthenticationType = TokenAuthenticationType.ArcGISToken;

    // generate an ArcGIS token credential with a hard-coded user name and password
    // (if authentication fails, an ArcGISWebException will be thrown)
    var cred = await IdentityManager.Current.GenerateCredentialAsync(
                                 "http://serverapps10.esri.com/arcgis/rest/services/", 
                                 "user1", 
                                 "pass.word1", 
                                 opts);

    // add the credential to the IdentityManager (will be included in all requests to this portal)
    IdentityManager.Current.AddCredential(cred);

    // load a layer based on a secured resource on the portal
    var layer = new ArcGISDynamicMapServiceLayer(new Uri
                        ("http://serverapps10.esri.com/arcgis/rest/services/GulfLawrenceSecureUser1/MapServer"));
    await layer.InitializeAsync();

    // add the layer to the map and zoom to its extent
    this.MyMapView.Map.Layers.Add(layer);
    await this.MyMapView.SetViewAsync(layer.FullExtent);
}
catch (ArcGISWebException webExp)
{
    var msgBox = new MessageDialog("Unable to authenticate with portal: " + webExp.Message);
    msgBox.ShowAsync();
}
catch (Exception exp)
{
    var msgBox = new MessageDialog("Unable to load secured layer: " + exp.Message);
    msgBox.ShowAsync();
}

In the previous example, accessing the secured content is seamless for the user. A credential is generated and stored with the identity manager before an attempt is made to access data on the portal. With the request to the secured resource, the identity manager automatically includes the required credential (ArcGIS token). From the user's perspective, the layer loads like any unsecured layer would. Additionally, any other secured resources on the same portal to which the provided login has permission can also be accessed without having to authenticate again.

Generating a credential before accessing a particular resource works fine in some situations, but what if your app allows users to access secured content that you cannot anticipate? Often, you need to respond to attempts to access secured content that you don't know about ahead of time. The following section describes creating a challenge handler component to respond to attempts to access a secured resource.

Use a challenge handler to generate a credential

When loading layers in your ArcGIS Runtime app, an ArcGISWebException is thrown when an attempt is made to access a secured resource if the identity manager does not have the required credential. Since you have the ability to catch such exceptions when creating or initializing a layer, it makes sense to respond by generating the required credential and trying to access the resource again. Fortunately, ArcGIS Runtime SDK for .NET provides a framework that allows you to respond to requests for secured content without having to directly handle the exceptions that are raised. To do so, create a challenge handler component.

A challenge handler class must implement the IChallengeHandler interface, which defines a single method, CreateCredentialAsync. The signature for this method is shown in the following example.

public async Task<Credential> CreateCredentialAsync(CredentialRequestInfo requestInfo)

As you can see, the challenge handler is responsible for returning a Credential. The CredentialRequestInfo that is passed into CreateCredentialAsync can be used to discover the URI of the service.

The following example shows an implementation of CreateCredentialAsync that returns a credential using the same hard-coded login information shown in the previous example.

private async Task<Credential> CreateHardCodedCredentialAsync(CredentialRequestInfo requestInfo)
{
    var cred = await IdentityManager.Current.GenerateCredentialAsync(
                            requestInfo.ServiceUri,
                            "user1",
                            "pass.word1");

    return cred;
}

To put this code into action, it must be a method of a class that implements IChallengeHandler, which must then be assigned to the IdentityManager.ChallengeHandler property. The following example creates a new challenge handler and sets the ChallengeHandler property.

var myChallenger = new MyChallengeHandler(); // custom class that implements IChallengeHander
IdentityManager.Current.ChallengeHandler = myChallenger;

As a shortcut, you can create a new challenge handler using the Esri.ArcGISRuntime.Security.ChallengeHandler utility class and passing in a function with the proper signature for the IChallengeHandler.CreateCredentialAsync method. The following example shows creating a new challenge handler using this utility class.

var myChallenger = new Esri.ArcGISRuntime.Security.ChallengeHandler
                                                       (this.CreateHardCodedCredentialAsync);
IdentityManager.Current.ChallengeHandler = myChallenger;

Once the ChallengeHandler property is assigned, attempts to access secured resources will be funnelled through your challenge handler (specifically, through the IChallengeHandler.CreateCredentialAsync method). A good way to see what's happening in your app when access to a secured resource is attempted, is to look at the HTTP traffic using a tool like Fiddler. Here's a summary of what you'll see:

  1. A request is made to a secured resource, the response is an unauthorized access error.
  2. Information about the portal that hosts the resource is requested, the response contains a tokenServicesUrl for obtaining ArcGIS tokens with an authorized user name and password.
  3. A user name and password are sent to the tokenServicesUrl. If the login is successful, the response contains a token (a long alphanumeric string).
  4. The request to the secured service is resent, this time with the token included in the URL query string. A successful response returns.
  5. All subsequent requests to the service (or any others hosted on the same portal) include the token.

While your challenge handler might include hard-coded login information as shown in the previous examples, it's more likely that you'll want to ask the user to provide their user name and password to access a secured resource. Displaying a UI to get login information is described in the following section.

Prompt the user for login information

When working with secured services in your app, you'll often need to prompt the user for their login information to gain access. This is a more secured solution than hard coding a user name and password into your app, although login information is sent as plain text and can be intercepted. If security of user's credentials is a concern, consider using OAuth authentication in your app instead. See the Use OAuth 2.0 authentication topic for more information about using OAuth in your ArcGIS Runtime app.

Implement your login UI

Implementing user login capability from scratch requires the same challenge handler component described in the previous section. Instead of returning a credential based on a hard-coded login, display a UI that allows the user to enter their user name and password. You then create and return a Credential by passing the user's login information to the same IdentityManager.GenerateCredentialAsync method described previously. The asynchronous nature of the challenge handler adds some complexity to this code, which requires creating the credential using a System.Threading.Tasks.TaskCompletionSource when the user submits their login from the UI. Refer to the TokenSecuredServices sample in the arcgis-runtime-samples-dotnet GitHub repository for an example.

Fortunately, the ArcGIS Runtime SDK for .NET Toolkit contains a challenge handler component that makes this much easier. The SignInChallengeHandler provides the recommended approach and is described in the following section.

Use the SignInChallengeHandler to show a login UI

If you haven't downloaded the ArcGIS Runtime SDK for .NET Toolkit, working with secured services may provide some motivation for doing so. The toolkit contains a challenge handler component called SignInChallengeHandler that encapsulates the logic and UI required to prompt the user for login information when a secured resource is encountered in your app. Using this class is much easier than writing your own and since you have access to the source code, you can easily make changes to the code or UI to suit your needs.

Follow the instructions in the Install the toolkit topic to include the toolkit in your Visual Studio project.

If you've tried to implement your logic for getting login information from the user in your challenge handler, you'll certainly appreciate the fact that the SignInChallengeHandler requires only a single line of code. The following example assigns the identity manager's challenge handler to the SignInChallengeHandler from the toolkit.

IdentityManager.Current.ChallengeHandler = new Esri.ArcGISRuntime.Toolkit.Security.SignInChallengeHandler();

After assigning the SignInChallengeHandler as the identity manager's challenge handler as shown in the previous example, requests for secured content causes the SIGN IN dialog box to display. If the user is authenticated, the resource loads; otherwise, an error message displays and the user can try to log in again. If the dialog box is dismissed, the map displays without the secured content.

Sign in dialog box presented by the SignInChallengeHandler

You can also allow the user to save the credentials they've provided for particular portals between sessions with your app. By default, the option to persist credentials is not shown in the SignInChallengeHandler UI. To enable this option, set the AllowSaveCredentials property to true when creating the SignInChallengeHandler, as shown in the following example.

IdentityManager.Current.ChallengeHandler = new Esri.ArcGISRuntime.Toolkit.Security.SignInChallengeHandler
                            { AllowSaveCredentials = true, 
                              CredentialSaveOption = CredentialSaveOption.Selected // set to CredentialSaveOption.Hidden to hide choice from the user
                            };
SignInChallengeHandler UI with AllowSave option enabled

The process of accessing token secured services with a challenge handler is illustrated in the following diagram.

Program flow when accessing a secured resource.
  1. A request is made to a secured resource.
  2. The portal responds with an unauthorized access error.
  3. A challenge handler associated with the identity manager is asked to provide a credential for the portal.
  4. A UI displays and the user is prompted to enter a user name and password.
  5. If the user is successfully authenticated, a credential (token) is incuded in requests to the secured service.
  6. The identity manager stores the credential for this portal and all requests for secured content includes the token in the request.

Related topics