Authenticating to Portal

4066
4
06-11-2015 11:06 AM
JohnDye
Occasional Contributor III

Can someone provide an example of how I have to create the ChallengeHandler to allow a user to authenticate to an On-Premise Portal?

I'm creating my FirstApp and while I can get it to work with ArcGIS Online, I can't get it to connect to our own Portal when I change the portalUri

XAML.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Esri.ArcGISRuntime.Controls;
using Esri.ArcGISRuntime.Portal;
using Esri.ArcGISRuntime.WebMap;
using Esri.ArcGISRuntime.Security;


namespace FirstApp
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>


    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
        private ArcGISPortal arcGISOnline;
        private ArcGISPortalItem selectedPortalItem;


        // changes the basemap layer
        private void baseMap_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            var combo = sender as ComboBox;
            var sel = combo.SelectedItem as ComboBoxItem;
            if (sel.Tag == null) { return; }


            //Find and remove the current basemap layer from the map
            if (mainMap == null) { return; }
            var oldBasemap = mainMap.Layers["BaseMap"];
            mainMap.Layers.Remove(oldBasemap);


            //Create a new basemap layer
            var newBaseMap = new Esri.ArcGISRuntime.Layers.ArcGISTiledMapServiceLayer();
            //Set the ServiceUri with the url defined for the ComboboxItem's Tag
            newBaseMap.ServiceUri = sel.Tag.ToString();
            //Give the layer an ID so it an still be found with the code above
            newBaseMap.ID = "BaseMap";
            
            //Insert the new basemap layer as the first (bottom) layer in the map
            mainMap.Layers.Insert(0, newBaseMap);
        }


        // searches the portal for content
        private async void SearchButton_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                if (this.arcGISOnline == null) 
                {
                    // create the uri for the portal 
                    var portalUri = new Uri("https://myserver.domain.com/portal/sharing/rest");
                    // create the portal 
                    this.arcGISOnline = await ArcGISPortal.CreateAsync(portalUri); 
                }
                // create a variable to store search results
                IEnumerable<ArcGISPortalItem> results = null;
                // get the search term provided in the UI
                var searchTerm = this.SearchTextBox.Text.Trim();
                var searchItem = this.ItemTypeCombobox.SelectedValue.ToString();


                // build a query that searches for the specified searchItem type
                // ('web mapping application' is excluded from the search since 'web map' will match those item types too)
                var queryString = string.Format("\"{0}\" type:(\"{1}\" NOT \"web mapping application\")", searchTerm, searchItem);
                var searchParameters = new SearchParameters()
                {
                    QueryString = queryString,
                    SortField = "avgrating",
                    SortOrder = QuerySortOrder.Descending,
                    Limit = 10
                };
                // execute the search
                var itemSearch = await this.arcGISOnline.SearchItemsAsync(searchParameters);
                results = itemSearch.Results;


                // show the results in the list box
                this.ResultListBox.ItemsSource = results;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error searching Portal");
            }
        }
        
        // resets the UI controls to keep them in sync with the currently selected portal item in the ResultsListBox
        private void ResetUI()
        {
            // clear UI controls
            this.SnippetTextBlock.Text = "";
            this.ThumbnailImage.Source = null;
            this.ShowMapButton.IsEnabled = false;
        }


        private void ResultSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            this.ResetUI();


            // store the currently selected portal item
            this.selectedPortalItem = this.ResultListBox.SelectedItem as ArcGISPortalItem;
            if (this.selectedPortalItem == null) { return; }


            // show the portal item snippet (brief description) in the UI
            if (!string.IsNullOrEmpty(this.selectedPortalItem.Snippet))
            {
                this.SnippetTextBlock.Text = this.selectedPortalItem.Snippet;
            }


            // show a thumnail for the selected portal item (if there is one)
            if (this.selectedPortalItem.ThumbnailUri != null)
            {
                var src = new BitmapImage(this.selectedPortalItem.ThumbnailUri);
                this.ThumbnailImage.Source = src;
            }


            // enable the show map button when a web map portal item is chosen
            this.ShowMapButton.IsEnabled = (this.selectedPortalItem.Type == ItemType.WebMap);
        }


        private async void ShowMapButton_Click(object sender, RoutedEventArgs e)
        {
            // create a web map from the selected portal item
            var webMap = await WebMap.FromPortalItemAsync(this.selectedPortalItem);


            // load the web map into a web map view model
            var webMapVM = await WebMapViewModel.LoadAsync(webMap, this.arcGISOnline);


            // show the web map view model's map in the page's map view control
            this.mainMapView.Map = webMapVM.Map;
        }
    }
}
Tags (3)
0 Kudos
4 Replies
ToddBlanchette
Occasional Contributor II

