Compartilhar via


Adicionar autenticação ao seu aplicativo MAUI do .NET

Nota

Este produto está desativado. Para obter uma substituição para projetos que usam o .NET 8 ou posterior, consulte a biblioteca datasync do Kit de Ferramentas da Comunidade .

Neste tutorial, você adicionará 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 ode back-end.

Ponta

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

Adicionar autenticação ao 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 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:

  • Registre um aplicativo com a ID do Microsoft Entra.
  • Adicione a verificação de autenticação ao projeto de back-end do ASP.NET 6.

Registrar o aplicativo

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

  1. Entre no portal do do Azure.

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

  3. Pesquise e selecione microsoft entra ID.

  4. Em Gerenciar, selecione Registros de aplicativo>Novo registro.

    • Name: insira um nome para seu aplicativo; por exemplo, início rápido do TodoApp. Os usuários do seu aplicativo verão esse nome. Você pode alterá-lo mais tarde.
    • tipos de conta com suporte: contas em qualquer diretório organizacional (qualquer diretório do 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 de URI da ID do Aplicativo, aceite o padrão selecionando Salvar e continuar.

  8. Insira os seguintes detalhes:

    • de nome do escopo :
    • Quem pode consentir?: administradores e usuários
    • nome de exibição de consentimento do administrador: Access TodoApp
    • descrição de consentimento do administrador: Allows the app to access TodoApp as the signed-in user.
    • nome de exibição de consentimento do usuário: Access TodoApp
    • descrição de consentimento do usuário: 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 a (conhecido como 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 (conhecida comoda 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. Na nova guia, selecione Procurare, em seguida, insira Microsoft.Identity.Web na caixa de pesquisa.

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

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

  4. Siga os prompts para concluir a instalação do pacote.

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

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();

Seu Program.cs agora deve ter esta aparência:

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 <client-id> pela ID do aplicativo da API Web que você registrou anteriormente. Depois de concluído, ele deverá 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 mouse no projeto TodoAppService.NET6 e 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 tela do navegador mostrando 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 JWT (Token Web Json) dentro de um cabeçalho da transação HTTP. Esse aplicativo usa o da MSAL (Biblioteca de Autenticação da Microsoft) 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 Web hospedadas em seu aplicativo usando uma biblioteca de clientes, como a MSAL (Biblioteca de Identidades da Microsoft).

  1. No portal do do Azure, selecione registros de ID do Microsoft Entra>App>Novo registro.

  2. Na página Registrar um aplicativo:

    • insira um Name para o registro do aplicativo. Talvez você queira usar o nome native-quickstart para distinguir este do usado pelo serviço de back-end.
    • Selecione Contas em qualquer diretório organizacional (qualquer diretório do Microsoft Entra – Multilocatário) e contas pessoais da Microsoft (por exemplo, Skype, Xbox).
    • Em de URI de Redirecionamento:
      • Selecione cliente público (área de trabalho de & móvel)
      • Insira o quickstart://auth de URL
  3. Selecione Registrar.

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

  5. Selecione o registro de aplicativo criado anteriormente para seu serviço de back-end. Se você não vir o registro do aplicativo, verifique se adicionou o escopo access_as_user.

    Captura de tela do registro de escopo no portal do Azure.

  6. Em Selecione permissões, selecione access_as_usere selecione Adicionar permissões.

  7. Selecionede aplicativosmóveis e de área de trabalho da Autenticação .

  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} pela 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 a ID do aplicativo (cliente) (conhecida como ID do aplicativo do cliente nativo), pois 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 é usado por aplicativos móveis (Android e iOS).

Adicionar o Cliente de Identidade da Microsoft 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 da MSAL (Biblioteca de Identidades da Microsoft) ao projeto :

Adicione o da MSAL (Biblioteca de Identidades da Microsoft) ao projeto da plataforma:

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

  2. Selecione a guia Procurar.

  3. Insira Microsoft.Identity.Client na caixa de pesquisa e pressione Enter.

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

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

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

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

Abra o projeto TodoApp.Data e edite o arquivo Constants.cs. Adicionar 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> pela ID do aplicativo Native Client você recebeu ao registrar o aplicativo cliente na ID do Microsoft Entra e o <scope> com o Escopo da API Web copiado quando você usou Expor um de API ao registrar o aplicativo de serviço.

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

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 a MSAL (Biblioteca de Identidade da Microsoft) para obter um token de acesso adequado para autorizar o usuário conectado ao serviço de back-end. Em seguida, essa função é passada para o RemoteTodoService para criar o cliente. Se a autenticação for bem-sucedida, o AuthenticationToken será produzido com os dados necessários para autorizar cada solicitação. Caso contrário, um token inválido expirado será produzido.

Podemos adicionar todas as opções específicas da plataforma usando as áreas de #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 uma nova classe Platforms\Android\MsalActivity.cs 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} pela ID do aplicativo do cliente nativo (que é o mesmo que Constants.ApplicationId).

Se o projeto for direcionado ao Android versão 11 (API versão 30) ou posterior, você deverá atualizar o AndroidManifest.xml para atender aos requisitos de visibilidade do pacote do Android. Abra Platforms/Android/AndroidManifest.xml e adicione os seguintes nós 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 essa etapa depois de atualizar o aplicativo para iOS, adicione o código designado pelo #if ANDROID (incluindo o #if e o #endif). O compilador escolhe a parte correta do código com base na plataforma que está sendo compilada. Esse 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. Depois que a autenticação for concluída, o navegador do sistema redirecionará para a URL de redirecionamento definida (msal{client-id}://auth). O MsalActivity intercepta a URL de redirecionamento, que, em seguida, 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 o aplicativo Android

Defina TodoApp.MAUI como o projeto de inicialização, selecione um emulador android como o destino e pressione F5 para compilar e executar o aplicativo. Quando o aplicativo é iniciado, você é solicitado a entrar no aplicativo. Na primeira execução, você será solicitado a consentir com o aplicativo. Depois que a autenticação for 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 o destino e pressione F5 para compilar e executar o aplicativo. Quando o aplicativo é iniciado, você é solicitado a entrar no aplicativo. Na primeira execução, você será solicitado a consentir com o aplicativo. Depois que a autenticação for concluída, o aplicativo será executado normalmente.

Próximas etapas

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

Leitura adicional