Gestionnaire de comptes web

Cet article explique comment utiliser AccountsSettingsPane pour connecter votre application plateforme Windows universelle (UWP) à des fournisseurs d’identité externes, tels que Microsoft ou Facebook, à l’aide des API du Gestionnaire de comptes web Windows 10 et Windows 11. Vous allez apprendre à demander l’autorisation d’un utilisateur d’utiliser son compte Microsoft, d’obtenir un jeton d’accès et de l’utiliser pour effectuer des opérations de base (comme obtenir des données de profil ou charger des fichiers sur son compte OneDrive). Les étapes sont similaires pour obtenir l’autorisation utilisateur et l’accès avec n’importe quel fournisseur d’identité qui prend en charge le Gestionnaire de comptes web.

Remarque

Pour obtenir un exemple de code complet, consultez l’exemple WebAccountManagement sur GitHub.

Se préparer

Tout d’abord, créez une application vide dans Visual Studio.

Ensuite, pour vous connecter aux fournisseurs d’identité, vous devez associer votre application au Windows Store. Pour ce faire, cliquez avec le bouton droit sur votre projet, choisissez l’application Store/Publish>Associate avec le Store, puis suivez les instructions de l’Assistant.

Troisièmement, créez une interface utilisateur très simple composée d’un bouton XAML simple et de deux zones de texte.

<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
	<Button x:Name="LoginButton" Content="Log in" Click="LoginButton_Click" />
	<TextBlock x:Name="UserIdTextBlock"/>
	<TextBlock x:Name="UserNameTextBlock"/>
</StackPanel>

Et un gestionnaire d’événements attaché à votre bouton dans le code-behind :

private void LoginButton_Click(object sender, RoutedEventArgs e)
{	
}

Enfin, ajoutez les espaces de noms suivants afin que vous n’ayez pas à vous soucier des problèmes de référence plus tard :

using System;
using Windows.Security.Authentication.Web.Core;
using Windows.System;
using Windows.UI.ApplicationSettings;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.Data.Json;
using Windows.UI.Xaml.Navigation;
using Windows.Web.Http;

Afficher le volet paramètres des comptes

Le système fournit une interface utilisateur intégrée pour la gestion des fournisseurs d’identité et des comptes web appelés AccountsSettingsPane. Vous pouvez l’afficher comme suit :

private void LoginButton_Click(object sender, RoutedEventArgs e)
{
	AccountsSettingsPane.Show(); 
}

Si vous exécutez votre application et cliquez sur le bouton « Se connecter », il doit afficher une fenêtre vide.

Capture d’écran de la fenêtre Choisir un compte sans comptes répertoriés.

Le volet est vide, car le système fournit uniquement un interpréteur de commandes d’interface utilisateur. Il incombe au développeur de remplir le volet par programmation avec les fournisseurs d’identité.

Conseil

Si vous le souhaitez, vous pouvez utiliser ShowAddAccountAsync au lieu de Show, qui retourne une IAsyncAction, pour rechercher l’état de l’opération.

S’inscrire à AccountCommandsRequested

Pour ajouter des commandes au volet, nous commençons par nous inscrire au gestionnaire d’événements AccountCommandsRequested. Cela indique au système d’exécuter notre logique de génération lorsque l’utilisateur demande à voir le volet (par exemple, cliquez sur notre bouton XAML).

Dans votre code-behind, remplacez les événements OnNavigatedTo et OnNavigatedFrom, puis ajoutez-y le code suivant :

protected override void OnNavigatedTo(NavigationEventArgs e)
{
	AccountsSettingsPane.GetForCurrentView().AccountCommandsRequested += BuildPaneAsync; 
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
	AccountsSettingsPane.GetForCurrentView().AccountCommandsRequested -= BuildPaneAsync; 
}

Les utilisateurs n’interagissent pas très souvent avec des comptes. Par conséquent, l’inscription et la désinscription de votre gestionnaire d’événements de cette façon empêchent les fuites de mémoire. De cette façon, votre volet personnalisé est uniquement en mémoire lorsqu’il y a une forte probabilité qu’un utilisateur le demande (car il se trouve sur une page « paramètres » ou « connexion », par exemple).

Générer le volet Paramètres du compte

