Setup Basic Rails Security and Facebook Authentication
1. Devise, OmniAuth, and
Facebook
A tutorial on how to setup basic rails security using Facebook for authentication
2. Setup
Create your basic application
> rvm use ruby-1.9.2-p290@rails3.2
> rails new MyGreatApp
Add devise to your gemfile
gem 'devise'
Run bundler again
> bundle install
3. Generate User Model
Generate devise modules
> rails generate devise:install
Generate User model
> rails generate devise User
4. Update Routes and Configuration
Add the following line to config/environments/development.rb
config.action_mailer.default_url_options = { :host => 'localhost:3000' }
Add a default route to config/routes.rb
root :to => ‘home#index’
Add some flash notices into the base template
<p class="notice"><%= notice %></p>
<p class="alert"><%= alert %></p>
Disable model loading when compiling assets. Add the following to
config/application.rb
config.assets.initialize_on_precompile = false
5. Generated User Model
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and
:omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me
end
6. Generated Migration
class DeviseCreateUsers < ActiveRecord::Migration
def change
create_table(:users) do |t|
t.database_authenticatable :null => false
t.recoverable
t.rememberable
t.trackable
t.timestamps
end
add_index :users, :email, :unique => true
add_index :users, :reset_password_token, :unique => true
end
end
7. Add before filter
Add a before filter to app/controllers/application_controller.rb
This will protect all your actions. Use an except filter in places you don’t need
> before_filter :authenticate_user!
Create a home controller
> rails generate controller home
Add a method and view for index
Remove index.html from public
9. Congratulations
You now have the basic devise working
See https://github.com/plataformatec/devise for more detailed information
about what you can do
10. Add Facebook
Now everybody wants the ability to sign in using Facebook
Add omniauth-facebook to your gemfile.
gem 'omniauth-facebook’
Do a Bundle install
11. Configure Devise
Go into the config/initializers/devise.rb and add
require "omniauth-facebook"
config.omniauth :facebook, "APP_ID", "APP_SECRET”
Go to https://github.com/mkdynamic/omniauth-facebook to get more
information about options include scopes and display options.
Go to Facebook and generate a developer key
Go to https://developers.facebook.com/apps/ select to create a new app
14. Finish configuration
Take the keys generated by Facebook and put them into config/devise.rb
Add Omniauth to your User object.
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :omniauthable
15. Setup callbacks
When Facebook returns to the application there are some routes that are
needed.
Create a Users:OmniauthCallbackController in the app/controllers/users
folder.
Will show this file on the next slide
Add a route to the new controller by updatating the devise_for in
config/routes.rb
devise_for :users, :controllers => { :omniauth_callbacks =>
"users/omniauth_callbacks" }
16. Users::OmniauthCallbacksController
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def facebook
# You need to implement the method below in your model
@user = User.find_for_facebook_oauth(request.env["omniauth.auth"], current_user)
if @user.persisted?
flash[:notice] = I18n.t "devise.omniauth_callbacks.success", :kind => "Facebook"
sign_in_and_redirect @user, :event => :authentication
else
session["devise.facebook_data"] = request.env["omniauth.auth"]
redirect_to new_user_registration_url
end
end
def passthru
render :file => "#{Rails.root}/public/404.html", :status => 404, :layout => false
end
end
17. Add finder to User model
def self.find_for_facebook_oauth(access_token, signed_in_resource=nil)
data = access_token.extra.raw_info
if user = User.where(:email => data.email).first
user
else # Create a user with a stub password.
User.create!(:email => data.email, :password => Devise.friendly_token[0,20])
end
end