Back-End

27 abr, 2017

Xamarin Forms – Autenticação com OAuth Identity Provider

Publicidade

Neste artigo, vou mostrar como fazer a autenticação via OAuth e Identity Provider em uma aplicação Xamarin Forms usando o VS 2015 Community e a linguagem C#.

O OAuth é um protocolo de autenticação web e um padrão aberto para autorização.

Atualmente, ele é muito usado para fazer o login em sites que usam as seguintes contas de usuário sem expor o seu registo:

  1. GOOGLE
  2. FACEBOOK
  3. TWITTER
  4. MICROSOFT
  5. LINKEDIN
  6. GITHUB
  7. FLICKER
  8. YAHOO
  9. DROPBOX

Para saber mais sobre os provedores de identidades, acesse este link  https://en.wikipedia.org/wiki/List_of_OAuth_providers

Como funciona o OAuth?

OAuth é framework de autorização que permite que uma aplicativo obtenha acesso limitado às contas de um usuário no serviço HTTP no Facebook, no Google, Twitter, na Microsoft etc.

Atualmente, não há necessidade de criar uma lógica de registro. Como alternativa, você pode escolher usar o identity provider login. Nesse caso, uma pessoa se inscreve para o aplicativo e uma conta é criada para ele e a etapa de autenticação é atendida pelo provedor de identidade.

O processo para poder acessar as informações de outro website sem realizar o registro, de forma resumida e sem entrar em detalhes da API OAuth, pode se feito em 3 etapas:

  1. Obter um token da solicitação – Request Token;
  2. Obter a autorização do usuário;
  3. Troca o token de solicitação por um token de acesso.

A figura abaixo ilustra esse processo:

Registrar novos aplicativos OAuth

Antes que você possa integrar o provedor de Identidade e se logar em seus aplicativos, você deve registrar seu aplicativo e obter o client ID e o client secret correspondentes a partir dos passos descritos abaixo no qual precisamos chamar a API Sign-in .

  1. Navegue até https://console.developers.google.com e faça login com as credencias de sua conta Google;
  2. Selecione a tab Credentials e clique em Create Project;
  3. Adicione o nome do seu  App/website e clique em Create;
  4. Obtenha o seu Client ID e o client secret.

Neste exemplo, estamos invocando a aplicação do Facebook para realizar o login e vamos injetar esse comportamento em uma página Login.xaml que iremos criar em nosso projeto. Essa view será uma view sem conteúdo nenhum que irá hospedar a página de autenticação que será injetada pelo Renderer do Xamarin. Além da página Login.xaml, vamos criar a página Profile.xaml contendo apenas uma Label para exibir a mensagem de sucesso ou de erro ao fazer o login.

Além da destas páginas, vamos criar uma página Main.xaml, onde teremos um botão de comando para que o usuário realize a autenticação via Facebook.

Todo o trabalho pesado será feito por um Renderizador, que no nosso exemplo será implementado e testado no projeto Android.

Os renderizadores personalizados são uma ponte entre o Xamarin.Forms e as bibliotecas Xamarin específicas de plataforma (iOS, Android, Windows Phone) que permitem pegar um elemento multiplataforma e o renderiza na tela usando a biblioteca de interface específica de plataforma.

Então, vamos criar uma classe no projeto Android chamada FBLoginPageRenderer que herda da classe PageRenderer e cujo código vemos abaixo:

using System;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using Android.App;
using Xamarin.Auth;
using Newtonsoft.Json.Linq;
using XF_LoginFacebook;
[assembly: ExportRenderer(typeof(Login), typeof(XF_LoginFacebook.Droid.FBLoginPageRenderer))]
namespace XF_LoginFacebook.Droid
{
    public class FBLoginPageRenderer : PageRenderer
    {
        public FBLoginPageRenderer()
        {
            var activity = this.Context as Activity;
            var auth = new OAuth2Authenticator(
                clientId: "180XXXXX20029269",   //  seu cliente id OAuth2 client id
                scope: "",                                      
                authorizeUrl: new Uri("https://m.facebook.com/dialog/oauth/"),
                redirectUrl: new Uri("http://www.facebook.com/connect/login_success.html"));
            auth.Completed += async (sender, eventArgs) => {
                if (eventArgs.IsAuthenticated)
                {
                    var accessToken = eventArgs.Account.Properties["access_token"].ToString();
                    var expiresIn = Convert.ToDouble(eventArgs.Account.Properties["expires_in"]);
                    var expiryDate = DateTime.Now + TimeSpan.FromSeconds(expiresIn);
                    var request = new OAuth2Request("GET", new Uri("https://graph.facebook.com/me"), null, eventArgs.Account);
                    var response = await request.GetResponseAsync();
                    var obj = JObject.Parse(response.GetResponseText());
                    var id = obj["id"].ToString().Replace("\"", "");
                    var name = obj["name"].ToString().Replace("\"", "");
                    await App.NavigateToProfile(string.Format("Olá {0}, seja bem-vindo", name));
                }
                else
                {
                    await App.NavigateToProfile("Usuário Cancelou o login");
                }
            };
            activity.StartActivity(auth.GetUI(activity));
        }
    }
}

