Azure Active Directory authentication in .NET MAUI

Azure Active Directory authentication in .NET MAUI

13 November 2021

MAUI/Xamarin

Share:

Hello!

Today we are going to create a small mobile application, which requires user authentication, using .NET MAUI.

I hope you already have a valid environment. Read this article on how to set up .NET MAUI.

So let's start!

  1. Create a new .NET MAUI project.
  2. Install Microsoft.Identity.Client and System.IdentityModel.Tokens.Jwt packages: Microsoft Identity Client Nuget
  3. Create Constants class:
public static class Constants
{
    public static readonly string ClientId = "Your client id guid";
    public static readonly string[] Scopes = new string[] { "openid", "offline_access" };
}
  1. Now we need to override some methods to receive a callback from the identity server.

For Android open Platforms/MainActivity.cs and override 2 methods OnCreate and OnActivityResult:

protected override void OnCreate(Bundle savedInstanceState)
{
    base.OnCreate(savedInstanceState);
    Microsoft.Maui.Essentials.Platform.Init(this, savedInstanceState); // this will allow us to get the current activity
}

protected override void OnActivityResult(int requestCode, Result resultCode, Intent? data)
{
    base.OnActivityResult(requestCode, resultCode, data);
    AuthenticationContinuationHelper.SetAuthenticationContinuationEventArgs(requestCode, resultCode, data);
}

Then open AndroidManifest.xml and add the next activity to the application:

<activity android:name="microsoft.identity.client.BrowserTabActivity">
	<intent-filter>
		<action android:name="android.intent.action.VIEW" />
		<category android:name="android.intent.category.DEFAULT" />
		<category android:name="android.intent.category.BROWSABLE" />
		<data android:scheme="msalYOUR_CLIENT_ID_HERE" android:host="auth" />
	</intent-filter>
</activity>

Pay attention that data android:scheme starts with msal.

For iOS open iOS/AppDelegate.cs and override OpenUrl method:

public override bool OpenUrl(UIApplication app, NSUrl url, NSDictionary options)
{
    AuthenticationContinuationHelper.SetAuthenticationContinuationEventArgs(url);
    return base.OpenUrl(app, url, options);
}
  1. It's time to create our AuthService:
public class AuthService
{
    private readonly IPublicClientApplication authenticationClient;
    public AuthService()
    {
        authenticationClient = PublicClientApplicationBuilder.Create(Constants.ClientId)
            .WithRedirectUri($"msal{Constants.ClientId}://auth")
            .Build();
    }

    public async Task<AuthenticationResult> LoginAsync(CancellationToken cancellationToken)
    {
        AuthenticationResult result;
        try
        {
            result = await authenticationClient
                .AcquireTokenInteractive(Constants.Scopes)
                .WithPrompt(Prompt.ForceLogin)
#if ANDROID
                .WithParentActivityOrWindow(Microsoft.Maui.Essentials.Platform.CurrentActivity)
#endif
                .ExecuteAsync(cancellationToken);
            return result;
        }
        catch (MsalClientException)
        {
            return null;
        }
    }
}
  1. Now we can prepare the UI to use our AuthService. Add login button to your XAML and add Clicked event handler:
var authService = new AuthService(); // most likely you will inject it in constructor, but for simplicity let's initialize it here
var result = await authService.LoginAsync(CancellationToken.None);
var token = result?.IdToken; // you can also get AccessToken if you need it
if (token != null)
{
	var handler = new JwtSecurityTokenHandler();
	var data = handler.ReadJwtToken(token);
	var claims = data.Claims.ToList();
	if (data != null)
	{
		var stringBuilder = new StringBuilder();
		stringBuilder.AppendLine($"Name: {data.Claims.FirstOrDefault(x => x.Type.Equals("name"))?.Value}");
		stringBuilder.AppendLine($"Email: {data.Claims.FirstOrDefault(x => x.Type.Equals("preferred_username"))?.Value}");
		LoginResultLabel.Text = stringBuilder.ToString();
	}
}

We are done. Now you can start the application and check the result. MAUI Auth

The full code can be found on GitHub.

Related:

Drawing View in Xamarin Community toolkit

Drawing View in Xamarin Community toolkit

The SignaturePad successor is now available in XCT. This article describes how to add it to your project

The first project with .NET MAUI

The first project with .NET MAUI

How to migrate Xamarin.Forms app to .NET MAUI step by step

An error has occurred. This application may no longer respond until reloaded. Reload 🗙