GustavoHenrique.net

  • About
  • Contact
  • RSS Feed
  • Twitter

 

26
Jun

Autenticação Facebook no Grails

By gustavohenrique|grails|2 Comments

Grails Logo

Recentemente comecei a brincar com o grails e precisei implementar a funcionalidade de login usando uma conta do facebook. Na minha busca sobre autenticação conheci o plugin spring-security-core do qual eu gostei muito e comecei a usar. Para autenticação no facebook existe o plugin facebook-graph que também é muito bom.
Pensando nisso resolvi mostrar como utilizar esses dois plugins juntos para implementar autenticação no facebook com spring-security-core e facebook-graph no grails.
Pra começar vou criar o projeto facebookauth, instalar os plugins e criar as classes SecUser e SecRole referentes à autenticação e controle de acesso:

$ grails create-app facebookauth
$ cd facebookauth
facebookauth$ grails install-plugin spring-seucrity-core
facebookauth$ grails install-plugin facebook-graph
facebookauth$ grails s2-quickstart org.example SecUser SecRole

O plugin spring-security-core provê um novo comando, o s2-quickstart, que serve para criar as classes de domínio referentes ao usuário e suas permissões de acesso. Não entrarei em detalhes sobre seu funcionamento pois há um artigo explicando o básico em http://blog.springsource.com/2010/08/11/simplified-spring-security-with-grails/.
Com isso foram criadas as classes SecUser, SecRole e SecUserSecRole, os controllers LoginController e LogoutController e a view auth.gsp que contém o formulário de login.
Antes de começar a brincar é preciso efetuar algumas configurações e registar sua aplicação no facebook…

  1. Crie uma conta (se não tiver) no facebook
  2. Acesse https://www.facebook.com/developers/createapp.php e cadastre sua aplicação com o nome fbauth
  3. Após o cadastro, vá na página de edição e clique no menu Web Site, então configure Site URL como www.localhost.com e Site Domain como localhost.com. Altere o /etc/hosts mapeando o ip 127.0.0.1 para www.localhost.com
  4. Pegue sua Application ID e Application Secret e adicione as linhas no arquivo grails-app/conf/Config.groovy
    facebook.applicationSecret='sua application secret aqui'
    facebook.applicationId='sua application id aqui'
    facebook.secure=true

Agora precisamos adicionar o atributo facebookId na classe SecUser.

package org.example
 
class SecUser {
 
    String username
    String password
    boolean enabled
    boolean accountExpired
    boolean accountLocked
    boolean passwordExpired
 
    String facebookId
 
    static constraints = {
        username blank: false, unique: true
        password blank: false
        facebookId blank: false, unique: true
    }
 
    static mapping = { 
        password column: '`password`'
    }   
 
    Set<SecRole> getAuthorities() {
        SecUserSecRole.findAllBySecUser(this).collect { it.secRole } as Set
    }   
}

Quando o usuário se autenticar pelo facebook, a aplicação vai receber o facebook id desse usuário e salvar no banco de dados. Então alteramos o comportamento da aplicação passando a buscar o usuário por esse id no banco, não mais por username e password.

O próximo passo é alterar a view de login para inserir um botão para autenticação via facebook. Altere o arquivo grails-app/views/login/auth.gsp inserindo o código abaixo:

<fbg:resources/>
<script type="text/javascript">
    function facebookLogin() {
        FB.getLoginStatus(function(response) {
            if (response.session) {
                window.location ="${createLink(controller:'login', action:'facebookLogin')}";
            }
        });
    }
</script>
<fb:login-button perms="email" onlogin="facebookLogin();" size="large">
    <g:message code="Login"/>
</fb:login-button>

Esse código insere um botão que ao ser clicado vai abrir um popup do facebook para o usuário se autenticar. Se o login for efetuado com sucesso, o popup será fechado e o usuário será redirecionado para a action facebookLogin no controller login.
Lembrando que o controller login foi criado anteriormente quando executamos o comando grails s2-quickstart porém a action facebookLogin não existe. Então vamos criá-la!

// outros imports existentes
 
import org.example.SecUser
import org.example.SecRole
import org.example.SecUserSecRole
 
class LoginController {
    // outros atributos e actions existentes
 
    def facebookGraphService
 
    def facebookLogin = {
        def details = facebookGraphService.getDetails()
        def facebookId = details.id
 
        def user = SecUser.findByFacebookId(facebookId)?: new SecUser(
            username: details.email,
            password: springSecurityService.encodePassword(facebookId),
            enabled: true,
            facebookId: facebookId).save(failOnError: true)
 
        def role = SecRole.findByAuthority('ROLE_FACEBOOK')?: new SecRole(
            authority:'ROLE_FACEBOOK').save(failOnError: true)
        if (! user.authorities.contains(role)) {
            SecUserSecRole.create user, role
        }
 
        SpringSecurityUtils.reauthenticate(user.username, user.password)
        redirect(controller: 'controlPanel')
    }
}

