Condividi tramite


Esercitazione: Concedere l’accesso utente nell'app .NET MAUI usando un tenant esterno

Questa esercitazione è la parte finale di una serie che mostra come aggiungere il codice di accesso e disconnessione alla shell .NET Multi-Platform App UI (.NET MAUI) ed eseguire l'app nella piattaforma Windows. Nella seconda parte di questa serieè stata creata un'app shell .NET MAUI, è stato aggiunto il supporto di MSAL SDK tramite le classi helper MSAL, sono state installate le librerie necessarie ed è stata inclusa una risorsa immagine. Questo passaggio finale mostra come aggiungere il codice di accesso e disconnessione alla shell .NET MAUI ed eseguire l'app nella piattaforma Windows.

In questa esercitazione apprenderai a:

  • Aggiungere il codice di accesso e disconnessione.
  • Modificare la shell dell'app.
  • Aggiungere codice specifico per la piattaforma.
  • Aggiungere le impostazioni dell'app.
  • Eseguire e testare l'app shell .NET MAUI.

Prerequisiti

Aggiungere il codice di accesso e disconnessione

L'interfaccia utente di un'app .NET MAUI è costituita da oggetti che eseguono il mapping ai controlli nativi di ogni piattaforma di destinazione. I gruppi di controllo principali usati per creare l'interfaccia utente di un'app .NET MAUI sono pagine, layout e visualizzazioni.

Aggiungere la pagina della visualizzazione principale

Nei passaggi successivi viene definito il codice in modo che main view sia definito.

  1. Eliminare MainPage.xaml e MainPage.xaml.cs dal progetto in quanto non sono più necessari. Nel riquadro Esplora soluzioni individuare la voce MainPage.xaml, fare clic con il pulsante destro del mouse e selezionare Elimina.

  2. Fare clic con il pulsante destro del mouse sul progetto SignInMaui e selezionare Aggiungi>Nuova cartella. Assegnare il nome Visualizzazioni alla cartella.

  3. Fare clic con il pulsante destro del mouse su Visualizzazioni.

  4. Selezionare Aggiungi>Nuovo elemento....

  5. Selezionare .NET MAUI nell'elenco dei modelli.

  6. Selezionare il modello .NET MAUI ContentPage (XAML). Assegnare il nome MainView.xaml al file.

  7. Selezionare Aggiungi.

  8. Il file MainView.xaml verrà aperto in una nuova scheda del documento, visualizzando tutto il markup XAML che rappresenta l'interfaccia utente della pagina. Sostituire il markup XAML con il markup seguente:

    <?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. Salvare il file.

    Suddividere le parti principali dei controlli XAML presenti nella pagina:

    • <ContentPage> è l'oggetto radice per la classe MainView.
    • <VerticalStackLayout> è l'oggetto figlio di ContentPage. Questo controllo di layout dispone verticalmente gli elementi figlio, uno dopo l'altro.
    • <Image> visualizza un’immagine, in questo caso usando azureactive_directory.png_ scaricato in precedenza.
    • <Label> controlla il testo da visualizzare.
    • <Button> può essere premuto dall'utente per generare l'evento Clicked. È possibile eseguire il codice in risposta all'evento Clicked.
    • Clicked="OnSignInClicked" l'evento Clicked del pulsante viene assegnato al gestore eventi OnSignInClicked, che verrà definito nel file code-behind. Questo codice verrà creato nel passaggio successivo.

Gestire l'evento OnSignInClicked

Il passaggio successivo consiste nell'aggiungere il codice per l'evento Clicked del pulsante.

  1. Nel riquadro Esplora soluzioni di Visual Studio espandere il file MainView.xaml per visualizzare il file code-behind MainView.xaml.cs. Aprire il file MainView.xaml.cs e sostituire il contenuto del file con il codice seguente:

    // 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 classe MainView è una pagina di contenuto responsabile della visualizzazione della finestra principale dell'app. Nel costruttore recupera l'account utente memorizzato nella cache usando MSALClientHelper dall'istanza PublicClientSingleton e abilita il pulsante di accesso, se non trova alcun account utente memorizzato nella cache.

Quando si fa clic sul pulsante di accesso, chiama il metodo AcquireTokenSilentAsync per acquisire un token in modo invisibile all'utente e passa alla pagina claimsview usando il metodo Shell.Current.GoToAsync. Inoltre, viene eseguito l’override del metodo OnBackButtonPressed in modo che restituisca true, a indicare che il pulsante Indietro è disabilitato per l visualizzazione.

Pagina Aggiungi visualizzazione delle attestazioni

