Skip To Content ArcGIS for Developers Sign In Dashboard

ArcGIS Runtime SDK for .NET

Integrated windows authentication

This code sample is available for these platforms:
View Sample on GitHub

Use Windows credentials to access services hosted on a portal secured with Integrated Windows Authentication (IWA).

How to use the sample

  1. Enter the URL to your IWA-secured portal.
  2. Click the button to search for web maps stored on the portal.
  3. You will be prompted for a user name, password, and domain (some platforms will use the current Windows login).
  4. If you authenticate successfully, portal item results will display in the list.
  5. Select a web map item to display it in the map view.

How it works

  1. The AuthenticationManager object is configured with a challenge handler that will prompt for a Windows login (username, password, and domain) if a secure resource is encountered.
  2. When a search for portal items is performed against an IWA-secured portal, the challenge handler creates an ArcGISNetworkCredential object from the information entered by the user.
  3. If the user authenticates, the search returns a list of web maps (ArcGISPortalItem) and the user can select one to display as a Map.
  4. On some platforms, the current Windows account is used by default and a login prompt will not be shown if it can authenticate successfully.

Relevant API

  • AuthenticationManager
  • ArcGISPortal
  • ArcGISNetworkCredential

About the data

This sample searches for web map portal items on a secure portal. To successfully run the sample, you need:

  • Access to a portal secured with Integrated Windows Authentication that contains one or more web map items.
  • A login that grants you access to the portal.

Additional information

IWA, which is built into Microsoft Internet Information Server (IIS), works well for intranet applications but isn't always practical for internet apps.

More information about IWA and it's use with ArcGIS can be found at the following links:

Tags

Authentication, Security, Windows, Portal

Sample Code

<UserControl x:Class="ArcGISRuntime.UWP.Samples.IntegratedWindowsAuth.IntegratedWindowsAuth"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:esriUI="using:Esri.ArcGISRuntime.UI.Controls">
    <Grid Background="DarkGray">
        <Grid x:Name="MyMapGrid">
            <esriUI:MapView x:Name="MyMapView" />
        </Grid>
        <!-- Search web maps UI-->
        <Border x:Name="LoadMapPanel" 
                Background="DarkGray" BorderBrush="Black" BorderThickness="1"
                Width="300" Height="600"
                HorizontalAlignment="Left" VerticalAlignment="Center">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="100"/>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="50"/>
                    <RowDefinition/>
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="Auto"/>
                </Grid.ColumnDefinitions>
                <Button Foreground="Blue"
                        Grid.Row="2" Grid.Column="1"
                        HorizontalAlignment="Center" VerticalAlignment="Center"
                        Width="33"
                        Click="ShowHidePanel_Click">
                    <Button.Content>
                        <TextBlock x:Name="SlideText">
                            <LineBreak/>
                            <Run Text="&lt;"/>
                            <LineBreak/>
                            <Run Text="&lt;"/>
                            <LineBreak/>
                            <Run Text="&lt;"/>
                            <LineBreak/>
                        </TextBlock>
                    </Button.Content>
                </Button>
                <Button x:Name="SearchPublicMapsButton"
                        Grid.Row="0"
                        Content="Search Public Maps"														
                        Width="265" Height="45"
                        HorizontalAlignment="Center"
                        Margin="0,30,0,0"
                        Click="SearchPublicMapsButtonClick"/>
                <Grid Grid.Row="1"
                      Margin="0,10"
                      HorizontalAlignment="Center">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="Auto"/>
                    </Grid.RowDefinitions>
                    <TextBox x:Name="SecurePortalUrlTextBox" 
                             PlaceholderText="URL to an IWA secured portal"
                             MaxWidth="265"
                             Grid.Row="0" Height="20"/>
                    <Button x:Name="SearchSecureMapsButton" 
                            Grid.Row="1"
			                Content="Search IWA Secured Maps"													
			                Width="265" Height="45"
                            Click="SearchSecureMapsButtonClick"/>
                </Grid>
                <ListBox x:Name="MapItemListBox"
                        Grid.Row="2"                         
                        FontSize="12"
                        Width="265" Height="200"/>
                <Button x:Name="AddMapItem"
                        Grid.Row="3"
                        Content="Load Web Map"
                        Width="150" Height="45"
                        HorizontalAlignment="Center"
                        IsEnabled="False"
                        Click="AddMapItemClick"/>
                <StackPanel x:Name="MessagePanel"
			                Grid.Row="4" Grid.ColumnSpan="2"
                            Orientation="Vertical"							
			                Margin="0,10"
                            MaxWidth="265">
                    <ScrollViewer>
                        <TextBlock x:Name="MessagesTextBlock" 
                                   Text="No credentials have been entered."
                                   TextWrapping="Wrap"/>
                    </ScrollViewer>
                    <ProgressBar x:Name="ProgressStatus" 
			                     IsIndeterminate="True"
                                 Visibility="Collapsed"/>
                </StackPanel>
            </Grid>
        </Border>
    </Grid>