O objeto facebookGraphService é injetado automaticamente pelo grails e ao chamar facebookGraphService.getDetails() é retornado um JSONObject com o seguinte formato:

{"location":{"id":"110200955653479","name":"Rio de Janeiro, Rio de Janeiro"},"link":"http://www.facebook.com/nomedousuario","locale":"en_US","updated_time":"2011-05-11T02:58:41+0000","id":"100000552012367","first_name":"xxxx","username":"xxxx","timezone":-3,"email":"xxxx@xxx.com","verified":true,"name":"Xxxx Xxxxx","last_name":"Xxxx","gender":"male"}

Então pegamos o facebook id e verificamos se existe algum cadastro no banco. Se não houver vai cadastrar um novo usuário usando o e-mail como username e o facebook id como senha. Para nível de acesso, foi adicionada a Role ROLE_FACEBOOK, que vai ser criada caso não exista.

Para testar, vamos criar um novo controller e apenas usuários autenticados podem acessar.
O spring security possui uma anotação para ser usada nas actions onde voce define a lista de Roles que podem acessar a action. Se o usuário não possuir nenhuma dessas Roles então será redirecionado para página de login.

Vamos criar o controller grails-app/controllers/ControlPanelController.groovy com o código abaixo:

import grails.plugins.springsecurity.Secured
 
class ControlPanelController {
 
    @Secured(['ROLE_FACEBOOK']) 
    def index = { 
        render "Olá! Você fez o login pelo facebook! \o/"
    }   
}

Se tudo deu certo, quando acessar a action index do controller controlPanel o usuário será redirecionado à tela de login. Ao clicar no botão do facebook, um popup será exibido para que o usuário se identifique usando suas credenciais do facebook. Login efetuado então será redirecionado para o controller controlPanel que dessa vez vai exibir a mensagem de boas vindas.

Links

http://www.grails.org/plugin/facebook-graph
https://github.com/chechu/grails-facebook-graph
http://blog.springsource.com/2010/08/11/simplified-spring-security-with-grails/
https://github.com/gustavohenrique/grails-facebook-auth-example

Bookmark It

Add to Del.icio.us Add to Diigo Add to Facebook Add to Google Bookmarks Add to LinkedIn Add to Mister Wong Add to Twitter Add to Yahoo My Web
Tagged as: facebook, grails, spring
Add your comment →

2 Comments

  1. Gostei do post :D ..

    Só to com um problema, que talvez tu saiba o que é

    22: def details = facebookGraphService.getDetails()
    23: def facebookId = details.id

    Error 500: Executing action [facebookLogin] of controller [LoginController] caused exception: Cannot get property ‘id’ on null object
    Servlet: grails
    URI: /facebookauth/grails/login/facebookLogin.dispatch
    Exception Message: Cannot get property ‘id’ on null object
    Caused by: Cannot get property ‘id’ on null object
    Class: LoginController
    At Line: [23]
    Code Snippet:

    se puder dá uma força.. vlw!!!

    By: Jackson Malta Reply →
    August 30, 2011 at 6:23 pm
  2. Estou tento exatamente o mesmo problema!

    By: VIctor Mendes Reply →
    January 21, 2012 at 6:40 pm

Leave your comment below! Cancel Reply

View More Posts:
  • ←
  • →

Tags

admin Django extjs firewall grails jquery KingHost liberações Linux manual model modelform mod_wsgi moeda brasileira mudanças mysql nível de serviço oo PagSeguro pdf php PIL pisa problemas proxy python qa qos real relacionamento roteamento service desk shell script sites tdd tipsforlinux traducao ubicomp ubuntu urllib virtualhost Webservices wikipedia xsol __init__

Recent Posts

  • Configurando um servidor LDAP no CentOS 6.2
  • Introdução ao padrão MVC no Ext JS 4
  • Virtualização com KVM
  • Autenticação Facebook no Grails
  • Grails com Sqlite3 no Ubuntu 11.04
  • Deploy no tomcat usando django-jython
  • Deploy múltiplas versões do Django no Nginx com VirtualEnv
  • Comandos básicos do Git
  • Introdução ao Apache Wicket
  • Feliz 2011

Archives

Categories

My tweets

  • Public Domain, a documentary about the problems of Rio de Janeiro http://t.co/UcTUoPRo 2012-10-10
  • Adobe has released "Source Code Pro", a new open source font designed for software developers http://t.co/AHxrVP9W #protip 2012-09-28
  • http://t.co/9TlbWvWN #protip 2012-09-27
  • 10 things IT architects should consider when choosing data storage technologies http://t.co/6BjGXICI 2012-09-20
  • tá com calor? http://t.co/d3XQQO84 2012-09-20
  • More updates...

Powered by the inLine Minimal WordPress Theme