Nei passaggi successivi il codice viene organizzato in modo che venga definita la pagina ClaimsView. La pagina visualizzerà le attestazioni dell'utente trovate nel token ID.

  1. Nel riquadro Esplora soluzioni di Visual Studio fare clic con il pulsante destro del mouse su Visualizzazioni.

  2. Selezionare Aggiungi>Nuovo elemento....

  3. Selezionare .NET MAUI nell'elenco dei modelli.

  4. Selezionare il modello .NET MAUI ContentPage (XAML). Assegnare il nome ClaimsView.xaml al file.

  5. Selezionare Aggiungi.

  6. Il file ClaimsView.xaml verrà aperto in una nuova scheda del documento, visualizzando tutto il markup XAML che rappresenta l'interfaccia utente della pagina. Sostituire il markup XAML con il markup seguente:

    <?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>
    

    Questo codice di markup XAML rappresenta il layout dell'interfaccia utente per una visualizzazione delle attestazioni in un'app .NET MAUI. Inizia definendo ContentPage con un titolo e disabilitando il comportamento del pulsante Indietro.

    All'interno di VerticalStackLayout sono presenti diversi elementi Label che visualizzano testo statico, seguito da un ListView denominato Claims che si associa a una raccolta denominata IdTokenClaims per visualizzare le attestazioni trovate nel token ID. Viene eseguito il rendering di ogni attestazione all'interno di un ViewCell usando un DataTemplate e ogni attestazione viene visualizzata come un’Label centrato all'interno di una griglia.

    Infine, è presente un pulsante Sign Out centrato nella parte inferiore del layout, che attiva il gestore eventi SignOutButton_Clicked quando viene selezionato con il mouse.

Gestire i dati ClaimsView

Il passaggio successivo consiste nell'aggiungere il codice per gestire i dati ClaimsView.

  1. Nel riquadro Esplora soluzioni di Visual Studio espandere il file ClaimsView.xaml per visualizzare il file code-behind ClaimsView.xaml.cs. Aprire il file ClaimsView.xaml.cs e sostituire il contenuto del file con il codice seguente:

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

    Il codice ClaimsView.xaml.cs rappresenta il code-behind per una visualizzazione delle attestazioni in un'app .NET MAUI. Inizia importando gli spazi dei nomi necessari e definendo la classe ClaimsView che estende ContentPage. La proprietà IdTokenClaims è un elenco enumerabile di stringhe, inizialmente impostata su una singola stringa che indica che non sono state trovate attestazioni.

    Il costruttore ClaimsView imposta il contesto di associazione sull'istanza corrente, inizializza i componenti di visualizzazione e chiama il metodo SetViewDataAsync in modo asincrono. Il metodo SetViewDataAsync tenta di acquisire un token in modo invisibile all'utente, recupera le attestazioni dal risultato dell'autenticazione e imposta la proprietà IdTokenClaims per visualizzare le attestazioni nell'oggetto ListView denominato Claims. Se si verifica un MsalUiRequiredException, a indicare che l'interazione dell'utente è necessaria per l'autenticazione, l'app passa alla visualizzazione delle attestazioni.

    Il metodo OnBackButtonPressed esegue l'override del comportamento del pulsante Indietro per restituire sempre true, impedendo all'utente di tornare a questa visualizzazione. Il gestore eventi SignOutButton_Clicked disconnette l'utente usando l'istanza PublicClientSingleton e, al termine, passa a main view.

Modificare la shell dell'app

La classe AppShell definisce la gerarchia visiva di un'app, il markup XAML usato per creare l'interfaccia utente dell'app. Aggiornare AppShell per segnalarlo a Views.

  1. Fare doppio clic sul file AppShell.xaml nel riquadro Esplora soluzioni per aprire l'editor XAML. Sostituire il markup XAML con il codice seguente:

    <?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>
    

    Il codice XAML definisce una classe AppShell che disabilita il comportamento del riquadro a comparsa e imposta il contenuto principale su un elemento ShellContent con un titolo Home e un modello di contenuto che punta alla classe MainView.

  2. Nel riquadro Esplora soluzioni di Visual Studio espandere il file AppShell.xaml per visualizzare il file code-behind AppShell.xaml.cs. Aprire il file AppShell.xaml.cs e sostituire il contenuto del file con il codice seguente:

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

    Aggiornare il file AppShell.xaml.cs in modo da includere le registrazioni di route necessarie per MainView e ClaimsView. La chiamata del metodo InitializeComponent() permette di assicurarsi che la classe AppShell venga inizializzata. Il metodo RegisterRoute() associa le route mainview e claimsview ai rispettivi tipi di visualizzazione, MainView e ClaimsView.

Aggiungere codice specifico per la piattaforma

Un progetto di app .NET MAUI contiene una cartella Platforms, in cui ogni cartella figlio rappresenta una piattaforma in cui è possibile eseguire .NET MAUI. Per fornire un comportamento specifico per l’applicazione in supplemento alla classe Application predefinita, è necessario modificare Platforms/Windows/App.xaml.cs.