Neste código, temos a autenticação sendo realizada e, a seguir, após o processo ser completado, verificamos as propriedades de token de acesso e data de expiração do mesmo. Depois, com essas informações, fazemos uma requisição para a conta no endereço – https://graph.facebook.com/me –  obtemos a resposta transformando-a em um objeto JSON. A seguir, obtemos o id e o nome da conta e utilizamos as informações para exibir a mensagem.

Ao final, usamos o método NavigateToProfile da classe App, que iremos implementar para exibir a mensagem na página Profile.xaml.

Talvez, o código mais importante seja o atributo usado na classe:

[assembly: ExportRenderer(typeof(Login), typeof(XF_LoginFacebook.Droid.FBLoginPageRenderer))]

Aqui temos o Renderer entrando em ação quando você executar o aplicativo. Seu trabalho é tomar o elemento agnóstico plataforma e transformá-lo em algo visual para apresentar ao usuário.

No nosso caso, o atributo ExportRenderer especifica que este Renderer personalizado deve ser chamado quando o controle é processado; no caso, quando o Login form chamado. Neste momento, a página de autenticação será injetada na view Login.xaml.

Isso posto, vamos implementar.

Recursos usados:

Criando um projeto no VS 2015 com Xamarin

Abra o Visual Studio Community 2015 e clique em New Project. Selecione Visual C#, o template Cross Plataform e, a seguir, Blank App (Xamarin.Forms Portable).

Nota: A opção Portable (Portable Class Library – PCL) inclui todo o código comum em uma biblioteca de vínculo dinâmico (DLL) que pode então ser referenciada a partir de outros projetos.

Informe o nome XF_LoginFacebook e clique no botão OK. Ao clicar, será criada uma solução contendo quatro projetos (dependendo do seu ambiente pode haver alguma variação nos projetos). O projeto comum possui a classe App.cs, que irá conter o código compartilhado e que vamos usar neste artigo.

Criando as páginas da aplicação: Main.xaml, Login.xaml e Profile.xaml

No menu Project, clique em Add New Item e, a seguir, em Cross Platform e em Forms Xaml Page e informe o nome Main.xaml:

Repita o procedimento e crie a página Login.xaml e para a página Profile.xaml.

Definindo o código da Main.xaml

Inclua o código abaixo na Pagina1.xaml:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="XF_LoginFacebook.Main"
             Title="Login com FaceBook">
    <StackLayout VerticalOptions="Center">
         <Button Text="Fazer Login com Facebook" x:Name="btnLogar" Clicked="btnLogar_Clicked" />
    </StackLayout>
    
</ContentPage>

Neste código, definimos um StackLayout contendo uma Button com nome btnLogar e um evento Clicked cujo código é visto abaixo:

        private async void btnLogar_Clicked(object sender, EventArgs e)
        {
            await Navigation.PushAsync(new Login());
        }

No evento, estamos navegando para página de Login que, ao ser instanciada, sofrerá a ação do Renderer que injetará a página de autenticação do Facebook.

Definindo o código da Login.xaml

A página de Login não tem nenhum conteúdo, conforme vemos a seguir:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="XF_LoginFacebook.Login"
             Title="Login com FaceBook">
    
</ContentPage>

Definindo o código da Profile.xaml

A seguir, defina o código XAML da Pagina2:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="XF_LoginFacebook.Profile"
             Title="Login com Facebook">
    <StackLayout VerticalOptions="Center">
       <Label x:Name="lblMessage" FontSize="Medium" HorizontalOptions="Center"
              TextColor="Black"/>
    </StackLayout>
</ContentPage>

Neste código iremos exibir as mensagens após a autenticação ser concluída com ou sem sucesso.

O código do arquivo Profile.xaml.cs é visto a seguir:

using Xamarin.Forms;
namespace XF_LoginFacebook
{
    public partial class Profile : ContentPage
    {
        public Profile(string message)
        {
            InitializeComponent();
            this.lblMessage.Text = message;
        }
    }
}

Definindo o código da classe App

Neste código, vamos definir a página principal da aplicação no construtor da classe, que será a nossa página Main.axml, e definir os métodos:

  • NavigateToProfile(string message) – Navega para a página Profile.xaml e exibe a mensagem recebida na autenticação;

  • HideLoginView() – Usa o método PopModalAsync() para ocultar a página de Login.

using System;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace XF_LoginFacebook
{
    public class App : Application
    {
        public static Action HideLoginView
        {
            get
            {
                return new Action(() => App.Current.MainPage.Navigation.PopModalAsync());
            }
        }
        public async static Task NavigateToProfile(string message)
        {
            await App.Current.MainPage.Navigation.PushAsync(new Profile(message));
        }
        public App()
        {
            MainPage = new NavigationPage(new Main());
        }
        protected override void OnStart()
        {}
        protected override void OnSleep()
        {}
        protected override void OnResume()
        {}
    }
}

Executando o projeto, iremos obter o seguinte resultado:

Pegue o código usado nas páginas da aplicação: XF_LoginFacebook.zip