Forum Libraries, Components, and Plugins

Xamarin.Auth Authentication Issues.

I have run into issues the last couple of days trying to get the Xamarin.Auth library to work with my WebAPI and Active Directory. For the life of me, I can't get our API to work with Xamarin.Auth but I can log in through a browser and view our JSON data. I'm using Joe Suave's example as a starter.

Our URL structure is like this: https://####.azurewebsites.net/api/web*

The default URL in AD and the WebAPI: https://####.azurewebsites.net/

My reply URLs in AD are as follows:

https://####.azurewebsites.net/.auth/login/aad/callback

https://####.azurewebsites.net/api/webgreeks

Based upon the Joe Suave Example, I have set OAuthSettings as follows:

ClientId: "Assigned Web App Client ID in AD"
AuthorizeURL: "https://login.microsoftonline.com/[Our AD TenantID GUID]/oauth2/authorize"
Scope: string.Empty // Should this be our api/web* calls?
RedirectURL: [One of the above redirects]

These settings get me to the Microsoft Login Page. I log in and I'm given an error that either the data returned is forged or the Resource was not returned.
I'm unable to get the proper authentication data to return and call my api/web*.

Using the */aad/callback reply URL results in 'Expected access_token in response, but did not receive one.'

Using the */api/webgreeks reply URL results in 'Invalid state from server. Possible forgery!'

I tried to retrieve the actual AAD###### error but it disappears way too quickly. The app is being run in iPhone 6 10.2 simulator on an iMac. Are there any tools I can be running to capture the returned data better? Edit: I actually did retrieve it: AADSTS50001 Resource Identifier not provided. Could this be my answer?

Any ideas on what I might be doing wrong?

