Partilhar via


Adicionar autenticação ao seu aplicativo .NET MAUI

Observação

Este produto foi retirado. Para obter uma substituição para projetos que usam o .NET 8 ou posterior, consulte a biblioteca Community Toolkit Datasync.

Neste tutorial, você adiciona a autenticação da Microsoft ao projeto TodoApp usando a ID do Microsoft Entra. Antes de concluir este tutorial, verifique se você criou o projeto e implantou o back-end.

Dica

Embora usemos a ID do Microsoft Entra para autenticação, você pode usar qualquer biblioteca de autenticação que desejar com os Aplicativos Móveis do Azure.

Adicionar autenticação ao seu serviço de back-end

Seu serviço de back-end é um serviço padrão ASP.NET 6. Qualquer tutorial que mostre como habilitar a autenticação para um serviço do ASP.NET 6 funciona com os Aplicativos Móveis do Azure.

Para habilitar a autenticação do Microsoft Entra para seu serviço de back-end, você precisa:

  • Registe uma aplicação com o Microsoft Entra ID.
  • Adicione a verificação de autenticação ao projeto de back-end do ASP.NET 6.

Registar a candidatura

Primeiro, registre a API da Web em seu locatário do Microsoft Entra e adicione um escopo seguindo estas etapas:

  1. Entre no portal do Azure.

  2. Se você tiver acesso a vários locatários, use o filtro Diretórios + assinaturas no menu superior para alternar para o locatário no qual deseja registrar o aplicativo.

  3. Procure e selecione Microsoft Entra ID.

  4. Em Gerir, selecione Registos de aplicações>Novo registo.

    • Nome: introduza um nome para a sua candidatura; por exemplo, TodoApp Quickstart. Os usuários do seu aplicativo verão esse nome. Você pode alterá-lo mais tarde.
    • Tipos de conta suportados: Contas em qualquer diretório organizacional (Qualquer diretório Microsoft Entra - Multilocatário) e contas pessoais da Microsoft (por exemplo, Skype, Xbox)
  5. Selecione Registrar.

  6. Em Gerenciar, selecione Expor uma API>Adicionar um escopo.

  7. Para URI de ID do Aplicativo, aceite o padrão selecionando Salvar e continuar.

  8. Insira os seguintes detalhes:

    • Nome do escopo: access_as_user
    • Quem pode consentir?: Administradores e usuários
    • Nome de exibição do consentimento do administrador: Access TodoApp
    • Descrição do consentimento do administrador: Allows the app to access TodoApp as the signed-in user.
    • Nome de exibição do consentimento do usuário: Access TodoApp
    • Descrição do consentimento do utilizador: Allow the app to access TodoApp on your behalf.
    • State: Enabled
  9. Selecione Adicionar de escopo para concluir a adição de escopo.

  10. Observe o valor do escopo, semelhante ao (conhecido comode Escopo da API Web ). Você precisa do escopo ao configurar o cliente.

  11. Selecione Visão geral.

  12. Observe a de ID do Aplicativo (cliente) na seção do Essentials (referida comode ID do Aplicativo da API Web ). Você precisa desse valor para configurar o serviço de back-end.

Abra o Visual Studio e selecione o projeto TodoAppService.NET6.

  1. Clique com o botão direito do mouse no projeto TodoAppService.NET6 e selecione Gerenciar pacotes NuGet....

  2. No novo separador, selecione Procurare, em seguida, introduza Microsoft.Identity.Web na caixa de pesquisa.

    Captura de tela da adição do M S A L NuGet no Visual Studio.

  3. Selecione o pacote Microsoft.Identity.Web e pressione Instalar.

  4. Siga as instruções para concluir a instalação do pacote.

  5. Abra Program.cs. Adicione o seguinte à lista de using instruções:

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Identity.Web;
  1. Adicione o seguinte código diretamente acima da chamada para builder.Services.AddDbContext():
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
  .AddMicrosoftIdentityWebApi(builder.Configuration);
builder.Services.AddAuthorization();
  1. Adicione o seguinte código diretamente acima da chamada para app.MapControllers():
app.UseAuthentication();
app.UseAuthorization();

O seu Program.cs deve agora ter o seguinte aspeto:

using Microsoft.AspNetCore.Datasync;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Identity.Web;
using TodoAppService.NET6.Db;
  
var builder = WebApplication.CreateBuilder(args);
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
  
if (connectionString == null)
{
  throw new ApplicationException("DefaultConnection is not set");
}
  
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
  .AddMicrosoftIdentityWebApi(builder.Configuration);