</UserControl>
// Copyright 2018 Esri.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
// You may obtain a copy of the License at: http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an 
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific 
// language governing permissions and limitations under the License.

using Esri.ArcGISRuntime.Mapping;
using Esri.ArcGISRuntime.Portal;
using Esri.ArcGISRuntime.UI.Controls;
using System;
using System.Linq;
using System.Text;
using Windows.UI.Popups;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Animation;

namespace ArcGISRuntime.UWP.Samples.IntegratedWindowsAuth
{
    // Important:
    //    You must add the "Private Networks" capability to use Integrated Windows Authentication (IWA)
    //    in your UWP project. Add this capability by checking "Private Networks (Client and Server)"
    //    in your project's Package.appxmanifest file.
    [ArcGISRuntime.Samples.Shared.Attributes.Sample(
           "Integrated Windows Authentication",
           "Security",
           "This sample demonstrates how to use a Windows login to authenticate with a portal that is secured with IWA.",
           "1. Enter the URL to your IWA-secured portal.\n2. Click the button to search for web maps on the secure portal.\n3. You will be prompted for a user name, password, and domain to authenticate with the portal.\n4. If you authenticate successfully, search results will display.",
           "Authentication, Security, Windows")]
    public partial class IntegratedWindowsAuth
    {
        // Note: The Universal Windows Platform handles challenging for Windows credentials.
        //       You do not need to surface your own UI to prompt the user for username, password, and domain.

        // The ArcGIS Online URL for searching public web maps.
        private string _publicPortalUrl = "http://www.arcgis.com";

        // The public and secured portals.
        ArcGISPortal _iwaSecuredPortal = null;
        ArcGISPortal _publicPortal = null;

        // Track if the user is looking at search results from the public or secured portal.
        bool _usingPublicPortal;

        public IntegratedWindowsAuth()
        {
            InitializeComponent();

            // Show the light gray canvas basemap.
            MyMapView.Map = new Map(Basemap.CreateLightGrayCanvasVector());
        }

        // Search the public portal for web maps and display the results in a list.
        private async void SearchPublicMapsButtonClick(object sender, RoutedEventArgs e)
        {
            try
            {
                // Create an instance of the public portal.
                _publicPortal = await ArcGISPortal.CreateAsync(new Uri(_publicPortalUrl));

                // Call a function to search the portal.
                SearchPortal(_publicPortal);

                // Set a variable that indicates this is the public portal.
                // When a map is loaded from the results, will need to know which portal it came from.
                _usingPublicPortal = true;
            }
            catch (Exception ex)
            {
                // Report any errors that were encountered.
                MessagesTextBlock.Text = ex.Message;
            }
        }

        // Search the IWA-secured portal for web maps and display the results in a list.
        private async void SearchSecureMapsButtonClick(object sender, RoutedEventArgs e)
        {
            try
            {
                // Get the value entered for the secure portal URL.
                string securedPortalUrl = SecurePortalUrlTextBox.Text.Trim();

                // Make sure a portal URL has been entered in the text box.
                if (string.IsNullOrEmpty(securedPortalUrl))
                {
                    MessageDialog dialog = new MessageDialog("Please enter the URL of the secured portal.", "Missing URL");
                    await dialog.ShowAsync();
                    return;
                }

                // Create an instance of the IWA-secured portal, the user may be challenged for access.
                _iwaSecuredPortal = await ArcGISPortal.CreateAsync(new Uri(securedPortalUrl));

                // Call a function to search the portal.
                SearchPortal(_iwaSecuredPortal);

                // Set a variable that indicates this is the secure portal.
                // When a map is loaded from the results, will need to know which portal it came from.
                _usingPublicPortal = false;
            }
            catch (Exception ex)
            {
                // Report errors (connecting to the secured portal, for example).
                MessagesTextBlock.Text = ex.Message;
            }
        }

        private async void SearchPortal(ArcGISPortal currentPortal)
        {
            // Clear any existing results.
            MapItemListBox.Items.Clear();

            // Show status message and the progress bar.
            MessagesTextBlock.Text = "Searching for web map items on the portal at " + currentPortal.Uri.AbsoluteUri;
            ProgressStatus.Visibility = Visibility.Visible;
            var messageBuilder = new StringBuilder();

            try
            {
                // Report connection info
                messageBuilder.AppendLine("Connected to the portal on " + currentPortal.Uri.Host);

                // Report the user name used for this connection.
                if (currentPortal.User != null)
                {
                    messageBuilder.AppendLine("Connected as: " + currentPortal.User.UserName);
                }
                else
                {
                    // Note: This shouldn't happen for a secure portal!
                    messageBuilder.AppendLine("Anonymous");
                }

                // Search the portal for web maps.
                var items = await currentPortal.FindItemsAsync(new PortalQueryParameters("type:(\"web map\" NOT \"web mapping application\")"));

                // Build a list of items from the results that shows the map name and stores the item ID (with the Tag property).
                var resultItems = from r in items.Results select new ListBoxItem { Tag = r.ItemId, Content = r.Title };

                // Add the items to the list box.
                foreach (var itm in resultItems)
                {
                    MapItemListBox.Items.Add(itm);
                }

                // Enable the button to load a selected web map item.
                AddMapItem.IsEnabled = true;
            }
            catch (Exception ex)
            {
                // Report errors searching the portal.
                messageBuilder.AppendLine(ex.Message);
            }
            finally
            {
                // Show messages, hide progress bar.
                MessagesTextBlock.Text = messageBuilder.ToString();
                ProgressStatus.Visibility = Visibility.Collapsed;
            }
        }

