Tutorial: inicio de sesión de los usuarios en la aplicación de MAUI de .NET mediante un inquilino externo
Este tutorial es la parte final de una serie que muestra cómo agregar código de inicio y cierre de sesión en el shell de la interfaz de usuario de aplicaciones multiplataforma de .NET (.NET MAUI) y ejecutar la aplicación en la plataforma Windows. En Parte 2 de esta serie, creó una aplicación de shell de MAUI de .NET, agregó compatibilidad con el SDK de MSAL a través de clases auxiliares de MSAL, bibliotecas necesarias instaladas e incluyó un recurso de imagen. En este paso final se muestra cómo agregar código de inicio de sesión y cierre de sesión en el shell de .NET MAUI y ejecutar la aplicación en la plataforma Windows.
En este tutorial, aprenderá a:
- Agregar inicio y cierre de sesión.
- Modificar el shell de la aplicación.
- Agregar código específico de plataforma.
- Agregar la configuración de la aplicación.
- Ejecute y pruebe la aplicación de shell MAUI de .NET.
Requisitos previos
Adición de inicio y cierre de sesión
La interfaz de usuario (UI) de una aplicación .NET MAUI se construye de objetos que se asignan a los controles nativos de cada plataforma de destino. Los grupos de controles principales que se usan para crear la interfaz de usuario de una aplicación .NET MAUI son páginas, diseños y vistas.
Agregar página de vista principal
En los próximos pasos organizaremos nuestro código para que main view
esté definido.
Elimine MainPage.xaml y MainPage.xaml.cs del proyecto, ya no son necesarios. En el panel Explorador de soluciones, busque la entrada de MainPage.xaml, haga clic con el botón derecho en ella y seleccione Eliminar.
Haga clic con el botón derecho en el proyecto SignInMaui y seleccione Agregar>Nueva carpeta. Asigne a la carpeta el nombre Vistas.
Haga clic con el botón derecho en Vistas .
Seleccione Agregar>Nuevo elemento....
Seleccione .NET MAUI en la lista de plantillas.
Seleccione la plantilla ContentPage (XAML) de .NET MAUI. Asigne al archivo el nombre MainView.xaml.
Seleccione Agregar.
El archivo MainView.xaml se abrirá en una nueva pestaña de documento, mostrando todo el marcado XAML que representa la interfaz de usuario de la página. Reemplace el marcado XAML por el siguiente marcado:
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="SignInMaui.Views.MainView" Title="Microsoft Entra External ID" > <Shell.BackButtonBehavior> <BackButtonBehavior IsVisible="False" IsEnabled="False" /> </Shell.BackButtonBehavior> <ScrollView> <VerticalStackLayout Spacing="25" Padding="30,0" VerticalOptions="Center"> <Image Source="external_id.png" SemanticProperties.Description="External ID" HeightRequest="200" HorizontalOptions="Center" /> <Label Text="CIAM" SemanticProperties.HeadingLevel="Level1" FontSize="26" HorizontalOptions="Center" /> <Label Text="MAUI sample" SemanticProperties.HeadingLevel="Level1" FontSize="26" HorizontalOptions="Center" /> <Button x:Name="SignInButton" Text="Sign In" SemanticProperties.Hint="Sign In" Clicked="OnSignInClicked" HorizontalOptions="Center" IsEnabled="False"/> </VerticalStackLayout> </ScrollView> </ContentPage>
Guarde el archivo.
Vamos a desglosar las partes clave de los controles XAML colocados en la página:
<ContentPage>
es el objeto raíz de la clase MainView.<VerticalStackLayout>
es el objeto secundario de ContentPage. Este control de diseño organiza sus elementos secundarios verticalmente, uno después del otro.<Image>
muestra una imagen, en este caso usa el azureactive_directory.png_ que descargó anteriormente.<Label>
controla la visualización del texto.<Button>
el usuario puede presionarlo, lo que genera el eventoClicked
. Puede ejecutar código en respuesta al eventoClicked
.Clicked="OnSignInClicked"
el eventoClicked
del botón se asigna al controlador de eventosOnSignInClicked
, que se definirá en el archivo de código subyacente. La creará en el paso siguiente.
Controlar el evento OnSignInClicked
El siguiente paso consiste en agregar el código para el evento del botón Clicked
.
En el panel Explorador de soluciones de Visual Studio, expanda el archivo MainView.xaml para mostrar su archivo de código subyacente mainView.xaml.cs. Abra MainView.xaml.cs y reemplace el contenido del archivo por el siguiente código:
// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. using SignInMaui.MSALClient; using Microsoft.Identity.Client; namespace SignInMaui.Views { public partial class MainView : ContentPage { public MainView() { InitializeComponent(); IAccount cachedUserAccount = PublicClientSingleton.Instance.MSALClientHelper.FetchSignedInUserFromCache().Result; _ = Dispatcher.DispatchAsync(async () => { if (cachedUserAccount == null) { SignInButton.IsEnabled = true; } else { await Shell.Current.GoToAsync("claimsview"); } }); } private async void OnSignInClicked(object sender, EventArgs e) { await PublicClientSingleton.Instance.AcquireTokenSilentAsync(); await Shell.Current.GoToAsync("claimsview"); } protected override bool OnBackButtonPressed() { return true; } } }
La clase MainView
es una página de contenido responsable de mostrar la vista principal de la aplicación. En el constructor, recupera la cuenta de usuario en caché utilizando el MSALClientHelper
de la instancia PublicClientSingleton
y habilita el botón de inicio de sesión, si no se encuentra ninguna cuenta de usuario en caché.
Cuando se hace clic en el botón de inicio de sesión, llama al método AcquireTokenSilentAsync
para adquirir un token de forma silenciosa y navega a la página claimsview
mediante el método Shell.Current.GoToAsync
. Además, el método OnBackButtonPressed
se invalida para devolver true, lo que indica que el botón atrás está deshabilitado para esta vista.
Agregar página de vista de reclamaciones
Los siguientes pasos organizarán el código para que la página ClaimsView
quede definida. La página mostrará las notificaciones del usuario que se encuentran en el token de Id.
En el panel Explorador de soluciones de Visual Studio, haga clic con el botón derecho en Vistas.
Seleccione Agregar>Nuevo elemento....
Seleccione .NET MAUI en la lista de plantillas.
Seleccione la plantilla ContentPage (XAML) de .NET MAUI. Asigne al archivo el nombre ClaimsView.xaml.
Seleccione Agregar.
El archivo ClaimsView.xaml se abrirá en una nueva pestaña de documento, mostrando todo el marcado XAML que representa la interfaz de usuario de la página. Reemplace el marcado XAML por el siguiente marcado:
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="SignInMaui.Views.ClaimsView" Title="ID Token View"> <Shell.BackButtonBehavior> <BackButtonBehavior IsVisible="False" IsEnabled="False" /> </Shell.BackButtonBehavior> <VerticalStackLayout> <Label Text="CIAM" FontSize="26" HorizontalOptions="Center" /> <Label Text="MAUI sample" FontSize="26" Padding="0,0,0,20" HorizontalOptions="Center" /> <Label Padding="0,20,0,0" VerticalOptions="Center" HorizontalOptions="Center" FontSize="18" Text="Claims found in ID token" /> <ListView ItemsSource="{Binding IdTokenClaims}" x:Name="Claims"> <ListView.ItemTemplate> <DataTemplate> <ViewCell> <Grid Padding="0, 0, 0, 0"> <Label Grid.Column="1" Text="{Binding}" HorizontalOptions="Center" /> </Grid> </ViewCell> </DataTemplate> </ListView.ItemTemplate> </ListView> <Button x:Name="SignOutButton" Text="Sign Out" HorizontalOptions="Center" Clicked="SignOutButton_Clicked" /> </VerticalStackLayout> </ContentPage>
Este código de marcado XAML representa el diseño de la interfaz de usuario de una vista de notificación en una aplicación .NET MAUI. Comienza definiendo
ContentPage
con un título y deshabilitando el comportamiento del botón atrás.Dentro de
VerticalStackLayout
, hay varios elementosLabel
que muestran texto estático, seguido de unListView
denominadoClaims
que enlaza a una colección denominadaIdTokenClaims
para mostrar las notificaciones encontradas en el token de Id. Cada notificación se representa dentro de unViewCell
mediante unDataTemplate
elemento y se muestra como un centradoLabel
dentro de una cuadrícula.Por último, hay un botón centrado
Sign Out
en la parte inferior del diseño, que desencadena el controlador de eventosSignOutButton_Clicked
cuando se hace clic en él.
Control de los datos de ClaimsView
El siguiente paso es agregar el código para controlar los datos ClaimsView
.
En el panel Explorador de soluciones de Visual Studio, expanda el archivo ClaimsView.xaml para mostrar su archivo de código subyacente ClaimsView.xaml.cs. Abra ClaimsView.xaml.cs y reemplace el contenido del archivo por el siguiente código:
using SignInMaui.MSALClient; using Microsoft.Identity.Client; namespace SignInMaui.Views; public partial class ClaimsView : ContentPage { public IEnumerable<string> IdTokenClaims { get; set; } = new string[] {"No claims found in ID token"}; public ClaimsView() { BindingContext = this; InitializeComponent(); _ = SetViewDataAsync(); } private async Task SetViewDataAsync() { try { _ = await PublicClientSingleton.Instance.AcquireTokenSilentAsync(); IdTokenClaims = PublicClientSingleton.Instance.MSALClientHelper.AuthResult.ClaimsPrincipal.Claims.Select(c => c.Value); Claims.ItemsSource = IdTokenClaims; } catch (MsalUiRequiredException) { await Shell.Current.GoToAsync("claimsview"); } } protected override bool OnBackButtonPressed() { return true; } private async void SignOutButton_Clicked(object sender, EventArgs e) { await PublicClientSingleton.Instance.SignOutAsync().ContinueWith((t) => { return Task.CompletedTask; }); await Shell.Current.GoToAsync("mainview"); } }
El código ClaimsView.xaml.cs representa el código subyacente de una vista de notificación en una aplicación .NET MAUI. Comienza importando los espacios de nombres necesarios y definiendo la clase
ClaimsView
, que extiendeContentPage
. La propiedadIdTokenClaims
es una enumeración de cadenas, establecida inicialmente en una sola cadena que indica que no se encontraron notificaciones.El constructor
ClaimsView
establece el contexto de enlace en la instancia actual, inicializa los componentes de vista y llama al métodoSetViewDataAsync
de forma asincrónica. El métodoSetViewDataAsync
intenta adquirir un token de forma silenciosa, recupera las notificaciones del resultado de autenticación y establece la propiedadIdTokenClaims
para mostrarlas en elListView
denominadoClaims
. Si se produceMsalUiRequiredException
, lo que indica que la interacción del usuario es necesaria para la autenticación, la aplicación navega a la vista de notificaciones.El método
OnBackButtonPressed
invalida el comportamiento del botón atrás para devolver siempre true, lo que impide que el usuario vuelva de esta vista. El controlador de eventosSignOutButton_Clicked
cierra la sesión del usuario mediante la instanciaPublicClientSingleton
y, al finalizar, navega amain view
.
Modificar el shell de la aplicación
La clase AppShell
define la jerarquía visual de una aplicación, el marcado XAML que se usa para crear la interfaz de usuario de la aplicación. Actualice AppShell
para que sepa sobre Views
.
Haga doble clic en el archivo
AppShell.xaml
del panel Explorador de soluciones para abrir el editor XAML. Reemplace el marcado XAML con el siguiente código:<?xml version="1.0" encoding="UTF-8" ?> <Shell x:Class="SignInMaui.AppShell" xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:SignInMaui.Views" Shell.FlyoutBehavior="Disabled"> <ShellContent Title="Home" ContentTemplate="{DataTemplate local:MainView}" Route="MainPage" /> </Shell>
El código XAML define una clase
AppShell
que deshabilita el comportamiento del control flotante y establece el contenido principal en un elementoShellContent
con un títuloHome
y una plantilla de contenido que apunta a la claseMainView
.En el panel Explorador de soluciones de Visual Studio, expanda el archivo AppShell.xaml para mostrar su archivo de código subyacente AppShell.xaml.cs. Abra AppShell.xaml.cs y reemplace el contenido del archivo por el siguiente código:
// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. using SignInMaui.Views; namespace SignInMaui; public partial class AppShell : Shell { public AppShell() { InitializeComponent(); Routing.RegisterRoute("mainview", typeof(MainView)); Routing.RegisterRoute("claimsview", typeof(ClaimsView)); } }
Actualice el archivo
AppShell.xaml.cs
para incluir los registros de ruta necesarios paraMainView
yClaimsView
. Al llamar al métodoInitializeComponent()
, se garantiza la inicialización de la claseAppShell
. El métodoRegisterRoute()
asocia las rutasmainview
yclaimsview
con sus respectivos tipos de vista,MainView
yClaimsView
.
Agregar código específico de la plataforma
Un proyecto de aplicación de .NET MAUI contiene una carpeta Plataformas, con cada carpeta secundaria que representa una plataforma que .NET MAUI puede tener como destino. Para proporcionar un comportamiento específico de la aplicación para complementar la clase de aplicación predeterminada, modifique Platforms/Windows/App.xaml.cs
.
Reemplace el contenido del archivo con el siguiente código:
using SignInMaui.MSALClient;
using Microsoft.Identity.Client;
using Microsoft.UI.Xaml;
// To learn more about WinUI, the WinUI project structure,
// and more about our project templates, see: http://aka.ms/winui-project-info.
namespace SignInMaui.WinUI;
/// <summary>
/// Provides application-specific behavior to supplement the default Application class.
/// </summary>
public partial class App : MauiWinUIApplication
{
/// <summary>
/// Initializes the singleton application object. This is the first line of authored code
/// executed, and as such is the logical equivalent of main() or WinMain().
/// </summary>
public App()
{
this.InitializeComponent();
// configure redirect URI for your application
PlatformConfig.Instance.RedirectUri = $"msal{PublicClientSingleton.Instance.MSALClientHelper.AzureAdConfig.ClientId}://auth";
// Initialize MSAL
IAccount existinguser = Task.Run(async () => await PublicClientSingleton.Instance.MSALClientHelper.InitializePublicClientAppAsync()).Result;
}
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
protected override void OnLaunched(LaunchActivatedEventArgs args)
{
base.OnLaunched(args);
var app = SignInMaui.App.Current;
PlatformConfig.Instance.ParentWindow = ((MauiWinUIWindow)app.Windows[0].Handler.PlatformView).WindowHandle;
}
}
En el código, configure el URI de redirección para la aplicación e inicie el MSAL y, a continuación, establezca la ventana primaria de la aplicación. Además, invalide el método OnLaunched
para controlar el evento de inicio y recupere el identificador de la ventana primaria.
Agregar la configuración de la aplicación
La configuración permite la separación de datos que configura el comportamiento de una aplicación desde el código, lo que permite cambiar el comportamiento sin volver a generar la aplicación. MauiAppBuilder
proporciona ConfigurationManager
para configurar las opciones en nuestra aplicación .NET MAUI. Vamos a agregar el archivo appsettings.json
como EmbeddedResource
.
Siga estos pasos para crear appsettings.json
:
En el panel Explorador de soluciones de Visual Studio, haga clic con el botón derecho en el proyecto SignInMaui>Agregar>Nuevo elemento....
Seleccione Web>Archivo de configuración JSON de JavaScript. Ponga al archivo el nombre
appsettings.json
.Seleccione Agregar.
Seleccione appsettings.json
En el panel Propiedades, establezca Acción de compilación en Recurso incrustado.
En el panel Propiedades, establezca Copiar en el directorio de salida en Copiar si es posterior.
Reemplace el contenido del archivo
appsettings.json
por el siguiente código:{ "AzureAd": { "Authority": "https://Enter_the_Tenant_Subdomain_Here.ciamlogin.com/", "ClientId": "Enter_the_Application_Id_Here", "CacheFileName": "msal_cache.txt", "CacheDir": "C:/temp" }, "DownstreamApi": { "Scopes": "openid offline_access" } }
En
appsettings.json
, busque el marcador de posición:Enter_the_Tenant_Subdomain_Here
y reemplácelo por el subdominio del directorio (inquilino). Por ejemplo, si el dominio principal del inquilino escontoso.onmicrosoft.com
, usecontoso
. Si no tiene el nombre del inquilino, vea cómo leer los datos del inquilino.Enter_the_Application_Id_Here
y reemplácelo por el identificador de aplicación (cliente) de la aplicación que registró anteriormente.
Uso del dominio de dirección URL personalizada (opcional)
Use un dominio personalizado para personalizar completamente la dirección URL de autenticación. Desde el punto de vista del usuario, este permanece en el dominio durante el proceso de autenticación, en lugar de que se le redirija al nombre de dominio ciamlogin.com.
Siga estos pasos para usar un dominio personalizado:
Siga los pasos descritos en Habilitar dominios de dirección URL personalizados para aplicaciones en inquilinos externos para habilitar la dirección URL de dominio personalizado para el inquilino externo.
Abra el archivo appsettings.json:
- Actualice el valor de la propiedad
Authority
a https://Enter_the_Custom_Domain_Here/Enter_the_Tenant_ID_Here. ReemplaceEnter_the_Custom_Domain_Here
por la dirección URL de dominio personalizado yEnter_the_Tenant_ID_Here
por el id. del inquilino. Si no tiene el identificador del inquilino, obtenga información sobre cómo leer los detalles del inquilino. - Agregue la propiedad
knownAuthorities
con un valor [Escriba_aquí_el_dominio_personalizado].
- Actualice el valor de la propiedad
Después de realizar los cambios en el archivo appsettings.json, si la dirección URL del dominio personalizado es login.contoso.comy el identificador de inquilino es aaaabbbb-0000-cccc-1111-dddd2222eeee, el archivo debe tener un aspecto similar al siguiente fragmento de código:
{
"AzureAd": {
"Authority": "https://login.contoso.com/aaaabbbb-0000-cccc-1111-dddd2222eeee",
"ClientId": "Enter_the_Application_Id_Here",
"CacheFileName": "msal_cache.txt",
"CacheDir": "C:/temp",
"KnownAuthorities": ["login.contoso.com"]
},
"DownstreamApi": {
"Scopes": "openid offline_access"
}
}
Ejecute y pruebe la aplicación de escritorio MAUI de .NET
Las aplicaciones .NET MAUI están diseñadas para ejecutarse en varios sistemas operativos y dispositivos. Deberá seleccionar el destino con el que quiere probar y depurar la aplicación.
Establezca el Destino de depuración en la barra de herramientas de Visual Studio en el dispositivo con el que desea depurar y probar. En los siguientes pasos se muestra cómo establecer el Destino de depuración en Windows:
- Seleccione lista desplegable Destino de depuración.
- Seleccione el Marco de trabajo
- Seleccione net7.0-windows...
Ejecute la aplicación presionando F5 o seleccionando el botón reproducir situado en la parte superior de Visual Studio.
Ahora puede probar la aplicación de escritorio de .NET MAUI de ejemplo. Después de ejecutar la aplicación, la ventana de la aplicación de escritorio aparece automáticamente:
En la ventana de escritorio que aparece, seleccione el botón Iniciar sesión. Se abre una ventana del explorador y se le pide que inicie sesión.
Durante el proceso de inicio de sesión, se le pedirá que conceda varios permisos (para permitir que la aplicación acceda a los datos). Después de iniciar sesión correctamente y dar su consentimiento, la pantalla de la aplicación muestra la página principal.