builder.Services.AddAuthorization();
builder.Services.AddDbContext<AppDbContext>(options => options.UseSqlServer(connectionString));
builder.Services.AddDatasyncControllers();
  
var app = builder.Build();
  
// Initialize the database
using (var scope = app.Services.CreateScope())
{
  var context = scope.ServiceProvider.GetRequiredService<AppDbContext>();
  await context.InitializeDatabaseAsync().ConfigureAwait(false);
}
  
// Configure and run the web service.
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
  1. Edite o Controllers\TodoItemController.cs. Adicione um atributo [Authorize] à classe. Sua classe deve ter esta aparência:
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Datasync;
using Microsoft.AspNetCore.Datasync.EFCore;
using Microsoft.AspNetCore.Mvc;
using TodoAppService.NET6.Db;

namespace TodoAppService.NET6.Controllers
{
  [Authorize]
  [Route("tables/todoitem")]
  public class TodoItemController : TableController<TodoItem>
  {
    public TodoItemController(AppDbContext context)
      : base(new EntityTableRepository<TodoItem>(context))
    {
    }
  }
}
  1. Edite o appsettings.json. Adicione o seguinte bloco:
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com",
    "ClientId": "<client-id>",
    "TenantId": "common"
  },

Substitua o pelo de ID do Aplicativo de API Web que você registrou anteriormente. Uma vez concluído, deve ter esta aparência:

{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com",
    "ClientId": "<client-id>",
    "TenantId": "common"
  },
  "ConnectionStrings": {
    "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=TodoApp;Trusted_Connection=True"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*"
}

Publique seu serviço no Azure novamente:

  1. Clique com o botão direito do rato no projeto TodoAppService.NET6 e, em seguida, selecione Publicar....
  2. Selecione o botão Publicar no canto superior direito da guia.

Abra um navegador para https://yoursite.azurewebsites.net/tables/todoitem?ZUMO-API-VERSION=3.0.0. Observe que o serviço agora retorna uma resposta 401, que indica que a autenticação é necessária.

Captura de ecrã do navegador a mostrar um erro.

Registrar seu aplicativo com o serviço de identidade

O Microsoft Data sync Framework tem suporte interno para qualquer provedor de autenticação que usa um Json Web Token (JWT) dentro de um cabeçalho da transação HTTP. Este aplicativo usa o Microsoft Authentication Library (MSAL) para solicitar esse token e autorizar o usuário conectado ao serviço de back-end.

Configurar um aplicativo cliente nativo

Você pode registrar clientes nativos para permitir a autenticação em APIs da Web hospedadas em seu aplicativo usando uma biblioteca de cliente, como a Microsoft Identity Library (MSAL).

  1. No portal do Azure, selecione Registros de aplicativo>ID do Microsoft Entra>Novo registro.

  2. Na página Registar uma candidatura:

    • introduza um Nome para o registo da sua aplicação. Você pode usar o nome native-quickstart para distinguir este do usado pelo seu serviço de back-end.
    • Selecione Contas em qualquer diretório organizacional (Qualquer diretório Microsoft Entra - Multilocatário) e contas pessoais da Microsoft (por exemplo, Skype, Xbox).
    • No URI de redirecionamento:
      • Selecione cliente público (móvel & desktop)
      • Introduza o URL quickstart://auth
  3. Selecione Registrar.

  4. Selecione permissões de API>Adicionar uma permissão>Minhas APIs.

  5. Selecione o registro do aplicativo que você criou anteriormente para seu serviço de back-end. Se não vir o registo da aplicação, certifique-se de que adicionou o access_as_user âmbito.

    Captura de ecrã do registo de âmbito no portal do Azure.

  6. Em Selecionar permissões, selecione access_as_usere, em seguida, selecione Adicionar permissões.

  7. Selecione Autenticação>aplicativos móveis e de desktop.

  8. Marque a caixa ao lado de https://login.microsoftonline.com/common/oauth2/nativeclient.

  9. Marque a caixa ao lado de msal{client-id}://auth (substituindo {client-id} pelo ID do aplicativo).

  10. Selecione Adicionarde URI e, em seguida, adicione http://localhost no campo para URIs extras.

  11. Selecione Salvar na parte inferior da página.

  12. Selecione Visão geral. Anote o de ID do Aplicativo (cliente) (conhecido comode ID do Aplicativo Native Client) conforme você precisa dele para configurar o aplicativo móvel.

