Tutorial: Entrar em usuários no aplicativo shell .NET MAUI usando um locatário externo
Este tutorial é a parte final de uma série que demonstra como criar um aplicativo shell .NET Multi-platform App UI (.NET MAUI) e prepará-lo para autenticação usando o centro de administração do Microsoft Entra. Na Parte 2 desta série , você adicionou um auxiliar de cliente personalizado da Microsoft Authentication Library (MSAL) para inicializar o SDK do MSAL, instalar as bibliotecas necessárias e incluir um recurso de imagem. Esta etapa final demonstra como adicionar código de entrada e saída no .NET MAUI e executar o aplicativo shell na plataforma Android.
Neste tutorial, você:
- Adicione o código de entrada e saída.
- Modifique o Shell do aplicativo.
- Adicione código específico da plataforma.
- Adicione as configurações do aplicativo.
- Execute e teste o aplicativo shell .NET MAUI.
Pré-requisitos
Adicionar código de entrada e saída
A interface do usuário (UI) de um aplicativo .NET MAUI é construída de objetos que mapeiam para os controles nativos de cada plataforma de destino. Os principais grupos de controle usados para criar a interface do usuário de um aplicativo .NET MAUI são páginas, layouts e modos de exibição.
Adicionar página de visualização principal
Os próximos passos irão organizar o nosso código para que o main view
seja definido.
Exclua MainPage.xaml e MainPage.xaml.cs do seu projeto, eles não são mais necessários. No painel Gerenciador de Soluções, localize a entrada para MainPage.xaml, clique com o botão direito do mouse nela e selecione Excluir.
Clique com o botão direito do mouse no projeto SignInMaui e selecione Adicionar>nova pasta. Nomeie a pasta como Views.
Clique com o botão direito do rato nas Vistas.
Selecione Adicionar>novo item....
Selecione .NET MAUI na lista de modelos.
Selecione o modelo .NET MAUI ContentPage (XAML). Nomeie o arquivo MainView.xaml.
Selecione Adicionar.
O arquivo MainView.xaml será aberto em uma nova guia de documento, exibindo toda a marcação XAML que representa a interface do usuário da página. Substitua a marcação XAML pela seguinte marcação:
<?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 o ficheiro.
Vamos detalhar as principais partes dos controles XAML colocados na página:
<ContentPage>
é o objeto raiz da classe MainView.<VerticalStackLayout>
é o objeto filho da ContentPage. Este controle de layout organiza seus filhos verticalmente, um após o outro.<Image>
Exibe uma imagem, neste caso está usando o Azureative_directory.png_ que você baixou anteriormente.<Label>
controles exibem texto.<Button>
pode ser pressionado pelo usuário, o que gera oClicked
evento. Você pode executar oClicked
código em resposta ao evento.Clicked="OnSignInClicked"
OClicked
evento do botão é atribuído aoOnSignInClicked
manipulador de eventos, que será definido no arquivo code-behind. Você criará esse código na próxima etapa.
Manipular o evento OnSignInClicked
O próximo passo é adicionar o código para o evento do Clicked
botão.
No painel Gerenciador de Soluções do Visual Studio, expanda o arquivo MainView.xaml para revelar seu arquivo code-behind MainView.xaml.cs. Abra o MainView.xaml.cs e substitua o conteúdo do arquivo pelo seguinte 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; } } }
A
MainView
classe é uma página de conteúdo responsável por exibir a visualização principal do aplicativo. No construtor, ele recupera a conta de usuário armazenada em cache usando oMSALClientHelper
da instância e habilita o botão de entrada, se nenhuma conta dePublicClientSingleton
usuário armazenada em cache for encontrada.Quando o botão de entrada é clicado, ele chama o
AcquireTokenSilentAsync
método para adquirir um token silenciosamente e navega para aclaimsview
página usando oShell.Current.GoToAsync
método. Além disso, oOnBackButtonPressed
método é substituído para retornar true, indicando que o botão Voltar está desativado para essa exibição.
Adicionar página de exibição de declarações
As próximas etapas organizarão o código para que ClaimsView
a página seja definida. A página exibirá as declarações do usuário encontradas no token de ID.
No painel Gerenciador de Soluções do Visual Studio, clique com o botão direito do mouse em Modos de Exibição.
Selecione Adicionar>novo item....
Selecione .NET MAUI na lista de modelos.
Selecione o modelo .NET MAUI ContentPage (XAML). Nomeie o arquivo ClaimsView.xaml.
Selecione Adicionar.
O arquivo ClaimsView.xaml será aberto em uma nova guia de documento, exibindo toda a marcação XAML que representa a interface do usuário da página. Substitua a marcação XAML pela seguinte marcação:
<?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>
Esse código de marcação XAML representa o layout da interface do usuário para uma exibição de declaração em um aplicativo .NET MAUI. Começa por definir o
ContentPage
com um título e desativar o comportamento do botão Voltar.Dentro de um
VerticalStackLayout
, há váriosLabel
elementos exibindo texto estático, seguido por umListView
nomeClaims
que se liga a uma coleção chamadaIdTokenClaims
para exibir as declarações encontradas no token de ID. Cada declaração é renderizada dentro de umViewCell
usando aDataTemplate
e exibida como centralizadaLabel
dentro de uma Grade.Por fim, há um
Sign Out
botão centralizado na parte inferior do layout, que aciona oSignOutButton_Clicked
manipulador de eventos quando clicado.
Manipular os dados ClaimsView
A próxima etapa é adicionar o código para lidar com ClaimsView
dados.
No painel Gerenciador de Soluções do Visual Studio, expanda o arquivo ClaimsView.xaml para revelar seu arquivo code-behind ClaimsView.xaml.cs. Abra o ClaimsView.xaml.cs e substitua o conteúdo do arquivo pelo seguinte 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"); } }
O código ClaimsView.xaml.cs representa o code-behind para uma exibição de declaração em um aplicativo .NET MAUI. Ele começa importando os namespaces necessários e definindo a
ClaimsView
classe, que se estendeContentPage
. AIdTokenClaims
propriedade é um enumerável de cadeias de caracteres, inicialmente definido como uma única cadeia de caracteres indicando nenhuma declaração encontrada.O
ClaimsView
construtor define o contexto de ligação para a instância atual, inicializa os componentes de exibição e chama oSetViewDataAsync
método de forma assíncrona. OSetViewDataAsync
método tenta adquirir um token silenciosamente, recupera as declarações do resultado da autenticação e define aIdTokenClaims
propriedade para exibi-las noListView
nomeClaims
. Se ocorrerMsalUiRequiredException
, indicando que a interação do usuário é necessária para autenticação, o aplicativo navegará para a exibição de declarações.O
OnBackButtonPressed
método substitui o comportamento do botão Voltar para sempre retornar true, impedindo que o usuário volte dessa exibição. OSignOutButton_Clicked
manipulador de eventos desconecta o usuário usando a instância e, após aPublicClientSingleton
conclusão, navega até omain view
.
Modificar o Shell do aplicativo
A AppShell
classe define a hierarquia visual de um aplicativo, a marcação XAML usada na criação da interface do usuário do aplicativo. Atualize o AppShell
para informá-lo sobre o Views
.
Clique duas vezes no
AppShell.xaml
arquivo no painel Gerenciador de Soluções para abrir o editor XAML. Substitua a marcação XAML pelo seguinte 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>
O código XAML define uma
AppShell
classe que desabilita o comportamento de submenu e define o conteúdo principal como umShellContent
elemento com um títuloHome
e um modelo de conteúdo apontando para aMainView
classe.No painel Gerenciador de Soluções do Visual Studio, expanda o arquivo AppShell.xaml para revelar seu arquivo code-behind AppShell.xaml.cs. Abra o AppShell.xaml.cs e substitua o conteúdo do arquivo pelo seguinte 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)); } }
Você atualiza o
AppShell.xaml.cs
arquivo para incluir os registros de rota necessários para oMainView
eClaimsView
. Ao chamar oInitializeComponent()
método, você garante aAppShell
inicialização da classe. ORegisterRoute()
método associa as rotas eclaimsview
commainview
seus respetivos tiposMainView
de exibição eClaimsView
.
Adicionar código específico da plataforma
Um projeto de aplicativo .NET MAUI contém uma pasta Plataformas, com cada pasta filho representando uma plataforma que o .NET MAUI pode segmentar. Para fornecer comportamento específico do aplicativo Android para complementar a classe de aplicativo padrão, siga estas etapas:
Clique duas vezes
Platforms/Android/AndroidManifest.xml
no arquivo no painel Gerenciador de Soluções para abrir o editor XML. Atualize as seguintes propriedades:- Defina Nome do aplicativo como MAUI CIAM.
- Defina o nome do pacote como SignInMaui.Droid.
- Defina a versão mínima do Android para Android 5.0 (nível de API 21).
Clique duas vezes
Platforms/Android/MainActivity.cs
no arquivo no painel Gerenciador de Soluções para abrir o editor csharp. Substitua o conteúdo do arquivo pelo seguinte código:// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. using Android.App; using Android.Content; using Android.Content.PM; using Android.OS; using SignInMaui.MSALClient; using Microsoft.Identity.Client; namespace SignInMaui; [Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)] public class MainActivity : MauiAppCompatActivity { protected override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); // configure platform specific params PlatformConfig.Instance.RedirectUri = $"msal{PublicClientSingleton.Instance.MSALClientHelper.AzureAdConfig.ClientId}://auth"; PlatformConfig.Instance.ParentWindow = this; // Initialize MSAL and platformConfig is set _ = Task.Run(async () => await PublicClientSingleton.Instance.MSALClientHelper.InitializePublicClientAppAsync()).Result; } protected override void OnActivityResult(int requestCode, Result resultCode, Intent data) { base.OnActivityResult(requestCode, resultCode, data); AuthenticationContinuationHelper.SetAuthenticationContinuationEventArgs(requestCode, resultCode, data); } }
Vamos detalhar as principais partes do código que você adicionou:
- As declarações necessárias
using
estão incluídas no topo. - A
MainActivity
classe é definida, herdando deMauiAppCompatActivity
, que é a classe base para a plataforma Android no .NET MAUI. - O atributo [Activity] é aplicado à
MainActivity
classe, especificando várias configurações para a atividade do Android.Theme = "@style/Maui.SplashTheme"
define o tema splash para a atividade.MainLauncher = true
designa esta atividade como o principal ponto de entrada da aplicação.ConfigurationChanges
especifica as alterações de configuração que a atividade pode manipular, como tamanho da tela, orientação, modo da interface do usuário, layout da tela, menor tamanho da tela e densidade.
OnCreate
método é substituído para fornecer lógica personalizada quando a atividade está sendo criada.base.OnCreate(savedInstanceState)
chama a implementação base do método.PlatformConfig.Instance.RedirectUri
é definido como um valor gerado dinamicamente com base emPublicClientSingleton.Instance.MSALClientHelper.AzureAdConfig.ClientId
. Ele configura o URI de redirecionamento para o cliente MSAL.PlatformConfig.Instance.ParentWindow
é definido como a instância de atividade atual, que especifica a janela pai para operações relacionadas à autenticação.PublicClientSingleton.Instance.MSALClientHelper.InitializePublicClientAppAsync()
inicializa o aplicativo cliente MSAL de forma assíncrona usando um método auxiliar de uma instância singleton chamadaMSALClientHelper
. OTask.Run
é usado para executar a inicialização em um thread em segundo plano e.Result
é usado para aguardar de forma síncrona a conclusão da tarefa.
OnActivityResult
método é substituído para manipular o resultado de uma atividade iniciada pela atividade atual.base.OnActivityResult(requestCode, resultCode, data)
chama a implementação base do método.AuthenticationContinuationHelper.SetAuthenticationContinuationEventArgs(requestCode, resultCode, data)
Define os argumentos do evento de continuação de autenticação com base no código de solicitação recebido, no código de resultado e nos dados de intenção. Isso é usado para continuar o fluxo de autenticação depois que uma atividade externa retorna um resultado.
- As declarações necessárias
No painel Gerenciador de Soluções do Visual Studio, selecione Plataformas.
Clique com o botão direito do rato na pasta> Android Adicionar>Novo Item....
Selecione Classe de itens>C#. Dê o nome
MsalActivity.cs
ao ficheiro.Substitua o conteúdo do
MsalActivity.cs
arquivo pelo seguinte código:// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. using System; using System.Collections.Generic; using System.Linq; using System.Text; using Android.App; using Android.Content; using Android.OS; using Android.Runtime; using Android.Views; using Android.Widget; using Microsoft.Identity.Client; namespace MauiAppBasic.Platforms.Android.Resources { [Activity(Exported =true)] [IntentFilter(new[] { Intent.ActionView }, Categories = new[] { Intent.CategoryBrowsable, Intent.CategoryDefault }, DataHost = "auth", DataScheme = "msalEnter_the_Application_Id_Here")] public class MsalActivity : BrowserTabActivity { } }
Vamos detalhar as principais partes do código que você adicionou:
MsalActivity
class é declarada dentro doMauiAppBasic.Platforms.Android.Resources
namespace. A classe herda daBrowserTabActivity
classe, indicando que ela estende sua funcionalidade.- A classe é decorada com o atributo, o
[Activity(Exported = true)]
que significa que a atividade é exportada e pode ser acessada por outros métodos. - Um filtro de intenção é especificado usando o atributo "[IntentFilter(...)]". Ele configura a atividade para intercetar a
ActionView
intenção. - O filtro de intenção é definido para manipular a
ActionView
intenção com o especificadoDataScheme
(msalEnter_the_Application_Id_Here
) eDataHost
("auth"). Essa configuração permite que a atividade manipule o processo de autenticação intercetando e processando aActionView
intenção. SubstituaEnter_the_Application_Id_Here
pelo ID do aplicativo (cliente) do aplicativo que você registrou anteriormente.
Adicionar configurações do aplicativo
As configurações permitem a separação de dados que configuram o comportamento de um aplicativo do código, permitindo que o comportamento seja alterado sem reconstruir o aplicativo. O MauiAppBuilder
fornece ConfigurationManager
para definir as configurações em nosso aplicativo .NET MAUI. Vamos adicionar o appsettings.json
arquivo como um EmbeddedResource
arquivo .
Para criar appsettings.json
o , siga estes passos:
No painel Gerenciador de Soluções do Visual Studio, clique com o botão direito do mouse no projeto> SignInMaui Adicionar>Novo Item....
Selecione Arquivo de configuração JSON JavaScript da Web>. Dê o nome
appsettings.json
ao ficheiro.Selecione Adicionar.
Selecione appsettings.json
No painel Propriedades, defina Build Action como Embedded resource.
No painel Propriedades, defina Copiar para Diretório de Saída como Copiar sempre.
Substitua o conteúdo do
appsettings.json
arquivo pelo seguinte 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" } }
No , localize o
appsettings.json
espaço reservado:Enter_the_Tenant_Subdomain_Here
e substitua-o pelo subdomínio Directory (locatário). Por exemplo, se o domínio principal do locatário forcontoso.onmicrosoft.com
, usecontoso
. Se não tiver o nome do inquilino, saiba como ler os detalhes do inquilino.Enter_the_Application_Id_Here
e substitua-o pelo ID do aplicativo (cliente) do aplicativo que você registrou anteriormente.
Usar domínio de URL personalizado (opcional)
Use um domínio personalizado para marcar totalmente a URL de autenticação. Do ponto de vista do usuário, os usuários permanecem no seu domínio durante o processo de autenticação, em vez de serem redirecionados para ciamlogin.com nome de domínio.
Siga estas etapas para usar um domínio personalizado:
Use as etapas em Habilitar domínios de URL personalizados para aplicativos em locatários externos para habilitar o domínio de URL personalizado para seu locatário externo.
Abra appsettings.json arquivo:
- Atualize o
Authority
valor da propriedade para https://Enter_the_Custom_Domain_Here/Enter_the_Tenant_ID_Here. SubstituaEnter_the_Custom_Domain_Here
pelo seu domínio de URL personalizado eEnter_the_Tenant_ID_Here
pelo seu ID de inquilino. Se não tiver o ID do inquilino, saiba como ler os detalhes do inquilino. - Adicionar
knownAuthorities
propriedade com um valor [Enter_the_Custom_Domain_Here].
- Atualize o
Depois de fazer as alterações no arquivo appsettings.json, se o domínio de URL personalizado estiver login.contoso.com e o ID do locatário for aaaabbbb-0000-cccc-1111-dddd2222eeee, o arquivo deverá ser semelhante ao seguinte trecho:
{
"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"
}
}
Executar e testar o aplicativo móvel .NET MAUI
Os aplicativos .NET MAUI são projetados para serem executados em vários sistemas operacionais e dispositivos. Você precisará selecionar com qual destino deseja testar e depurar seu aplicativo.
Defina o destino de depuração na barra de ferramentas do Visual Studio para o dispositivo com o qual você deseja depurar e testar. As etapas a seguir demonstram a configuração do destino de depuração para Android:
- Selecione a lista suspensa Depurar destino .
- Selecione Emuladores Android.
- Selecione o dispositivo do emulador.
Execute o aplicativo pressionando F5 ou selecione o botão de reprodução na parte superior do Visual Studio.
Agora você pode testar o aplicativo .NET MAUI Android de exemplo. Depois de executar o aplicativo, a janela do aplicativo Android aparece em um emulador:
Na janela do Android exibida, selecione o botão Entrar . Abre-se uma janela do browser e ser-lhe-á pedido para iniciar sessão.
Durante o processo de início de sessão, ser-lhe-á pedido que conceda várias permissões (para permitir que a aplicação aceda aos seus dados). Após o login e consentimento bem-sucedidos, a tela do aplicativo exibe a página principal.