Compartir a través de


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.

  1. 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.

  2. Haga clic con el botón derecho en el proyecto SignInMaui y seleccione Agregar>Nueva carpeta. Asigne a la carpeta el nombre Vistas.

  3. Haga clic con el botón derecho en Vistas .

  4. Seleccione Agregar>Nuevo elemento....

  5. Seleccione .NET MAUI en la lista de plantillas.

  6. Seleccione la plantilla ContentPage (XAML) de .NET MAUI. Asigne al archivo el nombre MainView.xaml.

  7. Seleccione Agregar.

  8. 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>
    
  9. 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 evento Clicked. Puede ejecutar código en respuesta al evento Clicked.
    • Clicked="OnSignInClicked" el evento Clicked del botón se asigna al controlador de eventos OnSignInClicked, 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.

  1. 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.

  1. En el panel Explorador de soluciones de Visual Studio, haga clic con el botón derecho en Vistas.

  2. Seleccione Agregar>Nuevo elemento....

  3. Seleccione .NET MAUI en la lista de plantillas.

  4. Seleccione la plantilla ContentPage (XAML) de .NET MAUI. Asigne al archivo el nombre ClaimsView.xaml.

  5. Seleccione Agregar.

  6. 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 elementos Label que muestran texto estático, seguido de un ListView denominado Claims que enlaza a una colección denominada IdTokenClaims para mostrar las notificaciones encontradas en el token de Id. Cada notificación se representa dentro de un ViewCell mediante un DataTemplate elemento y se muestra como un centrado Label 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 eventos SignOutButton_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.

  1. 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 extiende ContentPage. La propiedad IdTokenClaims 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étodo SetViewDataAsync de forma asincrónica. El método SetViewDataAsync intenta adquirir un token de forma silenciosa, recupera las notificaciones del resultado de autenticación y establece la propiedad IdTokenClaims para mostrarlas en el ListView denominado Claims. Si se produce MsalUiRequiredException, 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 eventos SignOutButton_Clicked cierra la sesión del usuario mediante la instancia PublicClientSingleton y, al finalizar, navega a main 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.

  1. 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 elemento ShellContent con un título Home y una plantilla de contenido que apunta a la clase MainView.

  2. 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 para MainView y ClaimsView. Al llamar al método InitializeComponent(), se garantiza la inicialización de la clase AppShell. El método RegisterRoute() asocia las rutas mainview y claimsview con sus respectivos tipos de vista, MainView y ClaimsView.

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:

  1. En el panel Explorador de soluciones de Visual Studio, haga clic con el botón derecho en el proyecto SignInMaui>Agregar>Nuevo elemento....

  2. Seleccione Web>Archivo de configuración JSON de JavaScript. Ponga al archivo el nombre appsettings.json.

  3. Seleccione Agregar.

  4. Seleccione appsettings.json

  5. En el panel Propiedades, establezca Acción de compilación en Recurso incrustado.

  6. En el panel Propiedades, establezca Copiar en el directorio de salida en Copiar si es posterior.

  7. 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"
      }
    }
    
  8. En appsettings.json, busque el marcador de posición:

    1. Enter_the_Tenant_Subdomain_Here y reemplácelo por el subdominio del directorio (inquilino). Por ejemplo, si el dominio principal del inquilino es contoso.onmicrosoft.com, use contoso. Si no tiene el nombre del inquilino, vea cómo leer los datos del inquilino.
    2. 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:

  1. 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.

  2. Abra el archivo appsettings.json:

    1. Actualice el valor de la propiedad Authority a https://Enter_the_Custom_Domain_Here/Enter_the_Tenant_ID_Here. Reemplace Enter_the_Custom_Domain_Here por la dirección URL de dominio personalizado y Enter_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.
    2. Agregue la propiedad knownAuthorities con un valor [Escriba_aquí_el_dominio_personalizado].

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:

  1. Seleccione lista desplegable Destino de depuración.
  2. Seleccione el Marco de trabajo
  3. Seleccione net7.0-windows...

Ejecute la aplicación presionando F5 o seleccionando el botón reproducir situado en la parte superior de Visual Studio.

  1. 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:

    Captura de pantalla del botón de inicio de sesión en la aplicación de escritorio.

  2. 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.

    Captura de pantalla de la solicitud del usuario para escribir las credenciales en la aplicación de escritorio.

    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.

    Captura de pantalla de la página principal de la aplicación de escritorio después de iniciar sesión.

siguiente paso