Sostituire il contenuto del file con il codice seguente:

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

Nel codice, è necessario configurare l'URI di reindirizzamento per l'applicazione e inizializzare MSAL e quindi impostare la finestra padre per l'applicazione. Inoltre, è necessario eseguire l'override del metodo OnLaunched per gestire l'evento di avvio e recuperare l'handle della finestra padre.

Aggiungere le impostazioni dell'app

Le impostazioni consentono la separazione dei dati che configurano il comportamento di un'app dal codice, consentendo la modifica del comportamento senza ricompilare l'app. MauiAppBuilder fornisce ConfigurationManager per la configurazione delle impostazioni nell'app .NET MAUI. Aggiungere il file appsettings.json come EmbeddedResource.

Per creare appsettings.json, seguire questa procedura:

  1. Nel riquadro Esplora soluzioni di Visual Studio, fare clic con il pulsante destro del mouse sul progetto SignInMaui>Aggiungi>Nuovo elemento....

  2. Selezionare Web>File di configurazione JSON per JavaScript. Denominare il file appsettings.json.

  3. Selezionare Aggiungi.

  4. Selezionare appsettings.json

  5. Nel riquadro Proprietà impostare Operazione di compilazione su Risorsa incorporata.

  6. Nel riquadro Proprietà impostare Copia in directory di output su Copia sempre.

  7. Sostituire il contenuto del file appsettings.jsoncon il codice seguente:

    {
      "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. In appsettings.json trovare il segnaposto:

    1. Enter_the_Tenant_Subdomain_Here e sostituirlo con il sottodominio della directory (tenant). Ad esempio, se il dominio primario del tenant è contoso.onmicrosoft.com, usare contoso. Se non si ha il nome del tenant, vedere come leggere i dettagli del tenant.
    2. Enter_the_Application_Id_Here e sostituirlo con l'ID applicazione (client) dell’app registrato in precedenza.

Usare un dominio URL personalizzato (facoltativo)

Usare un dominio personalizzato per personalizzare completamente l'URL di autenticazione. Dal punto di vista dell'utente, gli utenti rimangono nel dominio durante il processo di autenticazione, anziché essere reindirizzati a ciamlogin.com nome di dominio.

Per usare un dominio personalizzato, seguire questa procedura:

  1. Usare la procedura descritta in Abilitare domini URL personalizzati per le app nei tenant esterni per abilitare il dominio URL personalizzato per il tenant esterno.

  2. Aprire il file appsettings.json.

    1. Aggiornare il valore della proprietà da Authority a https://Enter_the_Custom_Domain_Here/Enter_the_Tenant_ID_Here. Sostituire Enter_the_Custom_Domain_Here con il dominio URL personalizzato e Enter_the_Tenant_ID_Here con l'ID tenant. Se non si ha l’ID del tenant, vedere come leggere i dettagli del tenant.
    2. Aggiungere una proprietà knownAuthorities con un valore [Enter_the_Custom_Domain_Here].

Dopo aver apportato le modifiche al file appsettings.json, se il dominio URL personalizzato è login.contoso.com e l'ID tenant è aaaabbbbbb-0000-cccc-1111-dddd2222eee, allora il file sarà simile al frammento di codice seguente:

{
  "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"
  }
}

Eseguire e testare l'app desktop .NET MAUI

Le app .NET MAUI sono progettate per essere eseguite in più sistemi operativi e dispositivi. È necessario selezionare la destinazione che si desidera usare per testare ed eseguire il debug dell'app.

Impostare la destinazione di debug nella barra degli strumenti di Visual Studio sul dispositivo con cui si vuole eseguire il debug e il test. I passaggi seguenti mostrano come impostare la destinazione di debug su Windows:

  1. Selezionare l’elenco a discesa Destinazione di debug.
  2. Selezionare Framework
  3. Selezionare net7.0-windows...

Eseguire l'app premendo F5 o selezionando il pulsante di riproduzione nella parte superiore di Visual Studio.

  1. È ora possibile testare l'applicazione desktop .NET MAUI di esempio. Dopo aver eseguito l'applicazione, viene automaticamente visualizzata la finestra dell'applicazione desktop:

    Screenshot del pulsante di accesso nell'applicazione desktop

  2. Nella finestra desktop visualizzata, selezionare il pulsante Accedi. Si apre una finestra del browser e viene richiesto di eseguire l'accesso.

    Screenshot che mostra la richiesta di immettere le credenziali nell'applicazione desktop.

    Durante il processo di accesso viene richiesto di concedere varie autorizzazioni (per consentire all'applicazione di accedere ai dati dell’utente). Al termine dell'accesso e del consenso, la schermata dell'applicazione visualizza la pagina principale.

    Screenshot della pagina principale nell'applicazione desktop, dopo l'accesso.

Passaggio successivo