I'm trying to get my feet wet with Xamarin and I'm having trouble adding in my organization's login. The screen shot below is as far as I can get attempting to login. When I click "Continue" the same page just loads again. Not really sure what's going on.
The image is the screen I'm stuck on.
I've added code that represents the app class and the code behind for the XAML page attempting to login, leaving out what I "think" is irrelvant.
Any suggestions?
App class...
public partial class App : Application
{
public static string AzureBackendUrl =
DeviceInfo.Platform == DevicePlatform.Android ? "http://10.0.2.2:5000" : "http://localhost:5000";
public static bool UseMockDataStore = true;
public static IPublicClientApplication PCA = null;
public static string ClientID = "CLIENT_ID";
public static string[] Scopes = { "User.Read" };
public static string Username = string.Empty;
public static object ParentWindow { get; set; }
public App()
{
InitializeComponent();
if (UseMockDataStore)
DependencyService.Register<MockDataStore>();
else
DependencyService.Register<AzureDataStore>();
PCA = PublicClientApplicationBuilder.Create(ClientID)
.WithRedirectUri($"msal{App.ClientID}://auth")
//.WithParentActivityOrWindow(() => App.ParentWindow)
.Build();
MainPage = new MSAL_Example();
}
}
MSAL_Example class...
public partial class MSAL_Example : ContentPage
{
public static string tenant_name = "MY_TENANT_NAME";
public MSAL_Example()
{
InitializeComponent();
App.ParentWindow = this;
}
public async Task SignOutAsync()
{
IEnumerable<IAccount> accounts = await App.PCA.GetAccountsAsync();
try
{
while (accounts.Any())
{
await App.PCA.RemoveAsync(accounts.FirstOrDefault());
accounts = await App.PCA.GetAccountsAsync();
}
slUser.IsVisible = false;
Device.BeginInvokeOnMainThread(() => { btnSignInSignOut.Text = "Sign in"; });
}
catch (Exception ex)
{
Debug.WriteLine("\tERROR {0}", ex.Message);
}
}
public async Task SignInAsync()
{
AuthenticationResult authResult = null;
IEnumerable<IAccount> accounts = await App.PCA.GetAccountsAsync();
// let's see if we have a user in our belly already
try
{
IAccount firstAccount = accounts.FirstOrDefault();
authResult = await App.PCA.AcquireTokenSilent(App.Scopes, firstAccount)
.ExecuteAsync();
await RefreshUserDataAsync(authResult.AccessToken).ConfigureAwait(false);
Device.BeginInvokeOnMainThread(() => { btnSignInSignOut.Text = "Sign out"; });
}
catch (MsalUiRequiredException ex)
{
try
{
authResult = await App.PCA.AcquireTokenInteractive(App.Scopes)
.WithParentActivityOrWindow(App.ParentWindow)
.WithAuthority("https://login.microsoftonline.com/" + tenant_name)
.ExecuteAsync();
await RefreshUserDataAsync(authResult.AccessToken);
Device.BeginInvokeOnMainThread(() => { btnSignInSignOut.Text = "Sign out"; });
}
catch (Exception ex2)
{
Debug.WriteLine("\tERROR {0}", ex2.Message);
}
}
}
public async Task RefreshUserDataAsync(string token)
{
//get data from API
HttpClient client = new HttpClient();
HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Get, "https://graph.microsoft.com/v1.0/me");
message.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("bearer", token);
HttpResponseMessage response = await client.SendAsync(message);
string responseString = await response.Content.ReadAsStringAsync();
if (response.IsSuccessStatusCode)
{
JObject user = JObject.Parse(responseString);
slUser.IsVisible = true;
Device.BeginInvokeOnMainThread(() =>
{
lblDisplayName.Text = user["displayName"].ToString();
lblGivenName.Text = user["givenName"].ToString();
lblId.Text = user["id"].ToString();
lblSurname.Text = user["surname"].ToString();
lblUserPrincipalName.Text = user["userPrincipalName"].ToString();
// just in case
btnSignInSignOut.Text = "Sign out";
});
}
else
{
await DisplayAlert("Something went wrong with the API call", responseString, "Dismiss");
}
}
}