Web Api – Adicionando autenticação externa via OAuthProvider (Facebook)

Fala galera!

Continuando com o assunto do post anterior “Adicionando autenticação (OAuth)“, fiz este artigo explicando como adicionar o Facebook como Login provider em nossa Web Api.

Existem muitas maneiras para autenticar com um provider externo. Dá para fazer isso criando um controller e fazer a autenticação na unha. Dá pra fazer um usando o próprio Provider para Facebook que do Owin (Microsoft.Owin.Security.Facebook).

Testando alguns, eu preferi usar o CustomGrant do próprio OAuthProvider, foi bem mais fácil e simples de configurar.

1) Acesse https://developers.facebook.com e crie um aplicativo. Guarde o AppId e AppSecret para usarmos mais tarde.

Você também vai precisar de um AccessToken para testar o aplicativo. Para obter um acesse: https://developers.facebook.com/tools/accesstoken/.

2) Vamos começar do ponto em que o projeto já está com autenticação OAuth funcionando. Para isso eu baixei o código fonte do artigo anterior: https://github.com/leonardohof/WebApiTest

3) Vamos adicionar o AppId e AppSecret do Facebook no Startup.Auth, deixando a classe assim:

using Owin;
using Microsoft.Owin;
using Microsoft.Owin.Security.OAuth;
using System;
using WebApiTest.Providers;

namespace WebApiTest
{
    public partial class Startup
    {
        public const string FacebookAppId = "xxxx";
        public const string FacebookAppSecret = "xxxx";

        public void ConfigureAuth(IAppBuilder app)
        {
            var OAuthBearerOptions = new OAuthBearerAuthenticationOptions();
            app.UseOAuthBearerAuthentication(OAuthBearerOptions);

            app.UseOAuthAuthorizationServer(new OAuthAuthorizationServerOptions()
            {
                TokenEndpointPath = new PathString("/Token"),
                Provider = new ApplicationOAuthProvider(),
                AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
                AllowInsecureHttp = true,
            });
        }
    }
}

4) Agora vamos alterar o AplicationOAuthProvider para aceitar o nosso novo grant. Adicione o código dentro da classe:

        public override Task GrantCustomExtension(OAuthGrantCustomExtensionContext c)
        {
            if (c.GrantType == "facebook_token")
            {
                var token = c.Parameters.Get("token");
                if (!string.IsNullOrEmpty(token))
                {
                    if (ValidateFacebookToken(token).Result)
                    {
                        // Verificar se o token é válido
                        var fbInfo = GetFacebookInfo(token).Result;
                        if (fbInfo != null)
                        {
                            string id = fbInfo["id"].Value;
                            //string email = fbInfo["email"].Value;
                            string name = fbInfo["name"].Value;

                            // Verificar se o usuário existe no banco de dados
                            // Se não existir e tiver todos os dados, pode cadastrar já
                            bool userHasRegistered = true;
                            if (userHasRegistered)
                            {
                                Claim claim1 = new Claim(ClaimTypes.Name, name);
                                Claim[] claims = new Claim[] { claim1 };
                                ClaimsIdentity claimsIdentity =
                                    new ClaimsIdentity(
                                       claims, OAuthDefaults.AuthenticationType);
                                c.Validated(claimsIdentity);
                            }
                        }
                    }
                }
            }

            return Task.FromResult<object>(null);
        }

        #region Helpers

        // Obtém as informações do usuário logado no Facebook a partir do AccessToken
        private async Task<bool> ValidateFacebookToken(string token)
        {
            var verifyTokenEndPoint = string.Format("https://graph.facebook.com/app?access_token={0}", token);
            var client = new HttpClient();
            var uri = new Uri(verifyTokenEndPoint);
            var response = await client.GetAsync(uri, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false);

            if (response.IsSuccessStatusCode)
            {
                var content = await response.Content.ReadAsStringAsync();
                dynamic jObj = (JObject)Newtonsoft.Json.JsonConvert.DeserializeObject(content);

                var app_id = jObj["id"].Value;

                if (string.Equals(Startup.FacebookAppId, app_id, StringComparison.OrdinalIgnoreCase))
                    return true;
            }

            return false;
        }

        // Serve apenas para verificar se o AccessToken é válido e pertence a mesma aplicação que estamos usando
        private async Task<dynamic> GetFacebookInfo(string token)
        {
            var verifyTokenEndPoint = string.Format("https://graph.facebook.com/me?access_token={0}", token);
            var client = new HttpClient();
            var uri = new Uri(verifyTokenEndPoint);
            var response = await client.GetAsync(uri, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false);

            if (response.IsSuccessStatusCode)
            {
                var content = await response.Content.ReadAsStringAsync();
                dynamic jObj = (JObject)Newtonsoft.Json.JsonConvert.DeserializeObject(content);

                return jObj;
            }

            return null;
        }

        #endregion

5) Agora vamos executar e ver o funcionamento. Execute o projeto e mude o endereço para “http://localhost:xxxx/api/me”, você verá uma mensagem informando que a autorização foi negada:

Screenshot_15

 

11) Para autorizar vamos enviar uma solicitação para o /Token, para isso vou utilizar o aplicativo “Postman”, disponível para instalar no chrome:

https://chrome.google.com/webstore/detail/postman/fhbjgbiflinjbdggehcddcbncdddomop

12) Crie uma requisição post para “http://localhost:xxxx/Token”

Adicione o Header:

Content-Type: application/x-www-form-urlencoded

Adicione body(raw):
*Nessa parte que diferencia do OAuth padrão.

grant_type=facebook_token&token=xxxx

13) Agora com um Token em mãos, conseguiremos acessar o “http://localhost:xxx/api/me”. Crie uma requisição para este endereço, do tipo GET e adicione o Header:

Authorization: Bearer TokenObtidoAnteriormente

Pronto, nossa autenticação já está funcionando via OAuth e via Facebook Token.
Espero ter ajudado, qualquer dúvida estou a disposição!

Código fonte:
https://github.com/leonardohof/WebApiTestFacebook


Curta também minha página no Facebook para ficar por dentro das novidades:
https://www.facebook.com/devleonardohofling

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *