Error Microsoft.WindowsAzure.MobileServices.Sync.MobileServicePushStatus.CancelledByAuthenticationError

Scott Thomson 56 Reputation points
2021-10-28T10:20:33.65+00:00

I have a xamarin.forms mobile app which is using MSAL to authenticate users via Azure Active Directory B2C (see git active-directory-b2c-xamarin-native.git). I am also using MobileServiceClient to use a sqlite store for offline sorage of user inputs. This is then synced back to Azure SQL Database. I have a "Mobile" or native client azure App Service. This Mobile App service has an identity provider register to it which is the B2C App associated with a B2C Tenant.

Prior to implementing B2C authentication the MobileServiceClient code was successfully synchronising data from the mobile back to the azure sql db. Once I implemented B2C (which was successfully allowing a user to sign up and sign in) I began to encounter an error when trying to synchronise with the Azure SQL Db.

The error occurrs on PushAsync line and only info I can extract currently is "Microsoft.WindowsAzure.MobileServices.Sync.MobileServicePushStatus.CancelledByAuthenticationError"

Search the web I found one article that sounds exactly like my problem. They said it was solved by putting a value into the B2C identity provider " allowed token audiences". I have tried several different entries but nothing helps.

As the error mentions authentication I have been assuming its something wrong with my azure App service or B2C configuration and because the syncing of tables and my Azure SQL Db previously worked without this MSAL authentication method (previously set it up with easy auth method). I must admit I have changed Azure settings so many times I am getting lost. The samples for native clients isnt detailed enough for my level of azure knowledge (novice).

I am also unsure whether the using MobileServiceClient with the MSAL B2C authentication is maybe not doable. I can't see any exchange of ID token etc occurring when executing PushAsync call back to the Mobil App service. I am not sure whether my mobile app code needs to pass back the authentication result as I believe occurs in a web API doing RESTful updates of database. Perhaps I'm using two incompatible strategies? eg I have to use a RESTful API or Azure function to update the database in conjunction with B2C auth rather than MobileServiceSyncContext tasks?

Appreciate any suggestions as to whats wrong or what to try to change or setup samples I could look at for Azure App services/B2C for xamarin.forms mobile app.

I posted below the manifest of the B2C App.

{ "id": "?????????f-26ea-4110-??????????198e4d", "acceptMappedClaims": null, "accessTokenAcceptedVersion": 2, "addIns": [], "allowPublicClient": true, "appId": "???????????-a307-4009-9582-?????????", "appRoles": [], "oauth2AllowUrlPathMatching": false, "createdDateTime": "2021-10-24T07:02:13Z", "certification": null, "disabledByMicrosoftStatus": null, "groupMembershipClaims": null, "identifierUris": [ "https://????????.onmicrosoft.com/????????" ], "informationalUrls": { "termsOfService": null, "support": null, "privacy": null, "marketing": null }, "keyCredentials": [], "knownClientApplications": [], "logoUrl": null, "logoutUrl": null, "name": "????????B2CApp", "oauth2AllowIdTokenImplicitFlow": false, "oauth2AllowImplicitFlow": false, "oauth2Permissions": [], "oauth2RequirePostResponse": false, "optionalClaims": null, "orgRestrictions": [], "parentalControlSettings": { "countriesBlockedForMinors": [], "legalAgeGroupRule": "Allow" }, "passwordCredentials": [], "preAuthorizedApplications": [], "publisherDomain": "?????????????.onmicrosoft.com", "replyUrlsWithType": [ { "url": "msal??????????-a307-????-9582-e70ab0b2600d://auth", "type": "InstalledClient" }, { "url": "https://??????.b2clogin.com/oauth2/nativeclient", "type": "InstalledClient" } ], "requiredResourceAccess": [ { "resourceAppId": "??????-0f1b-48f7-badc-1ba6abab6d66", "resourceAccess": [ { "id": "?????-04ce-46dc-8b5f-e9a5c60f0fc9", "type": "Scope" } ] }, { "resourceAppId": "?????-a6b6-4736-8310-5855508787cd", "resourceAccess": [ { "id": "??????-d128-49dc-ac08-2bf18f7874d8", "type": "Scope" } ] }, { "resourceAppId": "00000003-0000-0000-c000-000000000000", "resourceAccess": [ { "id": "?????-???-4136-accd-4a02d197296e", "type": "Scope" }, { "id": "????????-2fba-42fe-b0c0-848c9e6a8182", "type": "Scope" } ] } ], "samlMetadataUrl": null, "signInUrl": null, "signInAudience": "AzureADandPersonalMicrosoftAccount", "tags": [ "notApiConsumer", "mobileApp" ], "tokenEncryptionKeyId": null }

Here is the code for sync tables. Error occurs at await mClient.SyncContext.PushAsync().ConfigureAwait(false);

private MobileServiceClient mClient;
                private IMobileServiceSyncTable<UserSurvey> UserSurveyTable;
                private MobileServiceSQLiteStore mStore;

            public async Task InitializeAsync()
            {
                using (await initializationLock.LockAsync())
                {

                        if (!isInitialized)
                        {
                            mClient = new MobileServiceClient(Constants.BackendUrl); //, new LoggingHandler()

                        // Define the offline store.
                        mStore = new MobileServiceSQLiteStore("greenlightmobile3.db");
                            mStore.DefineTable<UserSurvey>();
                            await mClient.SyncContext.InitializeAsync(mStore).ConfigureAwait(false);
                            UserSurveyTable = mClient.GetSyncTable<UserSurvey>();
                            isInitialized = true;
                        }
}
}


                           public async Task SynchronizeAsync()
            {
            await InitializeAsync().ConfigureAwait(false);
IReadOnlyCollection<MobileServiceTableOperationError> syncErrors = null;
                try
                {
                    await mClient.SyncContext.PushAsync().ConfigureAwait(false);
                    await UserSurveyTable.PullAsync("usersurveys", UserSurveyTable.CreateQuery()).ConfigureAwait(false);
                }
                catch (MobileServicePushFailedException error)
                {
                    if (error.PushResult != null)
                    {
                        syncErrors = error.PushResult.Errors;
                    }
                }
 if (syncErrors != null)
            {
                foreach (var syncError in syncErrors)
                {
                    if (syncError.OperationKind == MobileServiceTableOperationKind.Update && syncError.Result != null)
                    {
                        // Prefer server copy
                        await syncError.CancelAndUpdateItemAsync(syncError.Result).ConfigureAwait(false);
                    }
                    else
                    {
                        // Discard local copy
                        await syncError.CancelAndDiscardItemAsync().ConfigureAwait(false);
                    }
                }
            }
Not Monitored
Not Monitored
Tag not monitored by Microsoft.
36,251 questions
{count} votes

1 answer

Sort by: Most helpful
  1. Scott Thomson 56 Reputation points
    2021-10-29T09:01:43.21+00:00

    I have done more reading and I think I will abandon using an App Service and instead change to RESTful API probably Azure Function. Seems like App service isnt the recommended strategy (mind you Microsofts strategy seems to change as often as their latest library!)

    Scott