Application de bureau appelant des API web : acquérir un jeton en utilisant un WAM

La bibliothèque d’authentification Microsoft (MSAL) appelle un WAM, un composant Windows 10+ qui agit en tant que répartiteur d’authentification. Le répartiteur permet aux utilisateurs de votre application de bénéficier de l’intégration avec les comptes connus de Windows, tels que le compte que vous avez connecté à votre session Windows.

Proposition de valeur du gestionnaire de comptes web

L’utilisation d’un répartiteur d’authentification tel qu’un WAM présente de nombreux avantages :

  • Sécurité renforcée. Consultez Protection des jetons.
  • Prise en charge de Windows Hello, de l’accès conditionnel et des clés FIDO.
  • Intégration avec l’affichage Comptes et e-mail de Windows.
  • Authentification unique rapide.
  • Possibilité de se connecter en mode silencieux avec le compte Windows actuel.
  • Des correctifs de bogues et d’autres améliorations sont fournis avec Windows.

Limitations du gestionnaire de comptes web

  • Un WAM est disponible sur Windows 10 et versions ultérieures et sur Windows Server 2019 et versions ultérieures. Sur Mac, Linux et des versions antérieures de Windows, le WAM revient automatiquement au navigateur.
  • Les autorités Azure Active Directory B2C (Azure AD B2C) et Services ADFS (AD FS) ne sont pas prises en charge. Le WAM revient au navigateur.

Package d’intégration WAM

La plupart des applications doivent référencer le package Microsoft.Identity.Client.Broker pour utiliser cette intégration. Les applications .NET MAUI n’ont pas besoin de le faire, car la fonctionnalité se trouve à l’intérieur du Gestionnaire de comptes web lorsque la cible est net6-windows et versions ultérieures.

Modèle d’appel de gestionnaire de comptes web

Vous pouvez utiliser le modèle suivant pour utiliser un WAM :

    // 1. Configuration - read below about redirect URI
    var pca = PublicClientApplicationBuilder.Create("client_id")
                    .WithBroker(new BrokerOptions(BrokerOptions.OperatingSystems.Windows))
                    .Build();

    // Add a token cache; see https://learn.microsoft.com/azure/active-directory/develop/msal-net-token-cache-serialization?tabs=desktop

    // 2. Find an account for silent login

    // Is there an account in the cache?
    IAccount accountToLogin = (await pca.GetAccountsAsync()).FirstOrDefault();
    if (accountToLogin == null)
    {
        // 3. No account in the cache; try to log in with the OS account
        accountToLogin = PublicClientApplication.OperatingSystemAccount;
    }

    try
    {
        // 4. Silent authentication 
        var authResult = await pca.AcquireTokenSilent(new[] { "User.Read" }, accountToLogin)
                                    .ExecuteAsync();
    }
    // Cannot log in silently - most likely Azure AD would show a consent dialog or the user needs to re-enter credentials
    catch (MsalUiRequiredException) 
    {
        // 5. Interactive authentication
        var authResult = await pca.AcquireTokenInteractive(new[] { "User.Read" })
                                    .WithAccount(accountToLogin)
                                    // This is mandatory so that WAM is correctly parented to your app; read on for more guidance
                                    .WithParentActivityOrWindow(myWindowHandle) 
                                    .ExecuteAsync();
                                    
        // Consider allowing the user to re-authenticate with a different account, by calling AcquireTokenInteractive again                                  
    }

En l’absence de répartiteur (par exemple Win8.8.1, Mac ou Linux), le WAM revient au navigateur, où s’appliquent les règles d’URI de redirection.

URI de redirection

Vous n’avez pas besoin de configurer des URI de redirection des URI dans un WAM, mais vous devez les configurer dans l’inscription de l’application :

ms-appx-web://microsoft.aad.brokerplugin/{client_id}

Persistance du cache de jetons

Il est important de conserver le cache de jetons du Gestionnaire de compte web, car ce dernier continue à y stocker des jetons d’ID et des métadonnées de compte. Pour plus d’informations, consultez Sérialisation du cache de jetons dans MSAL.NET.

Comptes pour une connexion en mode silencieux

Pour trouver un compte pour la connexion en mode silencieux, nous vous recommandons ce modèle :

  • Si l’utilisateur s’est précédemment connecté, utilisez ce compte. Sinon, utilisezPublicClientApplication.OperatingSystemAccount pour le compte Windows actuel.
  • Autorisez l’utilisateur à passer à un autre compte en se connectant de manière interactive.

