Xamarin.Essentials: Autenticador web

A classe WebAuthenticator permite iniciar fluxos baseados em navegador que escutam um retorno de chamada para uma URL específica registrada no aplicativo.

Visão geral

Muitos aplicativos exigem a adição de autenticação de usuário, e isso geralmente significa permitir que os usuários entrem em suas contas existentes da Microsoft, Facebook, Google e agora da Apple Sign In.

A MSAL (Biblioteca de Autenticação da Microsoft) fornece uma excelente solução turn-key para adicionar autenticação ao seu aplicativo. Há até mesmo suporte para aplicativos Xamarin em seu pacote NuGet cliente.

Se você estiver interessado em usar seu próprio serviço Web para autenticação, é possível usar o WebAuthenticator para implementar a funcionalidade do lado do cliente.

Por que usar um back-end do servidor?

Muitos provedores de autenticação passaram a oferecer apenas fluxos de autenticação explícitos ou de duas pernas para garantir uma melhor segurança. Isso significa que você precisará de um 'segredo do cliente' do provedor para concluir o fluxo de autenticação. Infelizmente, os aplicativos móveis não são um ótimo lugar para armazenar segredos e qualquer coisa armazenada no código, binários ou em um aplicativo móvel geralmente é considerada insegura.

A melhor prática aqui é usar um back-end da Web como uma camada intermediária entre seu aplicativo móvel e o provedor de autenticação.

Importante

É altamente recomendável não usar bibliotecas e padrões de autenticação somente móveis mais antigos que não aproveitam um back-end da Web no fluxo de autenticação devido à sua falta inerente de segurança para armazenar segredos do cliente.

Introdução

Para começar a usar essa API, leia o guia de introdução para Xamarin.Essentials para garantir que a biblioteca esteja instalada e configurada corretamente em seus projetos.

Para acessar a funcionalidade WebAuthenticator , a configuração específica da plataforma a seguir é necessária.

O Android requer uma configuração de Filtro de Intenção para lidar com o URI de retorno de chamada. Isso é facilmente realizado pela subclasse da WebAuthenticatorCallbackActivity classe :

const string CALLBACK_SCHEME = "myapp";

[Activity(NoHistory = true, LaunchMode = LaunchMode.SingleTop, Exported = true)]
[IntentFilter(new[] { Android.Content.Intent.ActionView },
    Categories = new[] { Android.Content.Intent.CategoryDefault, Android.Content.Intent.CategoryBrowsable },
    DataScheme = CALLBACK_SCHEME)]
public class WebAuthenticationCallbackActivity : Xamarin.Essentials.WebAuthenticatorCallbackActivity
{
}

Se a versão do Android de destino do projeto estiver definida como Android 11 (R API 30), você deverá atualizar seu Manifesto do Android com consultas que são usadas com os novos requisitos de visibilidade do pacote.

Abra o arquivo AndroidManifest.xml na pasta Propriedades e adicione o seguinte dentro do nó do manifesto:

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

Usando o WebAuthenticator

Adicione uma referência a Xamarin.Essentials em sua classe:

using Xamarin.Essentials;

A API consiste principalmente em um único método AuthenticateAsync que usa dois parâmetros: a URL que deve ser usada para iniciar o fluxo do navegador da Web e o URI que você espera que o fluxo chame de volta e para o qual seu aplicativo está registrado para ser capaz de lidar.

O resultado é um WebAuthenticatorResult que inclui todos os parâmetros de consulta analisados do URI de retorno de chamada:

var authResult = await WebAuthenticator.AuthenticateAsync(
        new Uri("https://mysite.com/mobileauth/Microsoft"),
        new Uri("myapp://"));

var accessToken = authResult?.AccessToken;

A WebAuthenticator API cuida de iniciar a URL no navegador e aguardar até que o retorno de chamada seja recebido:

Fluxo típico de autenticação da Web

Se o usuário cancelar o fluxo a qualquer momento, um TaskCanceledException será lançado.

Sessão de autenticação privada

O iOS 13 introduziu uma API de navegador da Web efêmera para desenvolvedores iniciarem a sessão de autenticação como privada. Isso permite que os desenvolvedores solicitem que nenhum cookies compartilhados ou dados de navegação estejam disponíveis entre as sessões de autenticação e serão uma nova sessão de logon a cada vez. Isso está disponível por meio do novo WebAuthenticatorOptions que foi introduzido na Xamarin.Essentials versão 1.7 para iOS.

var url = new Uri("https://mysite.com/mobileauth/Microsoft");
var callbackUrl = new Uri("myapp://");
var authResult = await WebAuthenticator.AuthenticateAsync(new WebAuthenticatorOptions
    {
        Url = url,
        CallbackUrl = callbackUrl,
        PrefersEphemeralWebBrowserSession = true
    });

Diferenças de plataforma

As guias personalizadas são usadas sempre que disponíveis; caso contrário, uma Intenção é iniciada para a URL.

Entrada da Apple

De acordo com as diretrizes de revisão da Apple, se seu aplicativo usar qualquer serviço de logon social para autenticar, ele também deverá oferecer a Entrada da Apple como uma opção.

