cvanbeek
cvanbeek

Reputation: 1961

Xamarin Microsoft.Identity.Client AuthenticationResult AccessToken is null

I'm creating a Xamarin.Forms PCL application that uses Azure B2C to authenticate users. I was previously using Microsoft.Identity.Client version 1.0.304142221-alpha but I just updated to 1.1.0-preview after it came out on NuGet.

I'm also using the Azure MobileServiceClient to login users so only authenticated users can make calls to my tables.

I am able to successfully authenticate, which I set up like this sample on GitHub.

Using the previous version of Microsoft.Identity.Client, I was able to login to the MobileServiceClient like this:

AuthenticationResult ar = await App.AuthenticationClient.AcquireTokenAsync(Config.Scopes, 
         string.Empty, UiOptions.SelectAccount, string.Empty, null, 
         Config.Authority, Config.SignUpSignInpolicy);

JObject payload = getPayload(ar.IdToken);
payload["access_token"] = ar.Token;
string objectId = payload["oid"].ToString();

MobileServiceUser u = await App.MobileService.LoginAsync(MobileServiceAuthenticationProvider.WindowsAzureActiveDirectory,
                      payload);

However, after the update, AuthenticationResult no longer has a member named Token. Instead, it has AccessToken, which for me, is always returning null.

I have tried logging into the MobileServiceClient using the IdToken, but this produces an unauthorized error.

I think this problem could have something to with the scopes I define. Right now I have:

public static string[] Scopes = { "https://<MyTennant>/<MyAPIName>.read"};

Are there any scopes that I'm missing to get the AccessToken or is the problem somewhere else?

Update: Here are my settings in the Azure Portal For my API: My Azure B2C API Settings

For my Native Client: My Azure B2C Native Client Settings

In my App, I'm logging in like this:

AuthenticationResult ar = await App.AuthenticationClient.AcquireTokenAsync(Scopes, 
                     GetUserByPolicy(App.AuthenticationClient.Users, PolicySignUpSignIn),
                     App.UiParent);
payload = getPayload(ar.IdToken);
payload["access_token"] = ar.IdToken;

var mobileService = new Microsoft.WindowsAzure.MobileServices.MobileServiceClient("https://giftthis.azurewebsites.net/.auth/");
MobileServiceUser u = await mobileService.LoginAsync(MobileServiceAuthenticationProvider.WindowsAzureActiveDirectory, payload);

LoginAsync is now executing, but it returns null so I still can't make calls to the tables.

Upvotes: 0

Views: 1546

Answers (1)

Fei Xue
Fei Xue

Reputation: 14649

I am trying to test this issue using the Microsoft.Identity.Client version 1.1.0-preview, however it works well for me.

The mobile app was protected using Azure AD B2C app with Advanced mode and set the ALLOWED TOKEN AUDIENCES using the app id like figure below: enter image description here

After that I used the MobileServiceClient from Azure Mobile Client SDK. And to new the MobileServiceClient we only need to provide the mobile application URL as code below:

string applicationUrl = "https://mobilefei.azurewebsites.net/";
var mobileClient = new MobileServiceClient(applicationUrl);

However if I used the MobileServiceClient from Azure Mobile Services SDK , I can reproduce the same issue with 401 error. In this scenario, when we need append .auth to initialize the MobileServiceClient like code below:

string applicationUrl = "https://mobilefei.azurewebsites.net/.auth/";
var mobileClient = new MobileServiceClient(applicationUrl);

Update:

string CLIENT_ID = "420a3a24-97cf-46ca-a882-f6c047b0d845";
string[] SCOPES = { "https://xxx.onmicrosoft.com/b2cwebapp/read" };
string Tenant = "xxx.onmicrosoft.com";

string PolicySignUpSignIn = "B2C_1_Sign_In";
string AuthorityBase = $"https://login.microsoftonline.com/tfp/{Tenant}/";
string Authority = $"{AuthorityBase}{PolicySignUpSignIn}";


PublicClientApplication myApp = new PublicClientApplication(CLIENT_ID, Authority);

AuthenticationResult authenticationResult = myApp.AcquireTokenAsync(SCOPES).Result;

Console.WriteLine($"AccessToken:\n{authenticationResult.AccessToken}");

Console.WriteLine($"IdToken:\n{authenticationResult.IdToken}");

//This applicationUrl  works for WindowsAzure.MobileServices
//string applicationUrl = "https://mobilefei.azurewebsites.net/.auth/";

//This applicationUrl  works for Microsoft.Azure.Mobile.Client
string applicationUrl = "https://mobilefei.azurewebsites.net/";
var mobileClient = new MobileServiceClient(applicationUrl);

JObject token = new JObject();
token.Add("access_token", authenticationResult.IdToken);
var user = mobileClient.LoginAsync(MobileServiceAuthenticationProvider.WindowsAzureActiveDirectory, token).Result;
Console.WriteLine($"UserID:\n{user.UserId}");
Console.Read();

Upvotes: 1

Related Questions