Hey John,

You'll have to setup a token (ArcGIS or OAuth), use network credentials or use certificates.  More info on how to use these processes and their returns is found at:

Security—ArcGIS Runtime SDK for .NET | ArcGIS for Developers

Cheers,

Todd

0 Kudos
JohnDye
Occasional Contributor III

Hi Todd, thanks for the response. This is my very second day with C# and .NET. I looked at that document and I have have been struggling to implement it

The document seems to indicate that the logic I should be using in XAML.cs is:

try
{
    // exception will be thrown here for bad credential ...
    var cred = await Esri.ArcGISRuntime.Security.IdentityManager.Current.GenerateCredentialAsync(
        PORTAL_SERVER_URL, UserTextBox.Text, PasswordTextBox.Password);


    // add the credential if it was generated successfully
    Esri.ArcGISRuntime.Security.IdentityManager.Current.AddCredential(cred);


    // connecting to the portal will use an available credential (based on the server URL)
    _portal = await Esri.ArcGISRuntime.Portal.ArcGISPortal.CreateAsync(new Uri(PORTAL_SERVER_URL));
}
catch(ArcGISWebException webExp)
{
    var msg = "Could not log in. Please check credentials. Error code: " + webExp.Code;


var messageDlg = new MessageDialog(msg);
await messageDlg.ShowAsync();
}





What I don't know is where to drop that code within my .cs file. There also doesn't seem to be any kind of indication that I need to provide a using statement or anything else. It's very unclear for a novice.

AnttiKajanus1
Occasional Contributor III

Hey,

Are you using Windows Store or Phone?

Some other reading and extra information about the topic :

Use ArcGIS token authentication—ArcGIS Runtime SDK for .NET | ArcGIS for Developers

Use OAuth 2.0 authentication—ArcGIS Runtime SDK for .NET | ArcGIS for Developers

Here is simple sample how to use build in authentication in Windows Store. App doesn't really do anything but sign in, created portal (authenticated version), gets users information and signs out from the portal. Let me know if you need more help with this. Typically you save instance of the portal for longer period and use that to access the portal information but here it's done like this to keep things simple.

using Esri.ArcGISRuntime.Portal;
using Esri.ArcGISRuntime.Security;
using System;
using System.Linq;
using System.Threading.Tasks;
using Windows.UI.Xaml.Controls;


namespace ArcGISApp27
{
    public sealed partial class MainPage : Page
    {
    private const string PORTAL_URL = "https://www.arcgis.com/sharing/rest/";


        public MainPage()
        {
            this.InitializeComponent();
        Initialize();
        }


    private async Task SignInAsync()
    {
        try
        {
            // This prompts UI for the authentication
            var crd = await IdentityManager.Current.GetCredentialAsync(new CredentialRequestInfo { ServiceUri = PORTAL_URL }, true);
            
            IdentityManager.Current.AddCredential(crd);
        }
        catch { } // can happen if user cancels the authentication
    }


    private async Task SignOut()
    {
        // Clear the credentials cache in order not to reuse them during the next session
        (IdentityManager.Current.ChallengeHandler as Esri.ArcGISRuntime.Security.DefaultChallengeHandler).ClearCredentialsCache();
        // Clear IM credentials so they won't be used during this session
        foreach (var crd in IdentityManager.Current.Credentials.ToArray())
        IdentityManager.Current.RemoveCredential(crd);
        // Do what ever you do after sign out
    }
    
    private async void Initialize()
    {
        ArcGISPortal portal = null;
        try
        {
            // Sign in
            await SignInAsync();


            // Create portal intance, this gets automatically credentials set in because credetials
            // are set in when sign in is done
            // Usually you are keeping reference to the portal instance and use it to access the portal
            // when needed.
            portal = await ArcGISPortal.CreateAsync(new Uri(PORTAL_URL));


            // use portal 
            var currentUser = portal.CurrentUser;


            // sign out
            await SignOut();
        }
        catch (Exception ex)
        {
            // Handle
        }
    }
   }
}
JohnDye
Occasional Contributor III

Hi Antti,

Thanks for that response. I'm actually using Windows Desktop, I'm going to give this code a go today. I'll probably need additional help but will post here if so. Thanks

0 Kudos