Definimos três URLs de redirecionamento:

  • http://localhost é usado por aplicativos WPF.
  • https://login.microsoftonline.com/common/oauth2/nativeclient é usado por aplicativos UWP.
  • msal{client-id}://auth é utilizado por aplicações móveis (Android e iOS).

Adicionar o Microsoft Identity Client ao seu aplicativo

Abra a solução TodoApp.sln no Visual Studio e defina o projeto TodoApp.MAUI como o projeto de inicialização. Adicione o Microsoft Identity Library (MSAL) ao projeto :

Adicione o Microsoft Identity Library (MSAL) ao projeto de plataforma:

  1. Clique com o botão direito do mouse no projeto e selecione Gerenciar pacotes NuGet....

  2. Selecione a guia Procurar.

  3. Introduza Microsoft.Identity.Client na caixa de pesquisa e, em seguida, prima Enter.

  4. Selecione o Microsoft.Identity.Client resultado e, em seguida, clique em Instalar.

    Captura de tela da seleção do MSAL NuGet no Visual Studio.

  5. Aceite o contrato de licença para continuar a instalação.

Adicione o ID do cliente nativo e o escopo do back-end à configuração.

Abra o projeto TodoApp.Data e edite o arquivo Constants.cs. Adicione constantes para ApplicationId e Scopes:

  public static class Constants
  {
      /// <summary>
      /// The base URI for the Datasync service.
      /// </summary>
      public static string ServiceUri = "https://demo-datasync-quickstart.azurewebsites.net";

      /// <summary>
      /// The application (client) ID for the native app within Microsoft Entra ID
      /// </summary>
      public static string ApplicationId = "<client-id>";

      /// <summary>
      /// The list of scopes to request
      /// </summary>
      public static string[] Scopes = new[]
      {
          "<scope>"
      };
  }

Substitua o <client-id> pelo Native Client Application ID você recebeu ao registrar o aplicativo cliente no Microsoft Entra ID e o <scope> pelo Web API Scope que você copiou quando usou Expose an API ao registrar o aplicativo de serviço.

Abra a classe MainPage.xaml.cs no projeto TodoApp.MAUI. Adicione as seguintes using instruções:

using Microsoft.Datasync.Client;
using Microsoft.Identity.Client;
using System.Diagnostics;

Na classe MainPage, adicione uma nova propriedade:

public IPublicClientApplication IdentityClient { get; set; }

Ajuste o construtor para ler:

public MainPage()
{
    InitializeComponent();
    TodoService = new RemoteTodoService(GetAuthenticationToken);
    viewModel = new MainViewModel(this, TodoService);
    BindingContext = viewModel;
}

Adicione o método GetAuthenticationToken à classe:

public async Task<AuthenticationToken> GetAuthenticationToken()
{
    if (IdentityClient == null)
    {
#if ANDROID
        IdentityClient = PublicClientApplicationBuilder
            .Create(Constants.ApplicationId)
            .WithAuthority(AzureCloudInstance.AzurePublic, "common")
            .WithRedirectUri($"msal{Constants.ApplicationId}://auth")
            .WithParentActivityOrWindow(() => Platform.CurrentActivity)
            .Build();
#elif IOS
        IdentityClient = PublicClientApplicationBuilder
            .Create(Constants.ApplicationId)
            .WithAuthority(AzureCloudInstance.AzurePublic, "common")
            .WithIosKeychainSecurityGroup("com.microsoft.adalcache")
            .WithRedirectUri($"msal{Constants.ApplicationId}://auth")
            .Build();
#else
        IdentityClient = PublicClientApplicationBuilder
            .Create(Constants.ApplicationId)
            .WithAuthority(AzureCloudInstance.AzurePublic, "common")
            .WithRedirectUri("https://login.microsoftonline.com/common/oauth2/nativeclient")
            .Build();
#endif
    }

    var accounts = await IdentityClient.GetAccountsAsync();
    AuthenticationResult result = null;
    bool tryInteractiveLogin = false;

    try
    {
        result = await IdentityClient
            .AcquireTokenSilent(Constants.Scopes, accounts.FirstOrDefault())
            .ExecuteAsync();
    }
    catch (MsalUiRequiredException)
    {
        tryInteractiveLogin = true;
    }
    catch (Exception ex)
    {
        Debug.WriteLine($"MSAL Silent Error: {ex.Message}");
    }

    if (tryInteractiveLogin)
    {
        try
        {
            result = await IdentityClient
                .AcquireTokenInteractive(Constants.Scopes)
                .ExecuteAsync();
        }
        catch (Exception ex)
        {
            Debug.WriteLine($"MSAL Interactive Error: {ex.Message}");
        }
    }

    return new AuthenticationToken
    {
        DisplayName = result?.Account?.Username ?? "",
        ExpiresOn = result?.ExpiresOn ?? DateTimeOffset.MinValue,
        Token = result?.AccessToken ?? "",
        UserId = result?.Account?.Username ?? ""
    };
}