Handles de fenêtre parente

Vous devez configurer un WAM avec la fenêtre à laquelle l’expérience interactive doit être apparentée en utilisant l’API WithParentActivityOrWindow.

Applications d’interface utilisateur

Pour des applications d’interface utilisateur telles que Windows Forms (WinForms), Windows Presentation Foundation (WPF) ou Bibliothèque d’interface utilisateur Windows version 3 (WinUI3), consultez Récupérer un handle de fenêtre.

Applications console

Pour des applications console, la configuration est un peu plus impliquée en raison de la fenêtre de terminal et de ses onglets. Utilisez le code suivant :

enum GetAncestorFlags
{   
    GetParent = 1,
    GetRoot = 2,
    /// <summary>
    /// Retrieves the owned root window by walking the chain of parent and owner windows returned by GetParent.
    /// </summary>
    GetRootOwner = 3
}

/// <summary>
/// Retrieves the handle to the ancestor of the specified window.
/// </summary>
/// <param name="hwnd">A handle to the window whose ancestor will be retrieved.
/// If this parameter is the desktop window, the function returns NULL. </param>
/// <param name="flags">The ancestor to be retrieved.</param>
/// <returns>The return value is the handle to the ancestor window.</returns>
[DllImport("user32.dll", ExactSpelling = true)]
static extern IntPtr GetAncestor(IntPtr hwnd, GetAncestorFlags flags);

[DllImport("kernel32.dll")]
static extern IntPtr GetConsoleWindow();

// This is your window handle!
public IntPtr GetConsoleOrTerminalWindow()
{
   IntPtr consoleHandle = GetConsoleWindow();
   IntPtr handle = GetAncestor(consoleHandle, GetAncestorFlags.GetRootOwner );
  
   return handle;
}

Résolution des problèmes

Message d’erreur « Le sélecteur de compte WAM n’a pas renvoyé de compte »

Le message « Le sélecteur de compte WAM n’a pas renvoyé de compte » indique que l’utilisateur de l’application a fermé la boîte de dialogue qui affiche des comptes ou que la boîte de dialogue elle-même s’est bloquée. Un blocage peut se produire si AccountsControl, un contrôle Windows, est inscrit de manière incorrecte dans Windows. Pour résoudre ce problème :

  1. Sur la barre des tâches, cliquez avec le bouton droit sur Démarrer, puis sélectionnez Windows PowerShell (Admin).

  2. Si vous y êtes invité par un dialogue de Contrôle de compte d’utilisateur, sélectionnez Oui pour démarrer PowerShell.

  3. Copiez, puis exécutez le script suivant :

    if (-not (Get-AppxPackage Microsoft.AccountsControl)) { Add-AppxPackage -Register "$env:windir\SystemApps\Microsoft.AccountsControl_cw5n1h2txyewy\AppxManifest.xml" -DisableDevelopmentMode -ForceApplicationShutdown } Get-AppxPackage Microsoft.AccountsControl
    

Message d’erreur « MsalClientException : ErrorCode : wam_runtime_init_failed » lors du déploiement d’un fichier unique

Il est possible que l’erreur suivante s’affiche lors de l’empaquetage de votre application dans un seul ensemble de fichiers :

MsalClientException: wam_runtime_init_failed: The type initializer for 'Microsoft.Identity.Client.NativeInterop.API' threw an exception. See https://aka.ms/msal-net-wam#troubleshooting

Cette erreur indique que les fichiers binaires natifs de Microsoft.Identity.Client.NativeInterop n’ont pas été empaquetés dans l’ensemble de fichiers unique. Pour incorporer ces fichiers pour l’extraction et obtenir un fichier de sortie, définissez la propriété IncludeNativeLibrariesForSelfExtract sur true. Apprenez-en davantage sur la façon d’empaqueter des fichiers binaires natifs dans un seul fichier.

Problèmes de connexion

Si l’utilisateur de l’application voit régulièrement un message d’erreur semblable à « Veuillez vérifier votre connexion et réessayer », consultez le guide de résolution des problèmes pour Office. Ce guide de résolution des problèmes utilise également le répartiteur.

Exemple

Vous trouverez un exemple WPF qui utilise WAM sur GitHub.

Étapes suivantes

Passez à l’article suivant de ce scénario, Appeler une API web à partir de l’appareil de bureau.