Answers

  • EnriqueRomeroEnriqueRomero USMember
    edited October 2018

    Hello,

    you must inherit and extend the xamarin.auth class with Resource parameter like this:

    namespace Xamarin.Auth
    {
    public class AuthenticatorExtensions : OAuth2Authenticator
    {

        private string _resource { get; set; }
    
        public AuthenticatorExtensions(
            string clientId,
            string scope,
            Uri authorizeUrl,
            Uri redirectUrl,
            string resource,
            GetUsernameAsyncFunc getUsernameAsync = null,
            bool isUsingNativeUI = false) :
            base(clientId, scope, authorizeUrl, redirectUrl, getUsernameAsync, isUsingNativeUI)
        {
            _resource = resource;
        }
    
        public AuthenticatorExtensions(string clientId, string clientSecret, string scope, Uri authorizeUrl, Uri redirectUrl, Uri accessTokenUrl,string resource, GetUsernameAsyncFunc getUsernameAsync = null, bool isUsingNativeUI = false) : base(clientId, clientSecret, scope, authorizeUrl, redirectUrl, accessTokenUrl, getUsernameAsync, isUsingNativeUI)
        {
            _resource = resource;
        }
    
    
        public override Task<Uri> GetInitialUrlAsync(Dictionary<string, string> custom_query_parameters = null)
        {
            if(custom_query_parameters == null)
                custom_query_parameters = new Dictionary<string, string>()
                {
                    {"resource", _resource }
                };
            else if (custom_query_parameters.ContainsKey("resource"))
                custom_query_parameters.Add("resource", _resource);
    
            return base.GetInitialUrlAsync(custom_query_parameters);
        }
    } 
    

    }_

  • Create a class and add this code below:

    using System;
    using Xamarin.Auth;
    
    namespace CRMInXamarin.Services
    {
        public class AuthenticatorExtensions : OAuth2Authenticator
        {
            public AuthenticatorExtensions(string clientId, string clientSecret, string scope, Uri authorizeUrl, Uri redirectUrl, Uri accessTokenUrl, GetUsernameAsyncFunc getUsernameAsync = null, bool isUsingNativeUI = false) : base(clientId, clientSecret, scope, authorizeUrl, redirectUrl, accessTokenUrl, getUsernameAsync, isUsingNativeUI)
            {
            }
            protected override void OnPageEncountered(Uri url, System.Collections.Generic.IDictionary<string, string> query, System.Collections.Generic.IDictionary<string, string> fragment)
            {
                // Remove state from dictionaries. 
                // We are ignoring request state forgery status 
                // as we're hitting an ASP.NET service which forwards 
                // to a third-party OAuth service itself
                if (query.ContainsKey("state"))
                {
                    query.Remove("state");
                }
    
                if (fragment.ContainsKey("state"))
                {
                    fragment.Remove("state");
                }
    
                base.OnPageEncountered(url, query, fragment);
            }
        }
    }
    

    Then use it as below:

            [Obsolete]
            private void SignInGoogleAuth()
            {
                try
                {
                    string clientId = null;
                    string redirectUri = null;
                    //Xamarin.Auth.CustomTabsConfiguration.CustomTabsClosingMessage = null;            
    
                    clientId = Constants.GoogleAndroidClientId;
                    redirectUri = Constants.GoogleAndroidRedirectUrl;
    
    
                    account = store.FindAccountsForService(Constants.AppName).FirstOrDefault();
    
                    var authenticator = new AuthenticatorExtensions(
                        clientId,
                        null,
                        Constants.GoogleScope,
                        new Uri(Constants.GoogleAuthorizeUrl),
                        new Uri(redirectUri),
                        new Uri(Constants.GoogleAccessTokenUrl),
                        null,
                        true);
    
                    authenticator.Completed += OnAuthCompleted;
                    authenticator.Error += OnAuthError;
    
                    AuthenticationState.Authenticator = authenticator;
    
                    var presenter = new Xamarin.Auth.Presenters.OAuthLoginPresenter();
                    presenter.Login(authenticator);
                }
                catch (Exception ex)
                {
                    ShowAlert("Alert", ex.Message);
                }
            }
    
            [Obsolete]
            async void OnAuthCompleted(object sender, AuthenticatorCompletedEventArgs e)
            {
                var authenticator = sender as OAuth2Authenticator;
                if (authenticator != null)
                {
                    authenticator.Completed -= OnAuthCompleted;
                    authenticator.Error -= OnAuthError;
                }
                if (e.IsAuthenticated)
                {
                        // If the user is authenticated, request their basic user data from Google
                        // UserInfoUrl = https://www.googleapis.com/oauth2/v2/userinfo
                        var request = new OAuth2Request("GET", new Uri(Constants.GoogleUserInfoUrl), null, e.Account);
                        var response = await request.GetResponseAsync();
                        if (response != null)
                        {
                            // Deserialize the data and store it in the account store
                            // The users email address will be used to identify data in SimpleDB
                            string userJson = await response.GetResponseTextAsync();
                            StaticVariables.googleProfile = JsonConvert.DeserializeObject<GoogleProfile>(userJson);
                        }
                        if (account != null)
                        {
                            store.Delete(account, Constants.AppName);
                        }
                        await store.SaveAsync(account = e.Account, Constants.AppName);
                        Application.Current.Properties.Remove("Id");
                        Application.Current.Properties.Remove("FirstName");
                        Application.Current.Properties.Remove("LastName");
                        Application.Current.Properties.Remove("DisplayName");
                        Application.Current.Properties.Remove("EmailAddress");
                        Application.Current.Properties.Remove("ProfilePicture");
    
                        Application.Current.Properties.Add("Id", StaticVariables.googleProfile.Id);
                        Application.Current.Properties.Add("FirstName", StaticVariables.googleProfile.GivenName);
                        Application.Current.Properties.Add("LastName", StaticVariables.googleProfile.FamilyName);
                        Application.Current.Properties.Add("DisplayName", StaticVariables.googleProfile.Name);
                        Application.Current.Properties.Add("EmailAddress", StaticVariables.googleProfile.Email);
                        Application.Current.Properties.Add("ProfilePicture", StaticVariables.googleProfile.Picture);
                        await Navigation.PushAsync(new GoogleProfilePage());
                }
            }
    
            [Obsolete]
            void OnAuthError(object sender, AuthenticatorErrorEventArgs e)
            {
                var authenticator = sender as OAuth2Authenticator;
                if (authenticator != null)
                {
                    authenticator.Completed -= OnAuthCompleted;
                    authenticator.Error -= OnAuthError;
                }
                Debug.WriteLine("Authentication error: " + e.Message);
            }
    
Sign In or Register to comment.