O método GetAuthenticationToken() funciona com o Microsoft Identity Library (MSAL) para obter um token de acesso adequado para autorizar o usuário conectado ao serviço de back-end. Esta função é então passada para o RemoteTodoService de criação do cliente. Se a autenticação for bem-sucedida, o AuthenticationToken é produzido com os dados necessários para autorizar cada solicitação. Se não, então um token incorreto expirado é produzido em vez disso.

Podemos adicionar quaisquer opções específicas da plataforma usando as áreas #if com um especificador de plataforma. Por exemplo, o Android exige que especifiquemos a atividade pai, que é passada da página de chamada.

Configurar o aplicativo Android para autenticação

Crie um novo Platforms\Android\MsalActivity.cs de classe com o seguinte código:

using Android.App;
using Android.Content;
using Microsoft.Identity.Client;

namespace TodoApp.MAUI
{
    [Activity(Exported = true)]
    [IntentFilter(new[] { Intent.ActionView },
        Categories = new[] { Intent.CategoryBrowsable, Intent.CategoryDefault },
        DataHost = "auth",
        DataScheme = "msal{client-id}")]
    public class MsalActivity : BrowserTabActivity
    {
    }
}

Substitua {client-id} pelo ID do aplicativo do cliente nativo (que é o mesmo que Constants.ApplicationId).

Se o seu projeto se destina ao Android versão 11 (API versão 30) ou posterior, você deve atualizar seu AndroidManifest.xml para atender aos requisitos de visibilidade do pacote Android. Abra o Platforms/Android/AndroidManifest.xml e adicione os seguintes nós de queries/intent ao nó manifest:

<manifest>
  ...
  <queries>
    <intent>
      <action android:name="android.support.customtabs.action.CustomTabsService" />
    </intent>
  </queries>
</manifest>

Abra MauiProgram.cs. Inclua as seguintes instruções using na parte superior do arquivo:

using Microsoft.Identity.Client;

Atualize o construtor para o seguinte código:

    builder
        .UseMauiApp<App>()
        .ConfigureLifecycleEvents(events =>
        {
#if ANDROID
            events.AddAndroid(platform =>
            {
                platform.OnActivityResult((activity, rc, result, data) =>
                {
                    AuthenticationContinuationHelper.SetAuthenticationContinuationEventArgs(rc, result, data);
                });
            });
#endif
        })
        .ConfigureFonts(fonts =>
        {
            fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
            fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
        });

Se você estiver fazendo esta etapa depois de atualizar o aplicativo para iOS, adicione o código designado pelo #if ANDROID (incluindo o #if e #endif). O compilador escolhe a parte correta do código com base na plataforma que está sendo compilada. Este código pode ser colocado antes ou depois do bloco existente para iOS.

Quando o Android requer autenticação, ele obtém um cliente de identidade e, em seguida, alterna para uma atividade interna que abre o navegador do sistema. Quando a autenticação estiver concluída, o navegador do sistema redireciona para o URL de redirecionamento definido (msal{client-id}://auth). O MsalActivity interceta a URL de redirecionamento, que então alterna de volta para a atividade principal chamando OnActivityResult(). O método OnActivityResult() chama o auxiliar de autenticação MSAL para concluir a transação.

Testar a aplicação Android

Defina TodoApp.MAUI como o projeto de inicialização, selecione um emulador Android como destino e pressione F5 para criar e executar o aplicativo. Quando a aplicação é iniciada, é-lhe pedido para iniciar sessão na aplicação. Na primeira execução, você será solicitado a consentir com o aplicativo. Quando a autenticação estiver concluída, o aplicativo será executado normalmente.

Testar o aplicativo do Windows

Defina TodoApp.MAUI como o projeto de inicialização, selecione Windows Machine como destino e pressione F5 para criar e executar o aplicativo. Quando a aplicação é iniciada, é-lhe pedido para iniciar sessão na aplicação. Na primeira execução, você será solicitado a consentir com o aplicativo. Quando a autenticação estiver concluída, o aplicativo será executado normalmente.

Próximos passos

Em seguida, configure seu aplicativo para operar offline implementando um repositório offline.

Leitura adicional