Authenticate the .NET MAUI App with Azure AD

Jollen Moyani - Dec 15 '22 - - Dev Community

Building desktop, mobile, and web applications with one code base is finally possible! With .NET MAUI, you can build your native UI in .NET with XAML and C#, and then run that same single code base on all these target platforms:

  • Windows using WinUI
  • macOS with Mac Catalyst apps
  • iOS and Android apps on phones

In this blog, we will see how to create a .NET MAUI application that authenticates users using Azure Active Directory on Windows and Android platforms. Authentication is the process of identifying users who request access to a system. This often determines user identity according to their credentials. Authentication keeps unauthorized users from accessing sensitive information, thus blocking cyber criminals on unsecured systems from accessing and stealing information.

To authenticate a .NET MAUI application using Azure AD:

Register the application in Azure AD

First, register the Web API in your Azure Active Directory tenant and add a scope by following these steps:

  1. Sign in to the Azure portal.
  2. If you have access to multiple tenants, use the Directories + subscriptions filter in the top menu to switch to the tenant where you want to register the application.
  3. Search for and select Azure Active Directory.
  4. Under Manage, select App registrations -> New registration.
    • Name : Enter a name for your application. For example, MyMauiApp. Users of your app will see this name. You can change it later.
    • Supported account types : Accounts in any organizational directory (any Azure AD directory—multitenant) and personal Microsoft accounts (e.g., Skype, Xbox).
  5. Select Register.
  6. Under Authentication, provide the redirection URI.
  7. Select Overview.

Overview of the app registration

Overview of the app registration

  1. Note the Application (client) ID in the Essentials section, as you’ll need this value to configure the backend service later. This will be referred to as the Web API Application ID.

Create a .NET MAUI Program

  1. Create a new .NET MAUI project referring to the MS documentation, Build your first app. Here, I am going to name the project MauiAuthApp.
  2. Install the Microsoft.Identity.Client , System.IdentityModel.Tokens.Jwt , and CommunityToolkit.Maui NuGet packages in the project. Install the Microsoft.Identity.Client NuGet packageThe Microsoft.Identity.Client package is used in the following scenarios:

Install System.IdentityModel.Tokens.Jwt NuGet packageThe System.IdentityModel.Tokens.Jws package is required for the security token designed for representing a JSON web token (JWT).

Install CommunityToolkit.Maui NuGet package

The CommunityToolkit.Maui package is used to display the authentication message in a toast.

Create a class named Constants to assign the client ID and the scope values. Refer to the following code.

namespace MauiAuthApp;

public static class Constants
{
    //The Application or Client ID will be generated while registering the app in the Azure portal. Copy and paste the GUID.
    public static readonly string ClientId = "3bf5e165-a671-44e9-a412-22f13c737078";

    //Leaving the scope to its default values.
    public static readonly string[] Scopes = new string[] { "openid", "offline_access" };
}
Enter fullscreen mode Exit fullscreen mode

Application or Client ID of the registered app

Application or Client ID of the registered app

  1. Modify the manifest files with the following code. For Android, open AndroidManifest.xml.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <application android:allowBackup="true" android:icon="@mipmap/appicon" android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true">

      <activity android:name="microsoft.identity.client.BrowserTabActivity" android:exported="true">
         <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="msal35610457-7107-4d3d-a3d9-f1f7ffaaf904" android:host="auth" />
         </intent-filter>
       </activity>

    </application>

    <queries>
      <package android:name="com.azure.authenticator" />
      <package android:name="com.companyname.mauiauthapp" /> <!-- This value should be copied from the MauiAuthApp.csproj file -->
      <package android:name="com.microsoft.windowsintune.companyportal" />
    </queries>

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
</manifest>
Enter fullscreen mode Exit fullscreen mode

Note: android:scheme starts with msal and continues with the client ID from the app registration at the Azure portal. Also, the application ID is used in the MAUI app’s project file. For example, refer to the screenshot of the MauiAuthApp.csproj file. Application ID in the MauiAuthApp.csproj file

  1. You need to override some methods to receive a callback from the identity server. For Android, open Android/MainActivity.cs and override the OnActivityResult method.
using Android.App;
using Android.Content;
using Android.Content.PM;
using Microsoft.Identity.Client;

namespace MauiAuthApp;

[Activity(Theme = "@style/Maui.SplashTheme", Exported = true, MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)]

