Can I get a sample code for authorizing a runtime user against ArcGIS.COM? I like to have my own dialog box (not the default ESRI one) that prompts the user for named user login.

390
1
01-03-2020 11:55 AM
AliDiba
New Contributor

Can I get a sample code for authorizing a runtime user against ArcGIS.COM? I like to have my own dialog box (not the default ESRI one) that prompts the user for named user login.

0 Kudos
1 Reply
JoeHershman
MVP Regular Contributor

Don't really have a way to package up a working sample but basically have a View that has the Text boxes and a button to launch command.  When that executes you create a Credential using the passed in username and password.

Below is a ViewModel bound to the view (this is in Xamarin not WPF - and also uses Prism Framework).  LoginCommand is bound to the button.  Basically checks to make sure the user entered the username and password and then tries to connect using the IPortalManager service - Code below).

public class LoginPopupPageViewModel : ViewModelBase
{
	private readonly IPageDialogService _pageDialogService;
	private readonly IPortalManager _portalManager;

	#region Private Backing Fields

	private string _userName;
	private string _password;
	private bool _useDevAgol;
	private string _navigateToPage;
	private string _message;

	#endregion

	public LoginPopupPageViewModel(IPageDialogService pageDialogService, IPortalManager portalManager, IEventAggregator eventAggregator) : base(eventAggregator)
	{
		_pageDialogService = pageDialogService;
		_portalManager = portalManager;
		Title = "Peoples As-Built";
		_useDevAgol = false;

	}

	#region Bound Properties

	public bool UseDevAgol
	{
		get => _useDevAgol;
		set => SetProperty(ref _useDevAgol, value);
	}

	public string UserName
	{
		get => _userName;
		set => SetProperty(ref _userName, value);
	}

	public string Password
	{
		get => _password;
		set => SetProperty(ref _password, value);
	}

	public string Message
	{
		get => _message;
		set => SetProperty(ref _message, value);
	}

	#endregion

	#region LoginCommand

	public DelegateCommand LoginCommand => new DelegateCommand(ExecuteLogin);

	public async void ExecuteLogin()
	{
		try
		{
			if (UserName == null)
			{
				await _pageDialogService.DisplayAlertAsync("User Name", "You need to enter a User Name", "Close");
				return;
			}

			if (Password == null)
			{
				await _pageDialogService.DisplayAlertAsync("Password", "You need to enter a Password", "Close");
				return;
			}

			Settings.UserName = UserName;
			Settings.Password = Password;
			Settings.UseDevAgol = UseDevAgol;

			await NavigationService.NavigateAsync("BusyPopupPage", new NavigationParameters("?message=Logging into ArcGIS Online"));

			//TODO: Check for connection - See Xamarin Essentials
			await _portalManager.OpenPortalAsync();

			await NavigationService.GoBackAsync(new NavigationParameters("?source=busy"));

			if ( _portalManager.ConnectionStatus == ConnectionStatus.InvalidUser )
			{
				await _pageDialogService.DisplayAlertAsync("Login failed", "Login failed. Please retry", "Close");
				UserName = Password = null;
				return;
			}

			// Integrated this so that we can direct to different end destinations after login
			if (_navigateToPage != null)
			{
				await NavigationService.NavigateAsync(_navigateToPage);
			}
			else
			{
				//return to calling page
				await NavigationService.GoBackAsync();
			}

		}
		catch (Exception)
		{
			await _pageDialogService.DisplayAlertAsync("Login failed", "Login failed. Please retry", "Close");
		}
	}

	#endregion


	#region CancelCommand

	public ICommand CancelCommand => new DelegateCommand<object>(ExecuteCancel);

	private async void ExecuteCancel(object obj)
	{
		await NavigationService.GoBackAsync();
	}

	#endregion

}

PortalManager:  One of the things that is needed is in the AuthenticationManager.Current.GenerateCredentialAsync method you need to use the sharing Url =  https://arcgis.com/sharing/rest

public class PortalManager : IPortalManager
{
	private ArcGISPortal _portal;
	private TokenCredential _credential;
	private readonly ILogger _log;

	public PortalManager(ILogManager logManager)
	{
		_log = logManager.GetLog();
		ConnectionStatus = ConnectionStatus.NotConnected;
		PortalUser = null;
	}

	public async Task<ArcGISPortal> OpenPortalAsync(bool refresh = false)
	{
		if (_portal != null && !refresh) return _portal;

		try
		{
			var credential = await Credential(true);

//public static Uri AgolUrl => new Uri("https://arcgis.com");

			_portal = await ArcGISPortal.CreateAsync(Constants.AgolUrl, credential, CancellationToken.None);
			ConnectionStatus = ConnectionStatus.Connected;

			PortalUser = _portal.User;

			return _portal;
		}
		catch (ArcGISWebException)
		{
			ConnectionStatus = ConnectionStatus.InvalidUser;
			return null;
		}
		catch (InvalidOperationException)
		{
			ConnectionStatus = ConnectionStatus.UnableToConnect;
			return null;
		}
		catch (Exception)
		{
			ConnectionStatus = ConnectionStatus.UnableToConnect;
			return null;
		}
	}

	public async Task<TokenCredential> Credential(bool refresh)
	{
		if (_credential != null && !refresh) return _credential;

// public static Uri AgolSharingUri = new Uri("https://arcgis.com/sharing/rest");

		_credential = await AuthenticationManager.Current.GenerateCredentialAsync(Constants.AgolSharingUri, Settings.UserName, Settings.Password);

		return _credential;
	}

	public void  SignOut()
	{
		_portal = null;
		_credential = null;
		PortalUser = null;
	}

	public ConnectionStatus ConnectionStatus { get; private set; }

	public PortalUser PortalUser { get; private set; }
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Hope that helps

-Joe

Thanks,
-Joe
0 Kudos