Autenticação Facebook no Grails
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…
- Crie uma conta (se não tiver) no facebook
- Acesse https://www.facebook.com/developers/createapp.php e cadastre sua aplicação com o nome fbauth
- 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
- Pegue sua Application ID e Application Secret e adicione as linhas no arquivo
grails-app/conf/Config.groovyfacebook.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








Gostei do post
..
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!!!
Estou tento exatamente o mesmo problema!