App desktop che chiama le API Web: acquisire un token usando WAM
Microsoft Authentication Library (MSAL) chiama Web Account Manager (WAM), un componente di Windows 10+ che funge da broker di autenticazione. Il broker consente agli utenti della tua app di trarre vantaggio dall'integrazione con gli account noti a Windows, ad esempio l'account che hai eseguito l'accesso alla sessione di Windows.
Proposta di valore WAM
L'uso di un broker di autenticazione come WAM offre numerosi vantaggi:
- Sicurezza avanzata. Vedere Protezione dei token.
- Supporto per le chiavi Windows Hello, Accesso condizionale e FIDO.
- Integrazione con la visualizzazione Posta elettronica e account di Windows.
- Accesso Single Sign-On rapido.
- Possibilità di accedere automaticamente con l'account di Windows corrente.
- Correzioni di bug e miglioramenti forniti con Windows.
Limitazioni di WAM
- WAM è disponibile in Windows 10 e versioni successive e in Windows Server 2019 e versioni successive. In Mac, Linux e versioni precedenti di Windows, MSAL esegue automaticamente il fallback a un browser.
- Le autorità di Azure Active Directory B2C (Azure AD B2C) e Active Directory Federation Services (AD FS) non sono supportate. MSAL esegue il fallback a un browser.
Pacchetto di integrazione WAM
La maggior parte delle app deve fare riferimento al Microsoft.Identity.Client.Broker
pacchetto per usare questa integrazione. Le app MAUI .NET non devono eseguire questa operazione, perché la funzionalità è all'interno di MSAL quando la destinazione è net6-windows
e versioni successive.
Modello di chiamata WAM
È possibile usare il modello seguente per 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
}
Se un broker non è presente (ad esempio, Windows 8.1, Mac o Linux), MSAL esegue il fallback a un browser, in cui si applicano le regole URI di reindirizzamento.
URI di reindirizzamento
Non è necessario configurare gli URI di reindirizzamento wam in MSAL, ma è necessario configurarli nella registrazione dell'app:
ms-appx-web://microsoft.aad.brokerplugin/{client_id}
Persistenza della cache dei token
È importante rendere persistente la cache dei token MSAL perché MSAL continua a archiviare i token ID e i metadati dell'account. Per altre informazioni, vedere Serializzazione della cache dei token in MSAL.NET.
Account per l'accesso invisibile all'utente
Per trovare un account per l'accesso invisibile all'utente, è consigliabile usare questo modello:
- Se l'utente ha eseguito l'accesso in precedenza, usare tale account. In caso contrario, usare
PublicClientApplication.OperatingSystemAccount
per l'account di Windows corrente. - Consentire all'utente di passare a un account diverso accedendo in modo interattivo.
Handle di finestra padre
È necessario configurare MSAL con la finestra a cui l'esperienza interattiva deve essere padre, usando WithParentActivityOrWindow
le API.
Applicazioni dell'interfaccia utente
Per app dell'interfaccia utente come Windows Form (WinForms), Windows Presentation Foundation (WPF) o Libreria dell'interfaccia utente di Windows versione 3 (WinUI3), vedi Recuperare un handle di finestra.
Applicazioni console
Per le applicazioni console, la configurazione è più interessata a causa della finestra del terminale e delle relative schede. Usare il codice seguente:
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;
}
Risoluzione dei problemi
Messaggio di errore "Selezione account WAM non ha restituito un account"
Il messaggio "Selezione account WAM non ha restituito un account" indica che l'utente dell'applicazione ha chiuso la finestra di dialogo che visualizza gli account o la finestra di dialogo stessa si è arrestata in modo anomalo. Un arresto anomalo potrebbe verificarsi se AccountsControl
, un controllo Windows, viene registrato in modo non corretto in Windows. Per risolvere questo problema:
Sulla barra delle applicazioni fare clic con il pulsante destro del mouse su Start e quindi scegliere Windows PowerShell (amministratore).
Se viene visualizzata una finestra di dialogo Controllo account utente, selezionare Sì per avviare PowerShell.
Copiare ed eseguire lo script seguente:
if (-not (Get-AppxPackage Microsoft.AccountsControl)) { Add-AppxPackage -Register "$env:windir\SystemApps\Microsoft.AccountsControl_cw5n1h2txyewy\AppxManifest.xml" -DisableDevelopmentMode -ForceApplicationShutdown } Get-AppxPackage Microsoft.AccountsControl
Messaggio di errore "MsalClientException: ErrorCode: wam_runtime_init_failed" durante una distribuzione di un singolo file
È possibile che venga visualizzato l'errore seguente durante la creazione del pacchetto dell'applicazione in un singolo bundle di file:
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
Questo errore indica che i file binari nativi di Microsoft.Identity.Client.NativeInterop non sono stati inseriti nel pacchetto di file singolo. Per incorporare tali file per l'estrazione e ottenere un file di output, impostare la proprietà IncludeNativeLibrariesForSelfExtract
su true
. Altre informazioni su come creare un pacchetto di file binari nativi in un singolo file.
Problemi di connessione
Se l'utente dell'applicazione visualizza regolarmente un messaggio di errore simile a "Controllare la connessione e riprovare", vedere la guida alla risoluzione dei problemi per Office. Questa guida alla risoluzione dei problemi usa anche il broker.
Esempio
È possibile trovare un esempio WPF che usa WAM in GitHub.
Passaggi successivi
Passare all'articolo successivo in questo scenario, Chiamare una API Web dall'applicazione desktop.