Xamarin.Forms - Not Native Xamarin

Has anyone seen any examples of integrating Auth0 into a Xamarin.Forms project? I have reviewed the QuickStart for Xamarin but they are for native iOS and Android, not Xamarin.Forms. The implementations in each project seem different enough that it would likely not be possible to move the code to the shared Xamarin.Forms project (at least using the OIDC client).

Is there a potential to use the REST API directly or will the Google WebView issue (I would like Google as a social auth option) rear its head?

Also thought about adding a DepenencyService and building the concrete implementations in each platform specific project but I am not sure how I would pass in the UIViewController (iOS) or Activity (Android) since I would be using Xamarin Pages in the shared project.

1 Like

I did it like this.

    public class UserAccount
    {        
        public string Username { get; set; }
        public Dictionary<string, string> Properties { get; set; }
    }    

    public interface ISocialLoginManager
    {
        Task<UserAccount> GetUser();
    }

[assembly: Dependency(typeof(Auth0SocialLoginManager))]
namespace YourApp.Droid.Services
{
	public class Auth0SocialLoginManager : ISocialLoginManager
	{
		private readonly Auth0Client _auth0 = new Auth0Client(AppConstants.Auth0.Domain, AppConstants.Auth0.ClientId);
		
		public async Task<UserAccount> GetUser()
		{
		    Auth0User auth0User = null;
		    try
		    {
		        auth0User = await _auth0.LoginAsync(Forms.Context, withRefreshToken: true, scope: AppConstants.Auth0.Scope);
		    }
		    catch (TaskCanceledException)
		    {
		        Debug.WriteLine("User cancelled out of login, going back to main page.");
		    }

		    if (auth0User == null)
		        return null;

		    var properties = auth0User.Profile.ToObject<Dictionary<string, object>>()		        
		        .Where(v => v.Value is string && !string.IsNullOrWhiteSpace(v.Value.ToString()))
		        .ToDictionary(v => v.Key, v => v.Value.ToString());
            
		    return new UserAccount
		    {
		        Username = properties.GetValueOrDefault(AppConstants.Auth0.ProfileEmailKey),
		        Properties = new Dictionary<string, string>
		        {
		            { AppConstants.UserAccountKeys.UserIdKey, properties.GetValueOrDefault(AppConstants.Auth0.ProfileIdKey) },
		            { AppConstants.UserAccountKeys.DisplayNameKey, properties.GetValueOrDefault(AppConstants.Auth0.ProfileNameKey) },
		            { AppConstants.UserAccountKeys.ProfilePictureKey, properties.GetValueOrDefault(AppConstants.Auth0.ProfilePictureKey) }
		        }
            };
        }        
	}
}

[assembly: Dependency(typeof(Auth0SocialLoginManager))]
namespace YourApp.iOS.Services
{
    public class Auth0SocialLoginManager : ISocialLoginManager
    {
        private readonly Auth0Client _auth0 = new Auth0Client(AppConstants.Auth0.Domain, AppConstants.Auth0.ClientId);
        private readonly AccountStore _accountStore = AccountStore.Create();

        public async Task<UserAccount> GetUser()
		{
		    Auth0User auth0User = null;
			var window = UIApplication.SharedApplication.KeyWindow;
			var vc = window.RootViewController;
			while (vc.PresentedViewController != null)
			{
				vc = vc.PresentedViewController;
			}

		    try
		    {
		        auth0User = await _auth0.LoginAsync(vc, withRefreshToken: true, scope: AppConstants.Auth0.Scope);
		    }
		    catch (TaskCanceledException)
		    {
		        Debug.WriteLine("User cancelled out of login, going back to main page.");
		    }

            if (auth0User == null)
		        return null;

		    var properties = auth0User.Profile.ToObject<Dictionary<string, object>>()
		        .Where(v => v.Value is string && !string.IsNullOrWhiteSpace(v.Value.ToString()))
		        .ToDictionary(v => v.Key, v => v.Value.ToString());

		    return new UserAccount
		    {
		        Username = properties.GetValueOrDefault(AppConstants.Auth0.ProfileEmailKey),
		        Properties = new Dictionary<string, string>
		        {
		            { AppConstants.UserAccountKeys.UserIdKey, properties.GetValueOrDefault(AppConstants.Auth0.ProfileIdKey) },
		            { AppConstants.UserAccountKeys.DisplayNameKey, properties.GetValueOrDefault(AppConstants.Auth0.ProfileNameKey) },
		            { AppConstants.UserAccountKeys.ProfilePictureKey, properties.GetValueOrDefault(AppConstants.Auth0.ProfilePictureKey) }
		        }
		    };
        }        
	}
}

[assembly: Dependency(typeof(Auth0SocialLoginManager))]
namespace YourApp.UWP.Services
{
    public class Auth0SocialLoginManager : ISocialLoginManager
    {
        private readonly Auth0Client _auth0 = new Auth0Client(AppConstants.Auth0.Domain, AppConstants.Auth0.ClientId);
        
        public async Task<UserAccount> GetUser()
        {
            Auth0User auth0User = null;
            try
            {
                auth0User = await _auth0.LoginAsync(withRefreshToken: true, scope: AppConstants.Auth0.Scope);
            }
            catch (TaskCanceledException)
            {
                Debug.WriteLine("User cancelled out of login, going back to main page.");
            }
            catch (AuthenticationCanceledException)
            {
                Debug.WriteLine("User cancelled out of login, going back to main page.");
            }
            catch (Exception e)
            {
                Debug.WriteLine("Failed to launch...");
                throw e;
            }

            if (auth0User == null)
                return null;

            var properties = auth0User.Profile.ToObject<Dictionary<string, object>>()
                .Where(v => v.Value is string && !string.IsNullOrWhiteSpace(v.Value.ToString()))
                .ToDictionary(v => v.Key, v => v.Value.ToString());

            return new UserAccount
            {
                Username = properties.GetValueOrDefault(AppConstants.Auth0.ProfileEmailKey),
                Properties = new Dictionary<string, string>
                {
                    { AppConstants.UserAccountKeys.UserIdKey, properties.GetValueOrDefault(AppConstants.Auth0.ProfileIdKey) },
                    { AppConstants.UserAccountKeys.DisplayNameKey, properties.GetValueOrDefault(AppConstants.Auth0.ProfileNameKey) },
                    { AppConstants.UserAccountKeys.ProfilePictureKey, properties.GetValueOrDefault(AppConstants.Auth0.ProfilePictureKey) }
                }
            };
        }        
    }
}

Thanks! Are you using using Auth0.OidcClient? LoginAsync returns a LoginResult when using Auth0.OidcClient, not an Auth0User object.

Does this still work? When I run this on Android, I get System.NullReference exception at the point where the Auth0Client is instanced. Seems to need an Activity? I’m using: Auth0Client _auth0Client = new Auth0Client(new Auth0ClientOptions { Domain = AppConstants.Auth0Domain, ClientId = AppConstants.Auth0ClientId});