Para adicionar o Apple Sign In aos seus aplicativos, primeiro você precisará configurar seu aplicativo para usar o Apple Sign In.

Para o iOS 13 e superior, você desejará chamar o AppleSignInAuthenticator.AuthenticateAsync() método . Isso usará a API nativa de Entrada da Apple nos bastidores para que os usuários obtenham a melhor experiência possível nesses dispositivos. Você pode escrever seu código compartilhado para usar a API correta em runtime da seguinte maneira:

var scheme = "..."; // Apple, Microsoft, Google, Facebook, etc.
WebAuthenticatorResult r = null;

if (scheme.Equals("Apple")
    && DeviceInfo.Platform == DevicePlatform.iOS
    && DeviceInfo.Version.Major >= 13)
{
    // Use Native Apple Sign In API's
    r = await AppleSignInAuthenticator.AuthenticateAsync();
}
else
{
    // Web Authentication flow
    var authUrl = new Uri(authenticationUrl + scheme);
    var callbackUrl = new Uri("xamarinessentials://");

    r = await WebAuthenticator.AuthenticateAsync(authUrl, callbackUrl);
}

var authToken = string.Empty;
if (r.Properties.TryGetValue("name", out var name) && !string.IsNullOrEmpty(name))
    authToken += $"Name: {name}{Environment.NewLine}";
if (r.Properties.TryGetValue("email", out var email) && !string.IsNullOrEmpty(email))
    authToken += $"Email: {email}{Environment.NewLine}";

// Note that Apple Sign In has an IdToken and not an AccessToken
authToken += r?.AccessToken ?? r?.IdToken;

Dica

Para dispositivos não iOS 13, isso iniciará o fluxo de autenticação da Web, que também pode ser usado para habilitar a Entrada da Apple em seus dispositivos Android e UWP. Você pode entrar em sua conta do iCloud em seu simulador de iOS para testar a Entrada da Apple.


ASP.NET back-end do servidor principal

É possível usar a WebAuthenticator API com qualquer serviço de back-end da Web. Para usá-lo com um aplicativo ASP.NET principal, primeiro você precisa configurar o aplicativo Web com as seguintes etapas:

  1. Configure os provedores de autenticação social externos desejados em um aplicativo Web ASP.NET Core.
  2. Defina o Esquema de Autenticação Padrão como CookieAuthenticationDefaults.AuthenticationScheme em sua .AddAuthentication() chamada.
  3. Use .AddCookie() em sua chamada Startup.cs .AddAuthentication() .
  4. Todos os provedores devem ser configurados com .SaveTokens = true;.
services.AddAuthentication(o =>
    {
        o.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    })
    .AddCookie()
    .AddFacebook(fb =>
    {
        fb.AppId = Configuration["FacebookAppId"];
        fb.AppSecret = Configuration["FacebookAppSecret"];
        fb.SaveTokens = true;
    });

Dica

Se você quiser incluir a Entrada da Apple, poderá usar o AspNet.Security.OAuth.Apple pacote NuGet. Você pode exibir o exemplo completo de Startup.cs no repositório GitHub do Essentials.

Adicionar um controlador de autenticação móvel personalizado

Com um fluxo de autenticação móvel, geralmente é desejável iniciar o fluxo diretamente para um provedor que o usuário escolheu (por exemplo, clicando em um botão "Microsoft" na tela de entrada do aplicativo). Também é importante poder retornar informações relevantes para seu aplicativo em um URI de retorno de chamada específico para encerrar o fluxo de autenticação.

Para fazer isso, use um Controlador de API personalizado:

[Route("mobileauth")]
[ApiController]
public class AuthController : ControllerBase
{
    const string callbackScheme = "myapp";

    [HttpGet("{scheme}")] // eg: Microsoft, Facebook, Apple, etc
    public async Task Get([FromRoute]string scheme)
    {
        // 1. Initiate authentication flow with the scheme (provider)
        // 2. When the provider calls back to this URL
        //    a. Parse out the result
        //    b. Build the app callback URL
        //    c. Redirect back to the app
    }
}

A finalidade desse controlador é inferir o esquema (provedor) que o aplicativo está solicitando e iniciar o fluxo de autenticação com o provedor social. Quando o provedor chama de volta para o back-end da Web, o controlador analisa o resultado e redireciona para o URI de retorno de chamada do aplicativo com parâmetros.

Às vezes, talvez você queira retornar dados como a volta do access_token provedor para o aplicativo, o que você pode fazer por meio dos parâmetros de consulta do URI de retorno de chamada. Ou talvez você queira, em vez disso, criar sua própria identidade em seu servidor e passar seu próprio token para o aplicativo. O que e como você faz essa parte cabe a você!

Confira o exemplo completo do controlador no repositório Essentials.

Observação

O exemplo acima demonstra como retornar o Token de Acesso do provedor de autenticação de terceiros (ou seja: OAuth). Para obter um token que você pode usar para autorizar solicitações da Web para o próprio back-end da Web, você deve criar seu próprio token em seu aplicativo Web e retornar isso. A Visão geral da autenticação ASP.NET Core tem mais informações sobre cenários de autenticação avançada no ASP.NET Core.


API