La méthode BuildPaneAsync est appelée chaque fois que AccountsSettingsPane est affiché. C’est là que nous allons placer le code pour personnaliser les commandes affichées dans le volet.

Commencez par obtenir un report. Cela indique au système de retarder l’affichage de AccountsSettingsPane jusqu’à ce que nous ayons terminé de le générer.

private async void BuildPaneAsync(AccountsSettingsPane s,
	AccountsSettingsPaneCommandsRequestedEventArgs e)
{
	var deferral = e.GetDeferral();
		
	deferral.Complete(); 
}

Ensuite, obtenez un fournisseur à l’aide de la méthode WebAuthenticationCoreManager.FindAccountProviderAsync. L’URL du fournisseur varie en fonction du fournisseur et se trouve dans la documentation du fournisseur. Pour les comptes Microsoft et Azure Active Directory, il s’agit de «https://login.microsoft.com" ;

private async void BuildPaneAsync(AccountsSettingsPane s,
	AccountsSettingsPaneCommandsRequestedEventArgs e)
{
	var deferral = e.GetDeferral();
		
	var msaProvider = await WebAuthenticationCoreManager.FindAccountProviderAsync(
		"https://login.microsoft.com", "consumers"); 
		
	deferral.Complete(); 
}

Notez que nous transmettons également la chaîne « consommateurs » au paramètre d’autorité facultatif. Cela est dû au fait que Microsoft fournit deux types d’authentification différents : les comptes Microsoft (MSA) pour les « consommateurs » et Azure Active Directory (AAD) pour les « organisations ». L’autorité « consommateurs » indique que nous voulons l’option MSA. Si vous développez une application d’entreprise, utilisez plutôt la chaîne « organisations ».

Enfin, ajoutez le fournisseur à AccountsSettingsPane en créant une commande WebAccountProviderCommand comme suit :

private async void BuildPaneAsync(AccountsSettingsPane s,
	AccountsSettingsPaneCommandsRequestedEventArgs e)
{
	var deferral = e.GetDeferral();

	var msaProvider = await WebAuthenticationCoreManager.FindAccountProviderAsync(
		"https://login.microsoft.com", "consumers");

	var command = new WebAccountProviderCommand(msaProvider, GetMsaTokenAsync);  

	e.WebAccountProviderCommands.Add(command);

	deferral.Complete(); 
}

La méthode GetMsaToken que nous avons passée à notre nouveau WebAccountProviderCommand n’existe pas encore (nous allons générer cela à l’étape suivante), donc n’hésitez pas à l’ajouter en tant que méthode vide pour l’instant.

Exécutez le code ci-dessus et votre volet doit ressembler à ceci :

Capture d’écran de la fenêtre Choisir un compte avec des comptes répertoriés.

Demander un jeton

Une fois que nous avons l’option Compte Microsoft affichée dans AccountsSettingsPane, nous devons gérer ce qui se passe lorsque l’utilisateur le sélectionne. Nous avons inscrit notre méthode GetMsaToken à déclencher lorsque l’utilisateur choisit de se connecter avec son compte Microsoft. Nous allons donc obtenir le jeton.

Pour obtenir un jeton, utilisez la méthode RequestTokenAsync comme suit :

private async void GetMsaTokenAsync(WebAccountProviderCommand command)
{
	WebTokenRequest request = new WebTokenRequest(command.WebAccountProvider, "wl.basic");
	WebTokenRequestResult result = await WebAuthenticationCoreManager.RequestTokenAsync(request);
}

Dans cet exemple, nous transmettons la chaîne « wl.basic » au paramètre d’étendue. L’étendue représente le type d’informations que vous demandez auprès du service fourni sur un utilisateur spécifique. Certaines étendues fournissent un accès uniquement aux informations de base d’un utilisateur, telles que le nom et l’adresse e-mail, tandis que d’autres étendues peuvent accorder l’accès à des informations sensibles telles que les photos ou la boîte de réception de messagerie de l’utilisateur. En règle générale, votre application doit utiliser la portée la moins permissive nécessaire pour atteindre sa fonction. Les fournisseurs de services fournissent une documentation sur les étendues nécessaires pour obtenir des jetons à utiliser avec leurs services.

