Alex Florentino

KISS - Keep It Simple, Stupid
January 29th, 2009

Autenticação com ruby on rails - restful authentication + OpenID

Todo programador  já deve ter escrito varios e varios sistemas onde exista a necessidade de proteger algumas paginas, qual é a solução mais comum ? escrever mais uma vez código para login de usuario, acabando por duplicar código entre projetos.

Outro efeito ruim disso é que acaba duplicando informações de acesso de usuarios, exemplo cada sistema tem sua própria base de dados de usuario, para resolver(ou tentar) este problema foi criado OpenID.

O funcionamento do OpenID, em linhas gerais, é o seguinte: usuario é dono de uma url digamos http://ualex.myopenid.com e  este usuario deseja logar no meu sistema que suporta autenticação por OpenID, ele simplesmente digita sua url na tela de login do meu sistema e logo depois é direcionado para um OpenID provider, neste caso myopenid.com, no site do OpenID provider o usuario digita sua  senha e comprova que é dono da URL, logo após isso ele é redirecionado para minha aplicação e continua navegando normalmente.

Parece complicado não é ?  OpenID tem uma especificação bem clara e existe varios frameworks em varias liguagens para tratar o processo de autenticação, existe até frameworks para criar seu próprio OpenID Provider, este útil para centralizar autenticação de usuarios de aplicações web dentro de uma empresa.

Neste tutorial irei aproveitar aplicação construida no post sobre restful authentication para implementar autenticação por OpenID, vamos la.

1. Instalar a biblioteca openid-ruby


gem install ruby-openid

2. Instalar o plugin open_id_authentication


git clone git://github.com/rails/open_id_authentication.git vendor/plugins/open_id_authentication

3. Criar as migrations do open_id_authentication


rake open_id_authentication:db:create

4. Criar uma migration para alterar nossa tabela users


ruby script\generate migration add_identity_url_for_users

Nossa nova migration irá conter :


class AddIdentityUrlForUsers < ActiveRecord::Migration
def self.up
add_column :users, :identity_url, :string
end

def self.down
remove_column :users, :identity_url
end
end

5. Alterar nosso controller Session para permitir autenticação por OpenID ou por password

Com certeza essa é umas das partes mais “complicadas” do processo, você irá precisar fazer as seguintes alterações no seu controller session(criado pelo restful_authentication).


def create
if using_open_id?
open_id_authentication()
else
password_authentication()
end
end

def open_id_authentication
authenticate_with_open_id do |result, identity_url|
if result.successful?
if @current_user = User.find_by_identity_url(identity_url)
success_login()
else
failed_login "Sorry, no user by that identity URL exists (#{identity_url})"
end
else
failed_login result.message
end
end
end

def success_login
session[:user_id] = @current_user.id
redirect_to(root_url)
flash[:notice] = "Sucesso"
end

def  failed_login(message)
flash[:notice] = message
redirect_to(new_session_url)

end

def password_authentication
logout_keeping_session!
user = User.authenticate(params[:login], params[:password])
if user
# Protects against session fixation attacks, causes request forgery
# protection if user resubmits an earlier form using back
# button. Uncomment if you understand the tradeoffs.
# reset_session
self.current_user = user
new_cookie_flag = (params[:remember_me] == "1")
handle_remember_cookie! new_cookie_flag
redirect_back_or_default('/')
flash[:notice] = "Logged in successfully"
else
note_failed_signin
@login       = params[:login]
@remember_me = params[:remember_me]
render :action => 'new'
end
end

altere seu arquivo conforme o código acima.

6. Adicionando a opção OpenID na tela de login

vamos adicionar em nossa tela de login um field para usuario entrar com sua url, e caso esta url estiver presente autenticar por OpenID.


//arquivo: sessions/new.html.erb
<p><%= label_tag "OpenID URL" %>
<p><%= text_field_tag 'openid_identifier' %></p>

7. Alterar nossa view para permitir o cadastro de nossa url de autenticação


adicione o novo field identity_url para quando o usuario estiver no processo de signup, ele possa entrar com a OpenID url.

//arquivo: users/new.html.erb

<p><%= label_tag 'Identity url' %><br/>
<%= f.text_field :identity_url %></p>

8. Corrigindo um  detalhe para torna nosso site mais seguro


//arquivo models/user.rb

attr_accessible :login, :email, :name, :password, :password_confirmation, :identity_url

note foi adicionado o :identity_url no final da listagem.

9. Finalizando

Pronto, se você chegou até aqui é hora de testar, para criar um OpenID(free) acesse o http://www.myopenid.com e faça o seu cadastro, uma dica é utilize o rails 2.2 e tentei inicialmente o rails 2.1.1 mais existe uma incompatibilidade entre os frameworks nessa versão.

Leave a Reply