I'm new to Xamarin and using the Office365 API. I'm attempting to learn through creating a Xamarin.Forms application that reads data from the Office365 server once the user is authenticated.
I've been following a tutorial and ended up with the following login page
namespace CMLender.Pages
{
public partial class Login
{
public IPlatformParameters PlatformParameters { get; set; }
public Login()
{
InitializeComponent();
LoginButton.Clicked += LoginButton_Clicked;
}
protected override void OnAppearing()
{
App.ClientApplication.PlatformParameters = PlatformParameters;
base.OnAppearing();
}
private async void LoginButton_Clicked(object sender, EventArgs e)
{
try
{
AuthenticationResult ar = await App.ClientApplication.AcquireTokenAsync(App.Scopes);
}
catch (MsalException ex)
{
WelcomeText.Text = ex.Message;
}
finally
{
await Navigation.PushAsync(new MainTab());
}
}
}
}
Once a user clicks on the login button they are taken through to the Office365 user authentication page. Once they have logged in with a valid username and password, the application then loads the MainTab XAML page.
Now this is where my problem starts. My MainTab page looks like this:
namespace CMLender.Pages
{
public partial class MainTab : ContentPage
{
public MainTab()
{
InitializeComponent();
DisplayMessage();
}
private async void DisplayMessage()
{
try
{
AuthenticationResult ar = await App.ClientApplication.AcquireTokenAsync(App.Scopes);
WelcomeText.Text = $"Welcome {ar.User.Name}";
}
catch (MsalException ex)
{
WelcomeText.Text = ex.Message;
}
finally
{
WelcomeTextTwo.Text = "BlaBlaBlab";
}
}
}
}
I wanted this page to write the logged in users name to a label (which it does) but first the user has to re-authenticate.
I'm pretty sure it's down to the AcquireTokenAsync task but it's the only way I can get it to work. How can I store the information that the user is already authenticated and access their user name?
I've done all the reading I can but the information just seems so far and wide on the subject.
For the most simplistic impllementation you can create a public static property in you App.cs or App.xaml.cs like :
public static AuthenticationResult LoggedInUser { get; set; }
In your login page add this to your login button click event :
private async void LoginButton_Clicked(object sender, EventArgs e)
{
try
{
AuthenticationResult ar = await App.ClientApplication.AcquireTokenAsync(App.Scopes);
App.LoggedInUser = ar;
}
catch (MsalException ex)
{
WelcomeText.Text = ex.Message;
}
finally
{
await Navigation.PushAsync(new MainTab());
}
}
And in you main page, get the data from the static property instead of calling the API again :
private async void DisplayMessage()
{
try
{
WelcomeText.Text = $"Welcome {App.LoggedInUser.User.Name}";
}
catch (MsalException ex)
{
WelcomeText.Text = ex.Message;
}
finally
{
WelcomeTextTwo.Text = "BlaBlaBlab";
}
}
Also, in your login method, It does not seem right to show the main page in finally because even if an exception occurs finally would get executed. I suggest you to move await Navigation.PushAsync(new MainTab());
to try
and show exception to user in catch
.