Conseil

Si vous le souhaitez, si votre application utilise un indicateur de connexion (pour remplir le champ utilisateur avec une adresse e-mail par défaut) ou une autre propriété spéciale liée à l’expérience de connexion, répertoriez-la dans la propriété WebTokenRequest.AppProperties. Cela entraîne l’ignorer par le système lors de la mise en cache du compte web, ce qui empêche les incompatibilités de compte dans le cache.

Si vous développez une application d’entreprise, vous souhaiterez probablement vous connecter à une instance Azure Active Directory (AAD) et utiliser l’API Microsoft Graph au lieu de services MSA standard. Dans ce scénario, utilisez plutôt le code suivant :

private async void GetAadTokenAsync(WebAccountProviderCommand command)
{
	string clientId = "your_guid_here"; // Obtain your clientId from the Azure Portal
	WebTokenRequest request = new WebTokenRequest(provider, "User.Read", clientId);
	request.Properties.Add("resource", "https://graph.microsoft.com");
	WebTokenRequestResult result = await WebAuthenticationCoreManager.RequestTokenAsync(request);
}

Le reste de cet article continue de décrire le scénario MSA, mais le code d’AAD est très similaire. Pour plus d’informations sur AAD/Graph, y compris un exemple complet sur GitHub, consultez la documentation Microsoft Graph.

Utilisation du jeton

La méthode RequestTokenAsync retourne un objet WebTokenRequestResult, qui contient les résultats de votre requête. Si votre demande a réussi, elle contiendra un jeton.

private async void GetMsaTokenAsync(WebAccountProviderCommand command)
{
	WebTokenRequest request = new WebTokenRequest(command.WebAccountProvider, "wl.basic");
	WebTokenRequestResult result = await WebAuthenticationCoreManager.RequestTokenAsync(request);
	
	if (result.ResponseStatus == WebTokenRequestStatus.Success)
	{
		string token = result.ResponseData[0].Token; 
	}
}

Remarque

Si vous recevez une erreur lors de la demande d’un jeton, vérifiez que vous avez associé votre application au Windows Store, comme décrit à l’étape 1. Votre application ne pourra pas obtenir de jeton si vous avez ignoré cette étape.

Une fois que vous avez un jeton, vous pouvez l’utiliser pour appeler l’API de votre fournisseur. Dans le code ci-dessous, nous allons appeler les informations utilisateur de l’API Microsoft Live pour obtenir des informations de base sur l’utilisateur et l’afficher dans notre interface utilisateur. Notez toutefois que dans la plupart des cas, il est recommandé de stocker le jeton une fois obtenu, puis de l’utiliser dans une méthode distincte.

private async void GetMsaTokenAsync(WebAccountProviderCommand command)
{
	WebTokenRequest request = new WebTokenRequest(command.WebAccountProvider, "wl.basic");
	WebTokenRequestResult result = await WebAuthenticationCoreManager.RequestTokenAsync(request);
	
	if (result.ResponseStatus == WebTokenRequestStatus.Success)
	{
		string token = result.ResponseData[0].Token; 
		
		var restApi = new Uri(@"https://apis.live.net/v5.0/me?access_token=" + token);

		using (var client = new HttpClient())
		{
			var infoResult = await client.GetAsync(restApi);
			string content = await infoResult.Content.ReadAsStringAsync();

			var jsonObject = JsonObject.Parse(content);
			string id = jsonObject["id"].GetString();
			string name = jsonObject["name"].GetString();

			UserIdTextBlock.Text = "Id: " + id; 
			UserNameTextBlock.Text = "Name: " + name;
		}
	}
}

La façon dont vous appelez différentes API REST varie entre les fournisseurs ; consultez la documentation de l’API du fournisseur pour plus d’informations sur l’utilisation de votre jeton.

Stocker le compte pour une utilisation ultérieure

Les jetons sont utiles pour obtenir immédiatement des informations sur un utilisateur, mais ils ont généralement des durées de vie variables : les jetons MSA, par exemple, ne sont valides que pendant quelques heures. Heureusement, vous n’avez pas besoin de réexécérer le AccountsSettingsPane chaque fois qu’un jeton expire. Une fois qu’un utilisateur a autorisé votre application une seule fois, vous pouvez stocker les informations de compte de l’utilisateur pour une utilisation ultérieure.

