Quantcast
Channel: Recent Threads — Xamarin Community Forums
Viewing all articles
Browse latest Browse all 204402

Can't authenticate MobileServiceClient with Azure ASP.NET Backend

$
0
0

Ciao,
I have ASP.NET Web Application (.NET Framework) based on Visual Studio 2019 template with custom authentication with individual user accounts.

 public void ConfigureAuth(IAppBuilder app)
    {
                // Configure the db context and user manager to use a single instance per request
                app.CreatePerOwinContext(ApplicationDbContext.Create);
                app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);

                // Enable the application to use a cookie to store information for the signed in user
                // and to use a cookie to temporarily store information about a user logging in with a third party login provider
                app.UseCookieAuthentication(new CookieAuthenticationOptions());
                app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

                // Configure the application for OAuth based flow
                PublicClientId = "self";
                OAuthOptions = new OAuthAuthorizationServerOptions
                {
                    TokenEndpointPath = new PathString("/Token"),
                    Provider = new ApplicationOAuthProvider(PublicClientId),
                    AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
                    AccessTokenExpireTimeSpan = TimeSpan.FromDays(10),
                    // In production mode set AllowInsecureHttp = false
                    AllowInsecureHttp = false
                };

                // Enable the application to use bearer tokens to authenticate users
                app.UseOAuthBearerTokens(OAuthOptions);
    }

It works with Postman. I am able to obtain a token and access controller marked as [Authorize]

I am struggling with authentication of MobileServiceClient that I use for offline sync. Client is initialized in this way:

client = new MobileServiceClient(App.BackendUrl, new NativeMessageHandler());

     public async Task LoginAsync(string username, string password)
            {
                try
                {

                    var token = await GetAuthenticationToken(username, password);

                    MobileServiceUser user = new MobileServiceUser(token.userName);

                    user.MobileServiceAuthenticationToken = token.Access_Token;

                    client.CurrentUser = user;

                }
                catch (InvalidGrantException) 
                {
                    throw; 
                }
                catch (MobileServiceInvalidOperationException ex) 
                { 
                    throw; 
                }
                catch (Exception ex)
                {
                    Crashes.TrackError(ex);
                    Debug.WriteLine(ex);
                    throw;
                }
            }

        private async Task<AuthenticationToken> GetAuthenticationToken(string username, string password)
        {
            var keyValues = new List<KeyValuePair<string, string>>
            {
                new KeyValuePair<string, string>("username", username),
                new KeyValuePair<string, string>("password", password),
                new KeyValuePair<string, string>("grant_type", "password")
            };

            HttpContent httpContent = new FormUrlEncodedContent(keyValues);
            httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");

            try
            {

                var response = await client.InvokeApiAsync("/token",
                                        httpContent,
                                        HttpMethod.Post,
                                        null,
                                        null);

                return JsonConvert.DeserializeObject<AuthenticationToken>(await response.Content.ReadAsStringAsync());
            }
            catch (MobileServiceInvalidOperationException exception)
            {
                if (string.Equals(exception.Message, "invalid_grant"))
                    throw new InvalidGrantException("invalid credentials",  exception);
                else
                    throw;
            }
        } 

Here some code for testing:
public async Task InitializeAsync()
{
if (client?.SyncContext?.IsInitialized ?? false)
return;
// Create a reference to the local sqlite store
const string path = "syncstore.db";

            var store = new MobileServiceSQLiteStore(path);

            // Define the database schema
             store.DefineTable<Brand>(); brandTable = new AzureCloudTable<Brand>(client, null);

            // Actually create the store and update the schema
            try
            {
                await client.SyncContext.InitializeAsync(store);
            }
            catch (Exception ex)
            {
                Crashes.TrackError(ex);
                Debug.WriteLine(ex);
            }
        }

        async Task Test(string username, string password)
        {
            await LoginAsync("Simulator8", " ");
            await InitializeAsync();

            //Test pull
            try
            {
        await brandTable.PullAsync();
            }
            catch (Exception ex)
            {
            }
        }

Test throws exception:

  • ex {Microsoft.WindowsAzure.MobileServices.MobileServiceInvalidOperationException: The request could not be completed. (Unauthorized)
    at Microsoft.WindowsAzure.MobileServices.MobileServiceHttpClient.ThrowInvalidResponse (System.Net.Http.HttpRequestMessage request, System.Net.Http.HttpResponseMessage response) [0x001d2] in :0
    at Microsoft.WindowsAzure.MobileServices.MobileServiceHttpClient.SendRequestAsync (System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, System.Boolean ensureResponseContent, System.Threading.CancellationToken cancellationToken) [0x00121] in :0
    at Microsoft.WindowsAzure.MobileServices.MobileServiceHttpClient.RequestAsync (System.Boolean UseHandlers, System.Net.Http.HttpMethod method, System.String uriPathAndQuery, Microsoft.WindowsAzure.MobileServices.MobileServiceUser user, System.String content, System.Boolean ensureResponseContent, System.Collections.Generic.IDictionary2[TKey,TValue] requestHeaders, System.Threading.CancellationToken cancellationToken) [0x000f0] in <d385e67aff524dc7bd2d27425b9e81ae>:0 at Microsoft.WindowsAzure.MobileServices.MobileServiceTable.ReadAsync (System.String uriString, Microsoft.WindowsAzure.MobileServices.MobileServiceFeatures features) [0x0009c] in <d385e67aff524dc7bd2d27425b9e81ae>:0 at Microsoft.WindowsAzure.MobileServices.MobileServiceTable.ReadAsync (System.String query, System.Collections.Generic.IDictionary2[TKey,TValue] parameters, Microsoft.WindowsAzure.MobileServices.MobileServiceFeatures features) [0x00136] in :0
    at Microsoft.WindowsAzure.MobileServices.Sync.PullAction.ProcessTableAsync () [0x00134] in :0
    at Microsoft.WindowsAzure.MobileServices.Sync.TableAction.ExecuteAsync () [0x00251] in :0
    at Microsoft.WindowsAzure.MobileServices.Sync.MobileServiceSyncContext.ExecuteSyncAction (Microsoft.WindowsAzure.MobileServices.Sync.SyncAction action) [0x00090] in :0
    at Microsoft.WindowsAzure.MobileServices.Sync.MobileServiceSyncContext.PullAsync (System.String tableName, Microsoft.WindowsAzure.MobileServices.Sync.MobileServiceTableKind tableKind, System.String queryId, System.String query, Microsoft.WindowsAzure.MobileServices.MobileServiceRemoteTableOptions options, System.Collections.Generic.IDictionary2[TKey,TValue] parameters, System.Collections.Generic.IEnumerable1[T] relatedTables, Microsoft.WindowsAzure.MobileServices.MobileServiceObjectReader reader, System.Threading.CancellationToken cancellationToken, Microsoft.WindowsAzure.MobileServices.Sync.PullOptions pullOptions) [0x00361] in :0
  1. If I try token that I receive in token.Access_Token in Postman it works
  2. If I try sync with controller without [Authorize] it works.
  3. This is the message from Azure Log stream:

Username is correct. But if I don't call GetAuthenticationToken from LoginAsync and pass token manually to the user.MobileServiceAuthenticationToken then the result is:

So it seems that setting a user doesn't have any effect.

Any ideas why I can't authenticate my MobileServiceClient?


Viewing all articles
Browse latest Browse all 204402

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>