public class MainActivity : MauiAppCompatActivity
{
    protected override void OnActivityResult(int requestCode, Result resultCode, Intent? data)
    {
        base.OnActivityResult(requestCode, resultCode, data);
        AuthenticationContinuationHelper.SetAuthenticationContinuationEventArgs(requestCode, resultCode, data);
    }
}
Enter fullscreen mode Exit fullscreen mode

You also need to set the activity attribute Exported = true.

  1. Next, create the AuthService class. Refer to the following code.
using Microsoft.Identity.Client;

namespace MauiAuthApp;

public class AuthService
{
    private readonly IPublicClientApplication authenticationClient;

    // Providing the RedirectionUri to receive the token based on success or failure.
    public AuthService()
    {
        authenticationClient = PublicClientApplicationBuilder.Create(Constants.ClientId)
            .WithRedirectUri($"msal{Constants.ClientId}://auth")
            .Build();
    }

    // Propagates notification that the operation should be cancelled.
    public async Task<AuthenticationResult> LoginAsync(CancellationToken cancellationToken)
    {
        AuthenticationResult result;
        try
        {
            result = await authenticationClient
                .AcquireTokenInteractive(Constants.Scopes)
                .WithPrompt(Prompt.ForceLogin) //This is optional. If provided, on each execution, the username and the password must be entered.
                .ExecuteAsync(cancellationToken);
            return result;
        }
        catch (MsalClientException)
        {
            return null;
        }
    }
}
Enter fullscreen mode Exit fullscreen mode
  1. Prepare the UI to use the AuthService. Add a login button to the MainPage.xaml. ** The following code is the default code in the **MainPage.xaml , where the label and the button elements are modified. Here, a Login button is added to perform the authentication.
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MauiAuthApp.MainPage">

    <ScrollView>
        <VerticalStackLayout
            Spacing="25"
            Padding="30,0"
            VerticalOptions="Center">

            <Image
                Source="dotnet_bot.png"
                SemanticProperties.Description="Cute dot net bot waving hi to you!"
                HeightRequest="200"
                HorizontalOptions="Center" />

            <Label
                Text="Hello, Everyone!"
                SemanticProperties.HeadingLevel="Level1"
                FontSize="32"
                HorizontalOptions="Center" />

            <Label
                Text="Authenticate .Net MAUI app with Azure Active Directory!"
                SemanticProperties.HeadingLevel="Level2"
                SemanticProperties.Description="Welcome to dot net Multi platform App UI"
                FontSize="18"
                HorizontalOptions="Center" />

            <Button
                Text="Login"
                SemanticProperties.Hint="Login"
                Clicked="OnLoginClicked"
                HorizontalOptions="Center" />

        </VerticalStackLayout>
    </ScrollView>

</ContentPage>
Enter fullscreen mode Exit fullscreen mode
  1. Add the click event handler in the MainPage.xaml.cs file. Use the following code to complete the application creation.
using CommunityToolkit.Maui.Alerts;
using Microsoft.Identity.Client;
using System.IdentityModel.Tokens.Jwt;
using System.Text;

namespace MauiAuthApp;

public partial class MainPage : ContentPage
{
    int count = 0;

    public MainPage()
    {
        InitializeComponent();
    }

    private async void OnLoginClicked(object sender, EventArgs e)
    {
          try
          {
            var authService = new AuthService();
            var result = await authService.LoginAsync(CancellationToken.None);
            var token = result?.IdToken; // AccessToken also can be used
            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}");
                    await Toast.Make(stringBuilder.ToString()).Show();
                }
            }
        }
        catch (MsalClientException ex)
        {
            await Toast.Make(ex.Message).Show();
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

We have completed implementing the application! Let’s run the application to see the result.

Following is the output of the application we created. The application runs and asks for authentication details. If authenticated, you will receive the toast message that we returned. Here, we have used the Name and Email address of the user to confirm the authentication.

Authenticating a .NET MAUI App with Azure AD

Authenticating a .NET MAUI App with Azure AD

GitHub

You can download the complete sample to authenticate .NET MAUI apps with Azure AD.

Conclusion

I hope you enjoyed reading this blog. This article explained the procedure to authenticate a .NET MAUI application using Azure Active Directory on Windows and Android platforms.

Syncfusion’s .NET MAUI controls were built from scratch using .NET MAUI, so they feel like framework controls. They are fine-tuned to work with a huge volume of data. Use them to build better cross-platform mobile and desktop apps!

For current customers, the new Essential Studio version is available for download from the License and Downloads page. If you are not yet a Syncfusion customer, you can always download our free evaluation to see all our controls in action.

For questions, you can contact us through our support forum, support portal, or feedback portal. We are always happy to assist you!

Related blogs

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .