Oauth API Part 1: Facebook — The A-Z Rails Guide
Lets get started
This is going to be a very quick tutorial on how to get the Facebook API functioning within your app using the rails gem “omniauth-facebook”.
This guide can be used to implement a simple authentication with Facebook into your website to reduce that lethargic and redundant email and password entry and have a simple, well known login that really everyone should have as an option on their site.
So first things first we want to add the gem into the file that you want to implement it into, this can be simply done by adding this to your gemfile.
gem 'omniauth-facebook'
Then run “bundle install” in your Rails app directory.
Next up we want to add the ‘Rack middleware’ code to our application. So you need to create a file within:
config/initializers/ and call it “omniauth.rb”
and type in:
Rails.application.config.middleware.use OmniAuth::Builder do
provider :facebook, ENV[‘FACEBOOK_KEY’], ENV[‘FACEBOOK_SECRET’]
end
So whats going on here, with these ENV Facebook Key and Facebook Secret variables? Essentially these are the keys that you are given when you sign your app up with Facebook developers.
Now if you haven’t done that you may want to go to https://developers.facebook.com/ and add a new app.
Once you have made your application you should see on your dashboard the App ID and the App Secret.
Yu can enter the Facebook key and your Facebook Secret inside the terminal as a shell session. Or you can put the key into the raw code but this could be fairly dangerous in the likely instance where you would be using this in production.
To enter the Facebook key into your shell session you want to go ahead and type in :
export FACEBOOK_KEY=insertfacebookkeyhereexport FACEBOOK_SECRET=insertfacebooksecrethere
To check that you have not made any mistakes type in your console:
echo $FACEBOOK_KEYecho $FACEBOOK_SECRET
and see whether or not you have got it right.
It should look something like this.
Now you need to have this particular shell session open to continue running this locally. So don’t delete that terminal tab and when you start your rails server start it in that shell session.
Now we just have to change the omniauth.rb file and remove the ENV tags around it so it looks something like this.
Rails.application.config.middleware.use OmniAuth::Builder do
provider :facebook, FACEBOOK_KEY,FACEBOOK_SECRET,
:scope => ‘email,user_birthday,user_likes’, :display => ‘popup’
end
I’ve An optional thing that you may want to add is ‘the scope’ This essentially asks Facebook for a bunch of details from your User. Here we are asking our user for their email, age and all their likes. To see what other values scope can take you may want to look at
https://developers.facebook.com/docs/facebook-login/permissions/v2.2
Model
Then we want to add this to our User model in User.rb :
def self.create_with_omniauth(auth)
create! do |user|
user.provider = auth['provider']
user.uid = auth['uid']
if auth['info']
user.name = auth['info']['name'] || ""
user.email = auth['info']['email'] || ""
end
end
end
Essentially what this is doing is attempting to create a new user using a hash from facebook which we have named auth. Im going to discuss how we get that hash in just a sec. Make sure that your user has the column called ‘name’ and ‘email’ otherwise alter the 6th and 7th to be whatever your name and email column is called. Eg user.full_name or user.email_address.
Routes
Now we can set up our routes.rb file like so :
match ‘/signout’ => ‘sessions#destroy’, :as => :signout , via: [:get]match ‘/signin’ => ‘sessions#new’, :as => :signin, via: [:get]match ‘/auth/:provider/callback’ => ‘sessions#create’ , via: [:get]
Controller
Now you have made your routes you may have noticed that there is a missing sessions controller which you may want to create. Next you want to create a sessions controller of some sort that can track whether or not the user is logged in or not.
We can do this by creating a “sessions controller”
So run this in your terminal in your rails app directory:
rails g controller sessions
Now you want to add the actions within the sessions controller so that you can utilize this
def create
auth = request.env["omniauth.auth"]
user = User.where(:provider => auth['provider'],
:uid => auth['uid']).first || User.create_with_omniauth(auth)
session[:user_id] = user.id
redirect_to root_url, :notice => "Signed in!"
end
So what is going on here, we are getting the hash from facebook (auth) and checking whether they exist (User.where(provider => auth[‘provider’]). If the user does not exist it creates a new User using the method we created in the model.
Afterwards we want to add a new method within the sessions controller which can sign in a user when called.
def new
redirect_to '/auth/facebook'
end
This means that once someone has clicked the login button they will be routed to be directed to the facebook page where they can fill in the correct or incorrect page. This is done because we already set the route in the routes.rb file called signin to call the new action in the sessions controller.
Lastly we want a way for us to know whether someone has logged out of the website. We can do this by creating the destroy action.
def destroy
reset_session
redirect_to root_url, notice => 'Signed out'
end
So similar to the new action we would have a link to the “signout_path” and then this would Log a user out of your application, this will also wipe out all information of the session
View
So now you want to show this all off put this link as your login link.
<ul>
<% flash.each do |key, msg| %>
<%= content_tag :li, msg, id: key %>
<% end %>
</ul> <%= link_to 'Sign in with Facebook', signin_path %>
and this as your log out link.
<ul>
<% flash.each do |key, msg| %>
<%= content_tag :li, msg, id: key %>
<% end %>
</ul><%= link_to 'Log Out', signout_path %>
DONE!
So there we are, hopefully you liked the tutorial, I know I found it extremely useful applying within so many of my projects.
Any questions or errors please feel free to email me at edzye101@gmail.com or comment on the article. My next article will be on speed prototyping mobile applications with the ionic framework, so stay tuned!