Partilhar via


Adicionar autenticação ao seu aplicativo Xamarin.Forms

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 seu aplicativo usando o Microsoft Entra ID. Antes de concluir este tutorial, verifique se você criou o projeto e implantou o back-end.

Observação

Como o aplicativo iOS requer acesso às chaves, você precisará configurar um perfil de provisionamento do iOS. Um perfil de provisionamento requer um dispositivo iOS real ou uma conta de desenvolvedor Apple paga (se estiver usando o simulador). Você pode pular este tutorial e passar para adicionar acesso offline ao seu aplicativo se não puder usar a autenticação devido a essa restrição.

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.Forms como o projeto de inicialização.

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 o projeto TodoApp.Forms. Adicione um novo arquivo chamado IPlatform.cs com o seguinte conteúdo:

using Microsoft.Identity.Client;

namespace TodoApp.Forms
{
    public interface IPlatform
    {
        IPublicClientApplication GetIdentityClient(string applicationId);
    }
}

Essa interface é usada posteriormente para permitir que o projeto compartilhado solicite ao projeto de plataforma um cliente de identidade adequado para a plataforma.

Abra App.xaml.cs. Adicione as seguintes using instruções:

using Microsoft.Datasync.Client;
using Microsoft.Identity.Client;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;

Na classe App, adicione duas novas propriedades:

public IPublicClientApplication IdentityClient { get; set; }
public IPlatform PlatformService { get; }

Ajuste o construtor para ler:

public App(IPlatform platformService)
{
    InitializeComponent();

    PlatformService = platformService;
    TodoService = new RemoteTodoService(GetAuthenticationToken);
    MainPage = new NavigationPage(new MainPage(this, TodoService));
}

Adicione o método GetAuthenticationToken à classe:

public async Task<AuthenticationToken> GetAuthenticationToken()
{
    if (IdentityClient == null)
    {
        IdentityClient = PlatformService.GetIdentityClient(Constants.ApplicationId);
    }

    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()
                .ConfigureAwait(false);
        }
        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.

Configurar o aplicativo Android para autenticação

Abra o projeto TodoApp.Forms.Android. Crie um novo MsalActivity de classe com o seguinte código:

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

namespace TodoApp.Forms.Droid
{
    [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 TodoApp.Forms.Android/Properties/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 MainActivity.cs. Adicione IPlatform à definição da classe MainActivity:

public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity, IPlatform

Altere a chamada de LoadApplication() no método OnCreate():

protected override void OnCreate(Bundle savedInstanceState)
{
    base.OnCreate(savedInstanceState);

    Xamarin.Essentials.Platform.Init(this, savedInstanceState);
    global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
    LoadApplication(new App(this));
}

Adicione o seguinte código à parte inferior da classe:

protected override void OnActivityResult(int requestCode, [GeneratedEnum] Result resultCode, Intent data)
{
    base.OnActivityResult(requestCode, resultCode, data);
    // Return control to MSAL
    AuthenticationContinuationHelper.SetAuthenticationContinuationEventArgs(requestCode, resultCode, data);
}

public IPublicClientApplication GetIdentityClient(string applicationId)
{
    var identityClient = PublicClientApplicationBuilder.Create(applicationId)
        .WithAuthority(AzureCloudInstance.AzurePublic, "common")
        .WithRedirectUri($"msal{applicationId}://auth")
        .WithParentActivityOrWindow(() => this)
        .Build();
    return identityClient;
}

Quando o projeto compartilhado requer autenticação, ele obtém um cliente de identidade do GetIdentityClient()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(). Em seguida, isso chama o auxiliar de autenticação MSAL, que conclui a transação.

Configurar o aplicativo iOS para autenticação

Abra o arquivo AppDelegate.cs no projeto TodoApp.Forms.iOS. Adicione IPlatform à definição da classe AppDelegate:

public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate, IPlatform

Altere o método FinishedLaunching() para ler:

public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
    global::Xamarin.Forms.Forms.Init();
    LoadApplication(new App(this));
    return base.FinishedLaunching(app, options);
}

Adicione o seguinte código ao final da classe:

public override bool OpenUrl(UIApplication app, NSUrl url, NSDictionary options)
{
    bool result = AuthenticationContinuationHelper.SetAuthenticationContinuationEventArgs(url);
    return result || base.OpenUrl(app, url, options);
}

public IPublicClientApplication GetIdentityClient(string applicationId)
{
    var identityClient = PublicClientApplicationBuilder.Create(applicationId)
        .WithIosKeychainSecurityGroup("com.microsoft.adalcache")
        .WithRedirectUri($"msal{applicationId}://auth")
        .Build();
    return identityClient;
}

Adicione acesso às chaves ao Entitlements.plist:

  1. Abra o arquivo Entitlements.plist.

  2. Selecione Porta-chaves.

  3. Selecione Adicionar Novo nos grupos de chaves.

  4. Insira com.microsoft.adalcache como o valor:

    Captura de ecrã a mostrar os direitos de i O S.

Adicione os direitos personalizados ao projeto:

  1. Clique com o botão direito do mouse no projeto TodoApp.Forms.iOS e selecione Propriedades.

  2. Selecione iOS Bundle Signing.

  3. Selecione o botão ... ao lado do campo Direitos Personalizados.

  4. Selecione Entitlementse, em seguida, selecione Abrir.

  5. Pressione Ctrl+S para salvar o projeto.

    Captura de tela mostrando as propriedades de assinatura do pacote i O S.

Testar a aplicação Android

Defina TodoApp.Forms.Android como o projeto de inicialização 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 a aplicação iOS

Observação

Como o aplicativo iOS requer acesso às chaves, você precisará configurar um perfil de provisionamento. Um perfil de provisionamento requer um dispositivo real ou uma conta de desenvolvedor Apple paga (se estiver usando o simulador). Para obter mais informações, consulte provisionamento de dispositivos para iOS.

Defina TodoApp.Forms.iOS como o projeto de inicialização 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