Pour ce faire, utilisez la classe WebAccount. Un WebAccount est retourné par la même méthode que celle utilisée pour demander le jeton :

private async void GetMsaTokenAsync(WebAccountProviderCommand command)
{
	WebTokenRequest request = new WebTokenRequest(command.WebAccountProvider, "wl.basic");
	WebTokenRequestResult result = await WebAuthenticationCoreManager.RequestTokenAsync(request);
	
	if (result.ResponseStatus == WebTokenRequestStatus.Success)
	{
		WebAccount account = result.ResponseData[0].WebAccount; 
	}
}

Une fois que vous disposez d’une instance WebAccount , vous pouvez facilement la stocker. Dans l’exemple suivant, nous utilisons LocalSettings. Pour plus d’informations sur l’utilisation de LocalSettings et d’autres méthodes pour stocker des données utilisateur, consultez Store et récupérer les paramètres et les données de l’application.

private async void StoreWebAccount(WebAccount account)
{
	ApplicationData.Current.LocalSettings.Values["CurrentUserProviderId"] = account.WebAccountProvider.Id;
	ApplicationData.Current.LocalSettings.Values["CurrentUserId"] = account.Id; 
}

Ensuite, nous pouvons utiliser une méthode asynchrone comme la suivante pour tenter d’obtenir un jeton en arrière-plan avec le WebAccount stocké.

private async Task<string> GetTokenSilentlyAsync()
{
	string providerId = ApplicationData.Current.LocalSettings.Values["CurrentUserProviderId"]?.ToString();
	string accountId = ApplicationData.Current.LocalSettings.Values["CurrentUserId"]?.ToString();

	if (null == providerId || null == accountId)
	{
		return null; 
	}

	WebAccountProvider provider = await WebAuthenticationCoreManager.FindAccountProviderAsync(providerId);
	WebAccount account = await WebAuthenticationCoreManager.FindAccountAsync(provider, accountId);

	WebTokenRequest request = new WebTokenRequest(provider, "wl.basic");

	WebTokenRequestResult result = await WebAuthenticationCoreManager.GetTokenSilentlyAsync(request, account);
	if (result.ResponseStatus == WebTokenRequestStatus.UserInteractionRequired)
	{
		// Unable to get a token silently - you'll need to show the UI
		return null; 
	}
	else if (result.ResponseStatus == WebTokenRequestStatus.Success)
	{
		// Success
		return result.ResponseData[0].Token;
	}
	else
	{
		// Other error 
		return null; 
	}
}

Placez la méthode ci-dessus juste avant le code qui génère accountsSettingsPane. Si le jeton est obtenu en arrière-plan, il n’est pas nécessaire d’afficher le volet.

private void LoginButton_Click(object sender, RoutedEventArgs e)
{
	string silentToken = await GetMsaTokenSilentlyAsync();

	if (silentToken != null)
	{
		// the token was obtained. store a reference to it or do something with it here.
	}
	else
	{
		// the token could not be obtained silently. Show the AccountsSettingsPane
		AccountsSettingsPane.Show();
	}
}

Étant donné que l’obtention d’un jeton en mode silencieux est très simple, vous devez utiliser ce processus pour actualiser votre jeton entre les sessions plutôt que de mettre en cache un jeton existant (car ce jeton peut expirer à tout moment).

Remarque

L’exemple ci-dessus couvre uniquement les cas de réussite et d’échec de base. Votre application doit également prendre en compte des scénarios inhabituels (comme un utilisateur qui révoque l’autorisation de votre application ou supprime son compte de Windows, par exemple) et les gère correctement.

Supprimer un compte stocké

Si vous conservez un compte web, vous pouvez donner à vos utilisateurs la possibilité de dissocier leur compte avec votre application. De cette façon, ils peuvent effectivement « se déconnecter » de l’application : leurs informations de compte ne seront plus chargées automatiquement lors du lancement. Pour ce faire, supprimez tout d’abord les informations de compte et de fournisseur enregistrées du stockage. Appelez ensuite SignOutAsync pour effacer le cache et invalider les jetons existants que votre application peut avoir.

