Compartir a través de


Administrador de cuentas web

En este artículo se describe cómo usar AccountsSettingsPane para conectar la aplicación de Plataforma universal de Windows (UWP) a proveedores de identidades externos, como Microsoft o Facebook, mediante las API de Administrador de cuentas web de Windows 10 y Windows 11. Aprenderá a solicitar permiso de un usuario para usar su cuenta Microsoft, obtener un token de acceso y usarlo para realizar operaciones básicas (como obtener datos de perfil o cargar archivos en su cuenta de OneDrive). Los pasos son similares para obtener permisos de usuario y acceso con cualquier proveedor de identidades que admita el Administrador de cuentas web.

Nota:

Para obtener un ejemplo de código completo, consulte el ejemplo WebAccountManagement en GitHub.

Prepárate

En primer lugar, cree una nueva aplicación en blanco en Visual Studio.

En segundo lugar, para conectarse a proveedores de identidades, deberá asociar la aplicación a la Tienda. Para ello, haga clic con el botón derecho en el proyecto, elija Store/Publish>Associate app with the store (Asociar aplicación con la tienda) y siga las instrucciones del asistente.

En tercer lugar, cree una interfaz de usuario muy básica que consta de un simple botón XAML y dos cuadros de texto.

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

Y un controlador de eventos adjunto al botón en el código subyacente:

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

Por último, agregue los siguientes espacios de nombres para que no tenga que preocuparse por los problemas de referencia más adelante:

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;

Mostrar el panel de configuración de cuentas

El sistema proporciona una interfaz de usuario integrada para administrar proveedores de identidades y cuentas web denominadas AccountsSettingsPane. Puede mostrarlo de la siguiente manera:

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

Si ejecuta la aplicación y hace clic en el botón "Iniciar sesión", debería mostrar una ventana vacía.

Captura de pantalla de la ventana Elegir una cuenta sin cuentas enumeradas.

El panel está vacío porque el sistema solo proporciona un shell de interfaz de usuario; es necesario que el desarrollador rellene mediante programación el panel con los proveedores de identidades.

Sugerencia

Opcionalmente, puede usar ShowAddAccountAsync en lugar de Show, que devolverá un IAsyncAction, para consultar el estado de la operación.

Registro para AccountCommandsRequested

Para agregar comandos al panel, empezamos registrando para el controlador de eventos AccountCommandsRequested. Esto indica al sistema que ejecute nuestra lógica de compilación cuando el usuario pida que vea el panel (por ejemplo, hace clic en el botón XAML).

En el código subyacente, invalide los eventos OnNavigatedTo y OnNavigatedFrom y agregue el código siguiente a ellos:

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

Los usuarios no interactúan con cuentas con mucha frecuencia, por lo que registrar y anular el registro del controlador de eventos de esta manera ayuda a evitar pérdidas de memoria. De este modo, el panel personalizado solo está en memoria cuando hay una gran probabilidad de que un usuario lo pida (porque se encuentra en una página "configuración" o "inicio de sesión", por ejemplo).

Crear el panel de configuración de la cuenta

Se llama al método BuildPaneAsync cada vez que se muestra accountsSettingsPane . Aquí es donde colocaremos el código para personalizar los comandos que se muestran en el panel.

Empiece por obtener un aplazamiento. Esto indica al sistema que retrase la visualización de AccountsSettingsPane hasta que hayamos terminado de compilarlo.

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

A continuación, obtenga un proveedor mediante el método WebAuthenticationCoreManager.FindAccountProviderAsync. La dirección URL del proveedor varía en función del proveedor y se puede encontrar en la documentación del proveedor. Para las cuentas de Microsoft y Azure Active Directory, es "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(); 
}

Observe que también pasamos la cadena "consumers" al parámetro de autoridad opcional. Esto se debe a que Microsoft proporciona dos tipos diferentes de autenticación: cuentas Microsoft (MSA) para "consumidores" y Azure Active Directory (AAD) para "organizaciones". La entidad de "consumidores" indica que queremos la opción MSA. Si va a desarrollar una aplicación empresarial, use la cadena "organizations" en su lugar.

