quarta-feira, 21 de janeiro de 2015

Exemplo de Autenticação em Node.JS - Autenticação via Facebook

Demais posts desta série:


Olá a todos!

Finalizando nossa série de posts sobre autenticação utilizando Node.JS, vamos adicionar à nossa aplicação o login via Facebook. O procedimento é o mesmo adotado para as autenticações externas anteriores (gerar as chaves e o ID do cliente, atualizar o config.js, atualizar o passport.js, etc). Porém, se você pensa que só é possível adicionar login externo somente com os serviços mostrados nesta série de posts, se engana. Neste link, estão relacionados todos os módulos do passport capazes de realizar autenticação externa. Lembre-se de olhar a documentação de cada módulo para ter certeza do que fazer para adicionar a sua aplicação.

Lembrando que o projeto completo está disponível aqui, e este tutorial foi baseado neste  excelente link.

Como é de praxe, vamos agora gerar as nossas chaves. Acesse a página de desenvolvedores do Facebook, no menu superior, clique em My Apps, e se registre como desenvolvedor. Ao final do processo, esta página aparecerá:



Clique em website. Em seguida, digite o nome da nossa aplicação e clique em "Create New Facebook App ID". No pop-up, escolha a categoria (pode ser a primeira) e clique no botão azul para finalizar o processo. Após o carregamento da página do app, clique em "start over", no canto superior esquerdo para acessar o dashboard da nossa aplicação. De cara, você já encontra o App ID e o App Secret. Copie os dois para o arquivo config.js.

facebook:{
    consumer_key:'seu app id aqui',
    consumer_secret:'seu app secret aqui',
    callback_url:'http://127.0.0.1:3000/facebook/callback',
},

Depois, volte para o facebook, pois temos mais uma configuração para fazer.  Por padrão, o Facebook não aceita que nenhuma URL se conecte com ele via OAuth. Assim, precisamos informar a ele qual URL ele deve aceitar. Em Configurações > Aba advanced, na parte inferior da página tem um campo chamado "Valid OAuth redirect URIs". Neste campo, coloque a URL da nossa aplicação (http://127.0.0.1:3000). Salve tudo e, agora sim, podemos voltar para a nossa aplicação.

Próxima fase: atualizar o modelo (arquivo models/User.js):

    facebook:{
            id:String,
            token:String,
            email:String,
            name:String,
        },

Depois, instalamos o módulo do passport que se conecta ao facebook e configuramos a estratégia no arquivo lib/passport.js

npm install --save passport-facebook

...
var FacebookStrategy=require('passport-facebook').Strategy;
...

    /*************************
     ***** FACEBOOK AUTH *****
     *************************/
     
     passport.use(new FacebookStrategy({
        clientID: config.secret.facebook.consumer_key,
        clientSecret: config.secret.facebook.consumer_secret,
        callbackURL: config.secret.facebook.callback_url,
        passReqToCallback: true,
    }, function(req,token, refreshToken, profile, done){
        process.nextTick(function(){
            if(!req.user){
                User.findOne({'auth.facebook.id':profile.id}, function(err, user){
                    if(err) return done(err);
                    if(user){
                        return done(null, user);
                    }else{
                        var newUser=new User();
                        newUser.auth.facebook.id=profile.id;
                        newUser.auth.facebook.token=token;
                        newUser.auth.facebook.email=profile.emails[0].value;
                        newUser.auth.facebook.name=profile.name.givenName+' '+profile.name.familyName;

                        newUser.save(function(err){
                            if(err) throw err;

                            return done(null, newUser)
                        });
                    }
                });
            }else{
                var _user=req.user;
                
                _user.auth.facebook.id=profile.id;
                _user.auth.facebook.token=token;
                _user.auth.facebook.email=profile.emails[0].value;
                _user.auth.facebook.name=profile.name.givenName+' '+profile.name.familyName;
                
                _user.save(function(err){
                    if(err) throw err;
                    
                    return done(null, _user);
                });
            }            
        });
    }));

Em seguida, as rotas (arquivo config/routes.js):

'/facebook/connect':{
        controller:'LoginController',
        action:'facebookConnect',
    },
    
    '/facebook/callback':{
        controller:'LoginController',
        action:'facebookCallback',
    },
    
    '/facebook/link':{
        controller:'LoginController',
        action:'facebookLink',
        policy:'isAuthenticated',
    },
    
    '/facebook/link/callback':{
        controller:'LoginController',
        action:'facebookLinkCallback',
        policy:'isAuthenticated',
    },
    
    '/facebook/unlink':{
        controller:'LoginController',
        action:'facebookUnlink',
        policy:'isAuthenticated',
    },

Para finalizar, atualizamos as views. Primeiro o dashboard.hbs:

<!--Facebook Information-->
            <div class="col-sm-6">
                <div class="well">
                    <h3 class="text-primary"><span class="fa fa-facebook"></span> Facebook</h3>
                    {{#if user.auth.facebook.id}}
                        <p>
                            <strong>id</strong>: {{user.auth.facebook.id}}<br/>
                            <strong>token</strong>: {{user.auth.facebook.token}}<br/>
                            <strong>email</strong>: {{user.auth.facebook.email}}<br/>
                            <strong>name</strong>: {{user.auth.facebook.name}}<br/>
                        </p>
                        <a href="/facebook/unlink" class="btn btn-primary">Desassociar conta</a>
                    {{else}}
                        <a href="/facebook/link" class="btn btn-primary">Conectar ao Facebook</a>
                    {{/if}}
                </div>
            </div>

Depois, o index.hbs:

<a href="/facebook/connect" class="btn btn-primary"><span class="fa fa-facebook"></span> Facebook</a>

Quando executarmos a aplicação, tudo deve estar funcionando devidamente.

Index

Dashboard

Com isso, encerramos a nossa série sobre autenticação utilizando o Node.JS. Lembrando que todo o código desenvolvido neste tutorial está disponível aqui, e qualquer dúvida referente ao desenvolvimento, podem postar nos comentários que responderei o máximo possível.

Inté.

Demais posts desta série:

Nenhum comentário:

Postar um comentário