        private async void AddMapItemClick(object sender, RoutedEventArgs e)
        {
            // Get a web map from the selected portal item and display it in the map view.
            if (MapItemListBox.SelectedItem == null)
            {
                MessageDialog dialog = new MessageDialog("No web map item is selected.");
                await dialog.ShowAsync();
                return;
            }

            // Clear status messages.
            MessagesTextBlock.Text = string.Empty;

            // Store status (or errors) when adding the map.
            var statusInfo = new StringBuilder();

            try
            {
                // Clear the current MapView control from the app.
                MyMapGrid.Children.Clear();

                // See if using the public or secured portal; get the appropriate object reference.
                ArcGISPortal portal = null;
                if (_usingPublicPortal)
                {
                    portal = _publicPortal;
                }
                else
                {
                    portal = _iwaSecuredPortal;
                }

                // Throw an exception if the portal is null.
                if (portal == null)
                {
                    throw new Exception("Portal has not been instantiated.");
                }

                // Get the portal item ID from the selected list box item (read it from the Tag property).
                var itemId = (MapItemListBox.SelectedItem as ListBoxItem).Tag.ToString();

                // Use the item ID to create a PortalItem from the appropriate portal.
                var portalItem = await PortalItem.CreateAsync(portal, itemId);

                if (portalItem != null)
                {
                    // Create a Map using the web map (portal item).
                    Map webMap = new Map(portalItem);

                    // Create a new MapView control to display the Map.
                    MapView myMapView = new MapView
                    {
                        Map = webMap
                    };

                    // Add the MapView to the app.
                    MyMapGrid.Children.Add(myMapView);
                }

                // Report success.
                statusInfo.AppendLine("Successfully loaded web map from item #" + itemId + " from " + portal.Uri.Host);
            }
            catch (Exception ex)
            {
                // Add an error message.
                statusInfo.AppendLine("Error accessing web map: " + ex.Message);
            }
            finally
            {
                // Show messages.
                MessagesTextBlock.Text = statusInfo.ToString();
            }
        }

        #region UI code to show/hide the search controls
        // Function that will animate sliding a UI element to a new position.
        public void SlideElement(UIElement target, Orientation orientation, double? from, double to, int duration = 400, int startTime = 0, EasingFunctionBase easing = null)
        {
            // Use an ExponentialEase easing function if none was passed in.
            if (easing == null)
            {
                easing = new ExponentialEase();
            }

            // Create a transformation for the element.
            var transform = target.RenderTransform as CompositeTransform;
            if (transform == null)
            {
                transform = new CompositeTransform();
                target.RenderTransform = transform;
            }
            target.RenderTransformOrigin = new Windows.Foundation.Point(0.5, 0.5);

            // Create the animation and specify the to/from locations, easing function, and duration.
            DoubleAnimation slideAnimation = new DoubleAnimation
            {
                To = to,
                From = from,
                EasingFunction = easing,
                Duration = TimeSpan.FromMilliseconds(duration)
            };

            // Set the target for the animation and define the target property (translate the X or Y axis).
            Storyboard.SetTarget(slideAnimation, target);
            string axis = orientation == Orientation.Horizontal ? "X" : "Y";
            Storyboard.SetTargetProperty(slideAnimation, $"(UIElement.RenderTransform).(CompositeTransform.Translate{axis})");

            // Create a new storyboard and specify the start time.
            Storyboard slideStoryboard = new Storyboard
            {
                BeginTime = TimeSpan.FromMilliseconds(startTime)
            };

            // Add the slide animation and start it.
            slideStoryboard.Children.Add(slideAnimation);
            slideStoryboard.Begin();
        }

        // Track whether the search UI is visible or not.
        private bool panelVisible = true;

        // Slide the search panel in/out to show/hide the controls.
        private void ShowHidePanel_Click(object sender, RoutedEventArgs e)
        {
            // Set the button text and start/end location for the slide.
            SlideText.Text = "\n>\n>\n>\n";
            double startX = 0;
            double endX = -280;

            // If the panel is not visible, set the start/end to show it.
            if (!panelVisible)
            {
                startX = endX;
                endX = 0;
                SlideText.Text = "\n<\n<\n<\n";
            }

            // Call a function to animate the sliding of the panel.
            SlideElement(LoadMapPanel, Orientation.Horizontal, startX, endX);

            // Update the variable that tracks the state of the panel.
            panelVisible = !panelVisible;
        }
        #endregion
    }
}