Por último, agregue el proveedor a AccountsSettingsPane mediante la creación de un nuevo WebAccountProviderCommand de la siguiente manera:

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(); 
}

El método GetMsaToken que pasamos a nuestro nuevo WebAccountProviderCommand aún no existe (lo compilaremos en el paso siguiente), así que no dude en agregarlo como un método vacío por ahora.

Ejecute el código anterior y el panel debe tener un aspecto similar al siguiente:

Captura de pantalla de la ventana Elegir una cuenta con cuentas enumeradas.

Solicitar un token

Una vez que tengamos la opción Cuenta Microsoft que se muestra en AccountsSettingsPane, es necesario controlar lo que sucede cuando el usuario lo selecciona. Registramos nuestro método GetMsaToken para que se active cuando el usuario decida iniciar sesión con su cuenta Microsoft, por lo que obtendremos el token allí.

Para obtener un token, use el método RequestTokenAsync de la siguiente manera:

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

En este ejemplo, pasamos la cadena "wl.basic" al parámetro de ámbito . El ámbito representa el tipo de información que solicita del servicio de prestación en un usuario específico. Algunos ámbitos proporcionan acceso solo a la información básica de un usuario, como el nombre y la dirección de correo electrónico, mientras que otros ámbitos pueden conceder acceso a información confidencial, como las fotos del usuario o la bandeja de entrada de correo electrónico. Por lo general, la aplicación debe usar el ámbito menos permisivo necesario para lograr su función. Los proveedores de servicios proporcionarán documentación sobre qué ámbitos son necesarios para obtener tokens para su uso con sus servicios.

Sugerencia

Opcionalmente, si la aplicación usa una sugerencia de inicio de sesión (para rellenar el campo de usuario con una dirección de correo electrónico predeterminada) u otra propiedad especial relacionada con la experiencia de inicio de sesión, enumere en la propiedad WebTokenRequest.AppProperties. Esto hará que el sistema ignore la propiedad al almacenar en caché la cuenta web, lo que impide que la cuenta no coincida en la memoria caché.

Si va a desarrollar una aplicación empresarial, es probable que quiera conectarse a una instancia de Azure Active Directory (AAD) y usar Microsoft Graph API en lugar de servicios de MSA normales. En este escenario, use el código siguiente en su lugar:

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);
}

El resto de este artículo sigue describiendo el escenario de MSA, pero el código de AAD es muy similar. Para obtener más información sobre AAD/Graph, incluido un ejemplo completo en GitHub, consulte la documentación de Microsoft Graph.

Uso del token

El método RequestTokenAsync devuelve un objeto WebTokenRequestResult, que contiene los resultados de la solicitud. Si la solicitud se realizó correctamente, contendrá un token.

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; 
	}
}

Nota:

Si recibes un error al solicitar un token, asegúrate de que has asociado la aplicación a la Tienda como se describe en el paso uno. La aplicación no podrá obtener un token si omite este paso.

Una vez que tenga un token, puede usarlo para llamar a la API del proveedor. En el código siguiente, llamaremos a la información de usuario de Microsoft Live API para obtener información básica sobre el usuario y mostrarla en nuestra interfaz de usuario. Sin embargo, tenga en cuenta que, en la mayoría de los casos, se recomienda almacenar el token una vez obtenido y, a continuación, usarlo en un método independiente.

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 forma de llamar a varias API REST varía entre proveedores; Consulte la documentación de la API del proveedor para obtener información sobre cómo usar el token.

Almacenar la cuenta para su uso futuro

Los tokens son útiles para obtener información inmediatamente sobre un usuario, pero normalmente tienen distintas duraciones: los tokens de MSA, por ejemplo, solo son válidos durante unas pocas horas. Afortunadamente, no es necesario volver a mostrar accountsSettingsPane cada vez que expire un token. Una vez que un usuario haya autorizado la aplicación una vez, puede almacenar la información de la cuenta del usuario para su uso futuro.

