📄 src/Auth/AuthService.cs
using Android.Content;
using Microsoft.Identity.Client;

namespace NotesApp.Auth;

public static class AuthService
{
    private static readonly string[] Scopes = ["Files.ReadWrite", "User.Read"];

    private static IPublicClientApplication? _pca;

    private static IPublicClientApplication GetOrCreatePca()
    {
        if (_pca != null)
            return _pca;

        var context = Application.Context;
        var clientId = context.GetString(Resource.String.msal_client_id);

        _pca = PublicClientApplicationBuilder
            .Create(clientId)
            .WithAuthority(
                AzureCloudInstance.AzurePublic,
                AadAuthorityAudience.PersonalMicrosoftAccount
            )
            .WithRedirectUri($"msal{clientId}://auth")
            .Build();

        return _pca;
    }

    public static async Task<AuthenticationResult> GetAccessTokenAsync(Activity activity)
    {
        var pca = GetOrCreatePca();
        var accounts = await pca.GetAccountsAsync();
        var account = accounts.FirstOrDefault();

        if (account != null)
        {
            try
            {
                return await pca.AcquireTokenSilent(Scopes, account).ExecuteAsync();
            }
            catch (MsalUiRequiredException)
            {
                // Falls through to interactive sign-in below.
            }
        }

        return await pca.AcquireTokenInteractive(Scopes)
            .WithParentActivityOrWindow(activity)
            .ExecuteAsync();
    }

    public static async Task<bool> IsSignedInAsync()
    {
        var accounts = await GetOrCreatePca().GetAccountsAsync();
        return accounts.Any();
    }

    public static void HandleActivityResult(int requestCode, Result resultCode, Intent? data) =>
        AuthenticationContinuationHelper.SetAuthenticationContinuationEventArgs(
            requestCode,
            resultCode,
            data
        );
}