private async Task SignOutAccountAsync(WebAccount account)
{
	ApplicationData.Current.LocalSettings.Values.Remove("CurrentUserProviderId");
	ApplicationData.Current.LocalSettings.Values.Remove("CurrentUserId"); 
	account.SignOutAsync(); 
}

Ajouter des fournisseurs qui ne prennent pas en charge WebAccountManager

Si vous souhaitez intégrer l’authentification à partir d’un service dans votre application, mais que ce service ne prend pas en charge WebAccountManager - Google+ ou Twitter, par exemple - vous pouvez toujours ajouter manuellement ce fournisseur au AccountsSettingsPane. Pour ce faire, créez un objet WebAccountProvider et fournissez votre propre nom et .png icône, puis ajoutez-le à la liste WebAccountProviderCommands. Voici un code stub :

private async void BuildPaneAsync(AccountsSettingsPane s, AccountsSettingsPaneCommandsRequestedEventArgs e)
{
	// other code here 

	var twitterProvider = new WebAccountProvider("twitter", "Twitter", new Uri(@"ms-appx:///Assets/twitter-auth-icon.png")); 
	var twitterCmd = new WebAccountProviderCommand(twitterProvider, GetTwitterTokenAsync);
	e.WebAccountProviderCommands.Add(twitterCmd);	
	
	// other code here
}

private async void GetTwitterTokenAsync(WebAccountProviderCommand command)
{
	// Manually handle Twitter login here
}

Remarque

Cette opération ajoute uniquement une icône à AccountsSettingsPane et exécute la méthode que vous spécifiez lorsque l’icône est cliquée (GetTwitterTokenAsync, dans ce cas). Vous devez fournir le code qui gère l’authentification réelle. Pour plus d’informations, consultez le répartiteur d’authentification web, qui fournit des méthodes d’assistance pour l’authentification à l’aide de services REST.

Ajouter un en-tête personnalisé

Vous pouvez personnaliser le volet des paramètres du compte à l’aide de la propriété HeaderText, comme suit :

private async void BuildPaneAsync(AccountsSettingsPane s, AccountsSettingsPaneCommandsRequestedEventArgs e)
{
	// other code here 
	
	args.HeaderText = "MyAwesomeApp works best if you're signed in."; 	
	
	// other code here
}

Capture d’écran de la fenêtre Choisir un compte sans comptes répertoriés et un message indiquant que Mon application géniale fonctionne mieux si vous êtes connecté.

Ne passez pas au-dessus du tableau avec du texte d’en-tête ; gardez-le court et doux. Si votre processus de connexion est compliqué et que vous devez afficher plus d’informations, liez l’utilisateur à une page distincte à l’aide d’un lien personnalisé.

Vous pouvez ajouter des commandes personnalisées à AccountsSettingsPane, qui apparaissent sous la forme de liens sous vos WebAccountProviders pris en charge. Les commandes personnalisées sont idéales pour les tâches simples liées aux comptes d’utilisateur, telles que l’affichage d’une stratégie de confidentialité ou le lancement d’une page de support pour les utilisateurs ayant des problèmes.

Voici un exemple :

private async void BuildPaneAsync(AccountsSettingsPane s, AccountsSettingsPaneCommandsRequestedEventArgs e)
{
	// other code here 
	
	var settingsCmd = new SettingsCommand(
		"settings_privacy", 
		"Privacy policy", 
		async (x) => await Launcher.LaunchUriAsync(new Uri(@"https://privacy.microsoft.com/en-US/"))); 

	e.Commands.Add(settingsCmd); 
	
	// other code here
}

Capture d’écran de la fenêtre Choisir un compte sans comptes répertoriés et un lien vers une stratégie de confidentialité.

Théoriquement, vous pouvez utiliser des commandes de paramètres pour tout ce qui est. Toutefois, nous vous suggérons de limiter leur utilisation aux scénarios intuitifs liés au compte, comme ceux décrits ci-dessus.

Voir aussi

Espace de noms Windows.Security.Authentication.Web.Core

Espace de noms Windows.Security.Credentials

AccountsSettingsPane, classe

Service Broker d’authentification web

Exemple de gestion de compte web

Application Planificateur de déjeuner