Para ello, use la clase WebAccount . WebAccount lo devuelve el mismo método que usó para solicitar el token:

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; 
	}
}

Una vez que tenga una instancia de WebAccount , puede almacenarla fácilmente. En el ejemplo siguiente, usamos LocalSettings. Para obtener más información sobre el uso de LocalSettings y otros métodos para almacenar datos de usuario, consulta Almacenar y recuperar la configuración y los datos de la aplicación.

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

A continuación, podemos usar un método asincrónico como el siguiente para intentar obtener un token en segundo plano con la cuenta web almacenada.

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; 
	}
}

Coloque el método anterior justo antes del código que compila AccountsSettingsPane. Si el token se obtiene en segundo plano, no es necesario mostrar el panel.

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();
	}
}

Dado que obtener un token de forma silenciosa es muy sencillo, debe usar este proceso para actualizar el token entre sesiones en lugar de almacenar en caché un token existente (ya que ese token puede expirar en cualquier momento).

Nota:

En el ejemplo anterior solo se tratan los casos básicos de éxito y error. La aplicación también debe tener en cuenta escenarios inusuales (como revocar el permiso de la aplicación o quitar su cuenta de Windows, por ejemplo) y controlarla correctamente.

Quitar una cuenta almacenada

Si conserva una cuenta web, es posible que quiera conceder a los usuarios la posibilidad de desasociar su cuenta con la aplicación. De este modo, pueden "cerrar sesión" de la aplicación de forma eficaz: su información de cuenta ya no se cargará automáticamente al iniciarse. Para ello, quite primero cualquier información de proveedor y cuenta guardada del almacenamiento. A continuación, llame a SignOutAsync para borrar la memoria caché e invalidar los tokens existentes que pueda tener la aplicación.

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

Agregar proveedores que no admiten WebAccountManager

Si quiere integrar la autenticación desde un servicio en la aplicación, pero ese servicio no admite WebAccountManager - Google+ o Twitter, por ejemplo, puede agregar manualmente ese proveedor a AccountsSettingsPane. Para ello, cree un nuevo objeto WebAccountProvider y proporcione su propio nombre y .png icono, a continuación, agréguelo a la lista WebAccountProviderCommands. Este es un código auxiliar:

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
}

Nota:

Esto solo agrega un icono a AccountsSettingsPane y ejecuta el método especificado cuando se hace clic en el icono (GetTwitterTokenAsync, en este caso). Debe proporcionar el código que controla la autenticación real. Para obtener más información, consulte Agente de autenticación web, que proporciona métodos auxiliares para autenticarse mediante servicios REST.

Agregar un encabezado personalizado

Puede personalizar el panel de configuración de la cuenta mediante la propiedad HeaderText, de la siguiente manera:

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

Captura de pantalla de la ventana Elegir una cuenta sin cuentas enumeradas y un mensaje que indica My Awesome App funciona mejor si ha iniciado sesión.

No sobrepases con texto de encabezado; mantenlo corto y dulce. Si el proceso de inicio de sesión es complicado y necesita mostrar más información, vincule al usuario a una página independiente mediante un vínculo personalizado.

Puede agregar comandos personalizados a AccountsSettingsPane, que aparecen como vínculos debajo de los webAccountProviders admitidos. Los comandos personalizados son excelentes para tareas sencillas relacionadas con las cuentas de usuario, como mostrar una directiva de privacidad o iniciar una página de soporte técnico para los usuarios que tienen problemas.

Este es un ejemplo:

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
}

Captura de pantalla de la ventana Elegir una cuenta sin cuentas enumeradas y un vínculo a una directiva de privacidad.

En teoría, puede usar comandos de configuración para cualquier cosa. Sin embargo, se recomienda limitar su uso a escenarios intuitivos relacionados con la cuenta, como los descritos anteriormente.

Consulte también

Espacio de nombres Windows.Security.Authentication.Web.Core

Espacio de nombres Windows.Security.Credentials

Clase AccountsSettingsPane

Agente de autenticación web

Ejemplo de administración de cuentas web

Aplicación De programador de almuerzos