#360 Facebook Authentication
Jun 25, 2012 | 12 minutes | Plugins, Authentication
This will show how to create a new facebook application and configure it. Then add some authentication with the omniauth-facebook gem and top it off with a client-side authentication using the JavaScript SDK.
- Download:
- source code
- mp4
- m4v
- webm
- ogv
Hi Ryan,
Did you try to set this header from your app in order to prevent the javascript error?
response.headers["Access-Control-Allow-Origin: facebook.com"]
Don't have time to try it right now, I can try it tomorrow maybe.
Greetz
Benoist
The error is due to a violation of the same-site origin policy caused by the AJAX calling to a script on another domain. It would be better to use jQuery or raw Javascript to append a new script element to the head and allow the browser to interpret it as a static asset.
This is great! Could you possible revise integrating omniauth with devise? I'm using omniauth-facebook and devise and I have a couple weird issues. One of which is when a user first registers for my site devise won't autolog them in even though I used signin_and_redirect. The other problem is facebook keeps adding #=_ to my url after I login.
+1
Ditto
+1
+1
Please go through https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview
This solved my problem. Hope works for you also.
+1 I'm having the same problem of facebook keep adding the #=_. I looked it up and i t seemed like that was intentionally done to indicate that nothing has happened.
@supriya surve, i'm guessing everyone here that's having a problem has already gone through the docs there. I certainly have (read it multiple times), but still can't figure out what the problem is.
http://stackoverflow.com/questions/7131909/facebook-callback-appends-to-return-url
This might help. Issue raised for Omniauth Facebook #441
I saw this earlier but didn't help..
http://stackoverflow.com/questions/11240756/facebook-authentication-with-devise-omniauth-facebook-not-doing-anything
I uploaded my problem on stackoverflow
+1. I am also looking forward to the revised devise with omniauth.
I figured this out. I posted an answer to my own question - see if this helps:http://stackoverflow.com/questions/11240756/facebook-authentication-with-devise-omniauth-facebook-not-doing-anything/11256425#11256425
Basically, I forgot to add it to the attr_accessible on the User model, and I also had to unchange the changes I made to the after_sign_in_path_for method that devise comes along with. And also, dont forget to create a migration to add the columns provider and uid to the user table.
Quick question, I notice that the facebook sign-in popup uses SSL, but the app you create does not. Would you recommend adding SSL everywhere, in order to stop session attacks? Heroku charge a whopping $20 per month to enable SSL endpoints.
Where do you set the ENV variable ?
If you are on linux or mac, then you can put it a file called
/home/.bashrc
export NAME_OF_VARIABLE=xyz123
Tip: Use your real variable name, there's usually no need for quotation marks, and the export keyword is required as shown above. Finally, you should make sure your variable name is written in UPPER_CASE.
Remember to save and close the file, before reloading your command prompt.
Is there a way to put ENV variables in a file?
How does the ENV hash work?
You can try https://github.com/bkeepers/dotenv, it's simple and does what it says
I tried this, but it doesn't specify WHERE the .env file needs to be saved. A little help would be appreciated. Thanks.
Try figaro: https://github.com/laserlemon/figaro
When testing manually what is the best way of avoiding the dependency on Facebook?
You can pass a :display =>"popup", to open the omniauth dialog in a popup:
It's a similar experience to the Javascript SDK when combined with the code from:
Turn omniauth facebook login into a popup (StackOverflow)
Has anyone figured out a way to load the authorization dialog in a modal window rather than a popup? From what I can tell, this currently isn't possible.
I followed the screencast step by step and couldn't get the login redirection working.
After approving the app with FB's dialog, i'm being redirected to a permissions request dialog and then all I get is a blank page as seen in the screenshot:
the contents of the dialog is the following javascript snippet
I'm suspecting Facebook's strict policies with XSS and same-site origin requests but it worked for Ryan...
Maybe one of you wonderful readers have bumped into this "undebuggable" weird behavior?
UPDATE: deployed the test app on Heroku and everything works so I guess it is some facebook domain issue. Still no go for localhost.
For local development you can use the domain http://lvh.me. Some kind soul purchased it and pointed it to localhost.
Useful. Thanks Alex!
Hi Yarin,
I'm getting the exact same thing. All I get is a blank dialog with the Facebook permissions url (https://www.facebook.com/dialog/permissions.request?....). Does anyone know if there is there some magic to getting localhost to play nicely? It seemed to work for Ryan with no problems.
i did the same as explained in the cast (only server-side), but when i click on the link i always get only a code back like this:
{"code"=>"AQAlwnb3kkcjBB0qkPJbPFeTlroBOVO5_daVPuqUEeghQtQqK8cjlGf5qqaQOHXiFpQXsHY07jwHsVEo07i35YBhN33kruM94KV2NpZSWj_Vsw4CrfTUSUD6-GT4y_THeojXtLUJXWyM9TF3XnnFrBA_ECCn5nhoNynxB6KyUm8M8Uw23C2YeeJJuJd9-dUrLkg",
"provider"=>"facebook"}
and therefore the
TypeError in SessionsController#create
can't convert nil into an exact number
does anyone know what i am doing wrong?
thank you!
Daniel
app/models/user.rb:8:in
at'
block in from_omniauth'app/models/user.rb:8:in
app/models/user.rb:3:in
tap'
from_omniauth'app/models/user.rb:3:in
app/controllers/sessions_controller.rb:3:in `create'
Have you solved the problem?
See my answer above.
Getting the same error. Jeesh.
I found the answer to this. It's in the:
user.oauth_expires_at = Time.at(auth.credentials.expires_at)
For my account, auth.credentials.expires_at does not exist. So Time.at was converting nil. For my account, I only had:
auth.credentials.token
auth.credentials.expires
So put some validation checking in there for that line and you should be good to go.
Care to share your validation check?
just modify your codeline
user.oauth_expires_at = Time.at(auth.credentials.expires_at)
also to a single line:
user.oauth_expires_at = Time.at(auth.credentials.expires_at) unless auth.credentials.expires_at.nil?
@cbmeeks thank you!
Thanks for sharing that...solved the issue I was having this evening without having to spend a lot of time searching.
Hi, I followed the tutorial step by step and I get:
can't convert nil into String error when I click the sign in with facebook link.
I forked the source code and It does not work either.
I get the same error.
How can I solve this?
Any Luck Here Tarik?
Getting the same error after authenticating Facebook via javascript based asynchronous call.
It works if I use the standard method where I am directed to login via Facebook website.
Thanks indeed for any help.
Any luck guys?
Having same issue with me as well. :(
Ryan, could we use Koala to to the same job for auth and for get user info, right? What your opinion about Koala x omniauth-facebook?
Thanks.
+1
So how would i go about redirecting a new user to a profile model so that they could fill in extra details about themselves?
With the facebook.js.coffee.erb the auth variable, in user model, is nil! I don't understand why! Someone can I help?
I am using devise with omniauth-facebook, it works fine and I can login and logout.
I encountered two errors
for the first error, a solution on StackOverflow suggest
<script type="text/javascript">if (window.location.hash == '#_=_')window.location.hash = '';</script>
is this right approach to handle this bug and how do I resolve csrf detected error when using javascript sdk.
Sorry, I'm first time to use omniauth. and have question about ENV["FACEBOOK_APP_ID"]
Should I replace FACEBOOK_APP_ID to my facebook app id, or I should set FACEBOOK_APP_ID in somewhere?
You should set an environment variable called FACEBOOK_APP_ID containing your actual id. If you're working on a unix type system you can do that with the export command, but that will set it just for the current session. You can also set the variable right before the rails command:
FACEBOOK_APP_ID="your app id" rails s
. If you want it to persist you should append the export call to your .bashrc file (or .zshrc or the rc file of your terminal).export FACEBOOK_APP_ID="your app id"
.Thanks, but it seems set in my computer, doesn't it?
I ask this question on the stackoverflow as well. Someone said :
"You just add this ENV['FACEBOOK_APP_ID'] = "yourapikey" into
config/environments/development.rb
orconfig/environments/production.rb
"What's the different?
I also met some problem .
When I put the first line
OmniAuth.config.logger = Rails.logger
in this file, I runrails s
, and the terminal said:When I delete the first line
OmniAuth.config.logger = Rails.logger
, it works.How can I solve this problem?
Has anyone encountered the following errror?
After approving the facebook app, I get:
OmniAuth::Strategies::OAuth2::CallbackError
Anyone help or comments would be greatly appreciated
Seems there is a problem with omniauth-facebook v1.4.1 (see http://stackoverflow.com/questions/11597130/omniauth-facebook-keeps-reporting-invalid-credentials)
thanks daniel!
Thank you!
Did anyone find another solution than just using gem 'omniauth-facebook', '1.4.0' ?
Hi every one.. if iam using mongoid(mongo database for creating user) with out having devise gem on it.. how can i find current user.
rails g model user provider uid name oauth_token oauth_expires_at:datetime
invoke mongoid
create app/models/user.rb
invoke test_unit
create test/unit/user_test.rb
create test/fixtures/users.yml
this is way i created user model, in model, i change the code like...
class User
include Mongoid::Document
def self.from_omniauth(auth)
auth.slice(:provider, :uid) do |user|
user.provider = auth.provider
user.uid = auth.uid
user.name = auth.info.name
end
end
end
in application.html.erb file how i need to get current user.. here we are using current_user right but if iam raise that, iam getting nill is current user.
It could be worth mentioning that if you are using the 1.4.1 version of omniauth-facebook gem, you could be running into this error:
OmniAuth::Strategies::OAuth2::CallbackError
By instead using the 1.4.0 version this problem was resolved, at least for me.
The issue causinh this problem is the one reported here
This does not prevent the error message in the JavaScript console, though.
Hello everyone,
I followed the tutorial and got fb-connect working with localhost:3000. I am using version 1.4.0 as suggested in the comment above and am not using javascript popup. Now, when I uploaded my work on development server and click "sign in with facebook", I get
No route matches [GET] "/auth/facebook"
The only difference between localhost and dev server is the app on dev server has dev.mydomain.com:3000 as its domain and that's the domain I entered on fb app setting page. Is having a subdomain the problem? Any help would be appreciated.
Here are gems on both my localhost and dev server. Thanks!
Using oauth2 (0.8.0)
Using omniauth (1.1.0)
Using omniauth-oauth2 (1.0.3)
Using omniauth-facebook (1.4.0)
hii everyone,
@pkohli1 - That's actually how it's supposed to work. Logging out on your app logs out the user from your system but that user should not be logged out of Facebook.
maybe a bit off subject but i am using omniauth to collect linked in profile data and am a bit stuck when it comes to getting info outside the - raise request.env["omniauth.auth"].to_yaml
I am trying to gain as much info as possible about signed in users such as past positions and location
here is the current user.rb save/create code
any help would be appreciated
Robbie
ps. i have had a look at this link but not sure how to go about getting the values into the db - [https://developer.linkedin.com/documents/profile-fields#profile]
Whenever I use the JS/Coffee code to log in using a pop-up I got:
Turns out this is due to a bug in omniauth-facebook 1.4.1 -- downgrading to 1.4.0 made it work.
Also, instead of hardcoding the path in the coffee file, I used:
Perhaps a little unwieldy - and I'd like to know a shorter way of doing this, but it works.
The above is akin to calling
user_omniauth_callback_path(:facebook)
In views etc.
PS ! Found out about the error from:
Link
I keep getting "Could not authenticate you from Facebook because "Csrf detected". And can't figure it out... can anyone help?
After dropping down to the 1.4 version of omniauth-facebook, I no longer receive the user's email in the auth hash. I tried adding
:scope => 'email'
to the OmniAuth provider config, but to no avail.Anyone have an idea?
Naturally, I figured out the answer immediately after asking for help.
I needed to add the scope parameter to the JS:
thank you a LOT!
If you are using coffeescript then use:
Thank you for this. Took me 2 days to realize I was loooking in the wrong place
Has anyone figured out the issue with why chrome won't work locally with the JDK but Safari will?
there's a message on chrome with "Unsafe Javascrtipt attempt to access frame with URL....... but there is no message like that in Safari.
I do have the FB.init setup properly
+1 I have the same issue
+1
+1
+1
+1, works in Firefox, but not in IE or Chrome.
I was getting this error because my app was in sandbox mode and I was using real users. Once I created test users and use them instead, it started working.
That's one possible reason, but alas there are others...
Anyone find a solution finally? I thought it was to pass
signed_request
params manually but that didn't work for me. Wrote a huge question about this here in case anyone can help: http://stackoverflow.com/questions/25819058/facebook-noauthorizationerror-after-passing-signed-parameters-manuallyHey guys,
I followed the tutorial precisely but I am getting an error such as this:
NoMethodError in SessionsController#create
Rails.root: /Users/raybesiga/Documents/Sites/foodie
Application Trace | Framework Trace | Full Trace
app/models/user.rb:29:in
from_omniauth'
create'app/controllers/sessions_controller.rb:3:in
However my user.rb file is as below:
and my sessions_controller.rb file is as follows:
Any idea why I get this error?
you misspelled omniauth ... you wrote 'ominauth'
user = User.from_omniauth(env["ominauth.auth"])
Hi,
Is there a way to use the same Facebook app for both production and development?
I mean, in FB app settings you can provide only one Site URL, which for development is usually http://localhost:3000/ and for production your actual URL where the application is hosted.
Of course you could create a separate "development facebook app" with a different APP ID and SECRET and localhost:3000 as login callback url, but it would be nice, if OmniAuth Facebook and the same fb app could handle both development and production.
You either have to change the Facebook Site URL or you hosts file. To edit your hosts file when you want to work on your app locally:
sudo nano /etc/hosts
Add:
127.0.0.1 www.yourdomain.com
Save the hosts file
Restart your browser.
Restart rails using port 80:
rvmsudo rails s -p 80
Now when you go to www.yourdomain.com it should be hitting your local dev machine.
In the above code instead of changing window.location, is there a way to do this through ajax.
Doing this through ajax doesnt seem to work.
Hello, I have a question. If I already have my own authentication / authorization systems but I want to add the option to login with facebook, this gem could help me????
Hello guys,
I'm getting the following error:
LoadError in SessionsController#create
Expected /Users/jeanosorio/rails_projects/andinitos/app/models/user.rb to define User
Does anybody has an idea, what is the problem???
Thanks
I am getting an error after allowing permission in the dialog. It looks like Facebook is routing the callback to an SSL page, which my localhost is not configured to handle.
The error:
Faraday::Error::ConnectionFailed
SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed
Does anyone know how I can get the callback to force a non-secure URL?
I solved this issue by modifying omniauth.rb. Basically you need to pass the path to your certificate, it's an issue related to openssl.
provider :facebook, Facebook::APP_ID, Facebook::SECRET, {:client_options => {:ssl => {:ca_file => "/opt/local/share/curl/curl-ca-bundle.crt"}}}
You can find more info and the link to the certificate in the following links:
https://github.com/arsduo/koala/wiki/HTTP-Services
http://martinottenwaelter.fr/2010/12/ruby19-and-the-ssl-error/
If you're having trouble with Pow and environment variables, be sure to store them in .powrc in your project root.
Hi Ryan,
I have seen your one of the video of face book in which you use a localtunnel gem.I do the same process and localtunnel generate a URL for me.
But i am confused because when i enter that URL in my address bar then after some time error occur.
I read about localtunnel gem , but none of that is useful for me.
I have some questions:-
Q Can you tell me how to use localtunnel ?
Q Is that URL is Accessible when i enter it in my address bar ?
Q If not accessible than what is a use of it?
Q If that URL is not working than how it be public available ?
As per my knowledge We can give our ip address with port number and any one can use it . Than were we are using localtunnel gem ?
Hope you understood the situation ?
Thanks
Regards
Fahim Babar Patel
Anyone getting this error on every single page? I can go to /auth/facebook and it redirects to Facebook for the auth, but when I come back I get this error. I also get this error on any other page I attempt to access:
"undefined method `helper_method' for main:Object"
Also, nothing populates in my users table.
This is coming from the bottom of application_controller.rb, which says in the show notes:
helper_method :current_user
Notice that if you don't want your users to be logged out from Facebook when logging out from your app you should change your javascript file to the following code. Any better solutions for that?
PS: I'm doing it just because I find it annoying to logout users from Facebook without asking them to do so.
hi ryan what if i want to add facebook comments to my rails application, how do i go about it so i can add this comments too to my database
provider :facebook, ENV['FACEBOOK_APP_ID'], ENV['FACEBOOK_SECRET']
This line of code will generate this error
(get { "error": { "message": "Missing client_id parameter.", "type": "OAuthException" } } )
for some versions of omniauth(i think from 1.0 + ). For this to work, change that line into:
provider :facebook, FACEBOOK_APP_ID, FACEBOOK_SECRET
Thanks, it works.
Has anyone had an issue where the popup window that opens doesn't close after it finished authenticating? Everything else is working properly but the window does not close after its done.
How to make this login work on page tab?
Could someone point me to a resource to learn how to set it up so that I can use facebook authentication for an app on heroku and localhost:300 at the same time?
FYI... Rails 4 deprecates
match
routes. As far as I can tell, replacing "match" with "get" in config/routes.rb makes this episode Rails 4 friendly. Maybe that is obvious, but I was surprised the'auth/:provider/callback'
route wasn't a POST.+1
match
isn't deprecated in Rails 4; you just have to specify the HTTP method:match
is still useful for paths that respond to multiple HTTP methods.+1
+1
+1
After upgrading to the latest jquery and adding Facebook 'Like' buttons, the sign-in popup window stopped functioning.
Firebug reported:
FB.getLoginStatus() called before calling FB.init().
To fix this, just move the "FB.init" call to the last position in facebook.js.coffee.erb.
Worked for me - not sure why.
Hey Ryan, thanks for the great tutorial.
There is one issue with auth permissions. current_user variable defined in application controller doesn't fully works with this standart Auth protection to access just a current actions in controller:
class SomeController < ApplicationController
before_filter :authenticate_user!, :except => [:action]
...
Hey! I have found how to Sign in with standart Devise method using "omniauth-facebook" gem:
http://stackoverflow.com/questions/16941850/sign-in-to-devise-using-omniauth-facebook
(In this tutorial, current_user var is set in application controller, but not signed in with Devise method)
I am trying to combine the information from episode 235 and this episode. I am unsure what to set the routes as. By following 235 my route is :
Following this episode, my routes would be :
If I follow 235 and try to combine it here, do I need to override the devise session controller create method?
I ultimately need to do all this via ajax.
Heroku does not recognizer ENV variables on precompile.
You should move this 'coffee' code to the layout in order for this example to work,
I have an issue that each time I close my browser, I get signed out from my website and have to log in again on revisit. I do keep signed in at facebook.com...
Anyone got any idea what is going on?
I was able to get everything working, but I've discovered a quirk that I can't seem to figure out. When you click sign out, the fb-root div inserted by facebook.js.coffee.erb disappears. That means if you sign in again immediately, you'll be redirected to Facebook instead of getting the pop-up window. Reloading the page makes it reappear, but it would be nice to get it to behave consistently. I'm using rails 4 if it matters.
Hi Ryan,
I keep getting this error:
{
"error": {
"message": "Error validating application. Invalid application ID.",
"type": "OAuthException",
"code": 101
}
}
The FB application ID matches the one that was given to me...so I don't really know what's up.
Before I watched the Railscast, I actually followed directions from: https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview
Here's a link to my repo: https://github.com/margotungsten/splurgeorsave
Could you help?
Thanks!
I'm having the same issue. I think I have troubles with the callback URL, the new menu for Apps in Facebook is not simple and direct as the old one, so I can't find where to write the address down.
Any LucK?
I'm getting a "The parameter app_id is required" when navigating to http://localhost:3000/auth/facebook. I scanned the comments didn't see anyone with the same issue. It's been two years since the tutorial. I followed it to a T. The only thing different is in routes.rb when I change match to get
Are
application_controller.rb
andsessions_controller.rb
in the root?Just checking since it doesn't specify
app/controllers/*
in the file name.If you want to use Facebook authentication in https://teatro.io/ first create special stage application in Facebook and then set domain as project-token.ttrcloud.com and authentication urls as http://project-token.ttrcloud.com. It will work on any branch of this project.
provider :facebook, ENV['FACEBOOK_APP_ID'], ENV['FACEBOOK_SECRET']
how to assign the values to facebook appid and facebook secret
plz let me know
thanks
Use figaro gem. https://github.com/laserlemon/figaro
This solution is much easier, and cleaner, and easier to maintain than secrete.yml in my opinion.
set keys in application.yml which figaro specifies you create, and set keys in that file like so
FACEBOOK_SECRET: '13103103779'
Then it will be available to access throughout your application with the syntax like so
provider :facebook, ENV['FACEBOOK_APP_ID'], ENV['FACEBOOK_SECRET']
If you're using Devise, put the above line in the devise.rb initializer file, and not the omniauth.rb initializer file. When using Devise and omniauth together, you don't need an omniauth.rb file. The syntax for the devise way is this
config.omniauth :facebook, ENV["FACEBOOK_APP_ID"], ENV["FACEBOOK_SECRET"]
If you face the problem with mongoid problem:
MONGO MOP Can't canonicalize query: BadValue unknown operator: $oid
Make sure you change current_user method:
https://github.com/liziane/Cookbook/commit/128a9aeee392b8e680d86fdad35ac258846cedd6
User creation needs to be modified slightly to play nicely with the new strong parameters in Rails 4. This error happens in 4.1.5 and might have been recent.
Issue and fix at stackoverflow
where(auth.slice(:provider, :uid))
needs to bewhere(provider: auth.provider, uid: auth.uid)
I was struggling with that issue... almost smacked my head against the walls. Really don't know why it took me too much to come and read the comments.
Thank you very much!
Nice Site
Nice article,
Super website with a great sharing and amazing stories is ur web.. please keep doing what u do now.. thanks to you, It's a great sharing and really informative.. will keep following ur web. thanks to you and ur great website.
I'm also having the same issue. I think I have troubles with the callback URL, the new menu for Apps in Facebook is not simple and direct as the old one, so I can't find where to write the address down.
here is amazing things which you will sure like
One of the best article i found on this website. Keep on writing.
thnaks for share
One of the best article i found on this website. Keep on writing.
Great post
Nice 1
This is really nice post. This post has really impress me through its quality writing. In this article i watch some new writing style which is really nice.
So thanks for sharing such a awesome post.
@Jen Did you ever figure out why you were getting 500 internal server error when hitting /auth/facebook? I'm experiencing the same issue. Any help is appreciated!
Hey I am having a similar issue, no idea on next steps could you help?
@avadhbsd Use omniauth-facebook gem version 1.4.0. According to many comments elsewhere. 1.4.0 is the "most/last stable version". Some folks mentioned that certain versions of rails conflict with the omniauth-facebook gem also. See this link for more: http://stackoverflow.com/questions/13425757/rails-facebook-login-error-with-omniauth-facebook-omniauthstrategiesoauth2