#241 Simple OmniAuth
Nov 22, 2010 | 9 minutes | Plugins, Authentication
Authentication is incredibly simple to add with just OmniAuth if you don't need username/password or multiple authentications per user.
- Download:
- source code
- mp4
- m4v
- webm
- ogv
good job
You are sure doing a lot of OmniAuth screencasts, are they paying you to make them? :\
I feel like for almost a whole month it's about the same thing.
I miss the variety that the show used to have.
Regardless, thanks again for doing what you do!
Why do we need another authentication solution? What is the major difference between the plugins, would you recommend to use Devise, OmniAuth, Restful Authentication or Authlogic?
Thanks for this cast :)
I am liking it but maybe because I didn't see the previous about Omniauth ;)
Thanks for your job!
Guys, please stop bitching about a high quality free service.
Thanks
Hi ryan,
Nice and simpel. I think I'll be using this alot when Devise seems too much.
Cheers !
Amazing that you can pull off a reliable authentication solution is about 30 lines of code.
I'm creating a new application and after watching this I'm re-evaluating whether I need to have the user/password or whether I just want to go this route with simple authentication.
Thanks for doing this Ryan.
Q. You mentioned a few times that this method doesn't handle multiple authentications. Does that mean that each user can only use one authentication provider? I'm assuming so because the application obviously allows a choice of multiple authentication providers. What would happen if a user used Twitter and then tried to sign-in with Facebook? Would you get duplicate user accounts?
Ryan, that's good as always.
However, with all those OmniAuth / social networking integration, I see on thing is missing from your screencasts: testing.
I am pretty sure that lots of people who want to integrate or base their authentication solutions on, say, Twitter, think "but how the hell I use that in Cucumber tests"?
Maybe it's worth creating a screencast about: how to integrate that sign, how to mock it or provite alternative sign in just for running tests -- creating "myapp-test" twitter account and using it to sign in is not only not fun but also slow and painful.
Ryan, I'm always looking forward to watching your screencasts.
I'd really appreciate an episode or two about TDD/BDD best practices, especially concerning integration of external services, so +1 Hubert.
@Ryan can you please elaborate on how OmniAuth can work with Google API? for example access youtube data for uploading? Is there even a link between the two??
Your insight is much appreciated!
If you're looking for an example to use OmniAuth in Facebook/Sinatra applications here is a simple one I made for Heroku (heroku.com/facebook):
the code is here: http://bit.ly/faceboku
I think right now the code is not up to date in the Heroku site, but it is in github.
@Antonio we all appreciate the high quality free screencasts, it's just there has been 3 OmniAuth screencasts in the past few weeks.
if session[:user_id] is a cookie wouldn't it be very easy to fake being whatever user?
@Jake, authentication is a requirement in almost any application so I think it is worth covering thoroughly. OmniAuth is one of the greatest things to happen in the Rails authentication space in a long time, and I wanted to show off how simple it can make authentication.
There is some overlap here with the earlier episodes because I want this screencast to stand on its own. Thanks for the input though, and expect some more variety in the future.
@0x4a6f4672, the reason there are so many authentication solutions is because different apps have different requirements. OmniAuth is a current favorite of mine because it stays out of the way and allows you to fully customize how authentication works in your app.
@Nate, yes, that is correct. If one has an account with Twitter and then signs in through Facebook it will make a separate account. Supporting multiple types of authentication per account helps this problem, but does not solve it completely. This is one of the primary drawbacks of offering third party authentication like this.
@Hubert, thanks for the suggestion. Testing is something I hope to cover more of in the future.
@ippa, the session is stored in a cookie by default, but it is encrypted and not editable by the user. However it is possible for him to see the contents of it, so just be certain to not put sensitive information that you don't want the user to see there. In this case it is okay if he sees his user id.
Ryan,
Do you have any tips on how to test OmniAuth with RSpec/Capybara?
I'm trying Link without success.
Thanks,
Thanks for another great post Ryan.
@jake - Variety has it's downfalls. By doing a casts on one area Ryan has been able to cover more advanced topics.
@9x4a - Unfortunately Facebook and Twitter aren't OpenID providers, so to capture this market (and you can't just ignore it) you need a solution that covers all major ID providers.
Hi!
I'm agree with Hubert and I'm pleased to know you'll cover more testing (devise...?)
I would really like to see also how to build a RESTful API.
Thanks a lot for this screencast!
What was the textmate key combo you used to make the 'if and else' completion?
Another great 'cast
+1 for testing
Hi Rany,
good job!
I have one question.
logout only set the session to nil, that is not real logout. anyone click login button will log-in again if the twitter is not logout and the page is not closed.
how to solve this problem? logout the page and meantime logout the twitter?
Could you make a episode to solve this issue?
Thans
Hi Ryan,
Great tutorial and introduction to Omniauth.
I kept getting stuck with a 401 Unauthorized error, but a look through the comments of your previous tutorial revealed that I hadn't switched my Twitter application type to "Browser" in the Twitter control panel (Twitter sets it to "Client" by default).
It might also be helpful to note that the callback URL for development apps should be set to "http://localhost:3000/auth/twitter/callback" or similar in Twitter's control panel.
Thanks,
Chris
For everyone struggling with the 401 Unauthorized error, here's the solution:
1. You have to register your web app at http://dev.twitter.com/apps/new
2. Under your new app settings, add localhost and 127.0.0.1 (redundant but ensures it works) as registered callback urls.
3. Replace CONSUMER_KEY and CONSUMER_SECRET in omniauth.rb with the values twitter gives you after finishing step 1.
4. Restart your web server and it should work. It did for me!
Be sure to log out of twitter or use a second browser after setting up everything or you'll automatically bypass the twitter.com log in and redirect pages.
Great and simple, thank you Ryan!
When using OpenID Omniauth renders a page to enter your OpenID before it redirects you to the correct OpenID provider. The page it renders is fine enough, but how can I customize it or replace it so that I get the same design as the rest of my site?
I am also getting the 401 error code, and I don't quite understand why.
I did not specify a callback URL, but that seems to set the negotiation to "client" rather than "browser" but adding a callback in the Twitter config for this app doesn't seem to fix it either.
Is there a debugging mode for oauth which will show the details of the SSL request being sent? Or a command-line tool to issue an oauth request? Or even a simple Ruby one? :)
Ryan, the omniauth railscasts are FANTASTIC. Many of us have been waiting for a multi-service authentication solution like this for some time, and the fact that you created 3 railscasts in order to give us some in-depth understanding of this powerful gem is totally justified and appreciated. Please keep up the excellent work!!
I can authenticate against Google using OpenID but I do not get the access token, just the uid, so I cannot query any service to get data form Google. I need to get user's contacts
As said above, if you're getting a 401 error with Twitter authentication make sure of the following:
1) Registered Twitter app.
2) App should be set to "browser". If you leave the "call back url" field blank, it changes "browser" to "client app"
3) Call back url should be: http://127.0.0.1/auth/twitter/callback and NOT localhost/auth/twitter/callback
Hope that helps.
This was just awesome.
+1 for a testing episode with omniauth.
@Alfred set the callback to http://127.0.0.1/auth/twitter/callback if you want to test it locally.
@ryan thanks for all the awesome screencasts, very much appreciated!
I'm having a problem with SSL after following the railscast. After clicking on login via facebook, on the return call this error happens:
OpenSSL::SSL::SSLError
SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed
I've seen people say this is due to ruby 1.9.2, and downgrading to 1.8.7 would help (I don't want to), and some have posted a "faraday hack" to this which I can't get working.
But I'm thinking this is a configuration issue more than anything. Does anyone have a clean fix for this?
this post on stackoverflow.com explains clean fix for this verification fail.
http://stackoverflow.com/questions/3977303/omniauth-facebook-certificate-verify-failed
Looks like it's a problem with Windows, where OmniAuth (or ruby) cannot find root certificates. No clue how to solve that yet.
I agree with riccardo "I can authenticate against Google using OpenID but I do not get the access token, just the uid, so I cannot query any service to get data form Google. I need to get user's contacts"
Ryan,
Thank you. I am just getting back into coding. Your railscasts makes it fun and easy.
Joel
Very good and useful.Thanks.
Ryan: I tried setting up an application on Facebook and using the code from the railscast. I'm getting an OAuthException: "Invalid redirect_uri: Given URL is not allowed by the Application configuration."
Did you have to setup something special for testing from localhost?
Thanks.
Great and simple railscast and a nice way of auth, I've follow this one but I'm using MongoDB, and Heroku + MongoHQ with Twitter API.
I'm having a problem when another developer forks que app and runs it and also when it runs in Heroku, It's not saving the user data to the database thus not showing the name of the person and each time he wants to log in it creates another empty user.
Can some one help me?
Problem solved, the method on the User model create_with_omniauth was not working with the create! block, I had to use the one that passes the parameters
Thanks Fernando - I'm experiencing the same thing. Can you provide some more detail about what you did instead of create_with_omniauth? Thanks!
Actually, I just ran 'heroku run rake db:migrate' and that's all I needed to get it to work
I was very excited to see this almost working but I get the following error after the callback:
You have a nil object when you didn't expect it!
You might have expected an instance of ActiveRecord::Base.
The error occurred while evaluating nil.[]
The application trace is empty, and the last call in the full trace is:
oa-oauth (0.1.6) lib/omniauth/strategies/oauth.rb:24:in `callback_phase'
Any ideas?
I'm having this exact same issue, any solution yet?
Omniauth is really useful,
Hi Ryan,
When does a user types in his login id and password using OmniAuth? Am I missing something?
Thanks,
Alex
I used Google as an OpenID provider and needed the user's email address.
In the create_with_omniauth method use this:
auth["user_info"]["email"]
to get the email address of the user. You'll have to add a new field to the User model to save it tho.
Brilliant. Thanks.
I put together a Rails 3 example app (with a detailed walk-through tutorial) that shows how to use Mongoid with OmniAuth (plus optional RSpec, Cucumber, and Haml): https://github.com/fortuity/rails3-mongoid-omniauth. It goes into more detail than the Railscast for those who need a full starter app.
That's why he is a ruby hero =)
I think the RailsCast are very illustrative, but all of them are buggy. All tutorials that I did until today had a bug or issue wasting valuable time.
This tutorial has a big issue:
uninitialized constant SessionController
I don't now what to do this time. Any idea to solve this?
did you miss the 'rails g controller sessions' by any chance?
I'm just learning rails so I'm sure this is a real novice mistake but I've gotten to where I have created a twitter dev account and added the consumer_key and consumer consumer_secret to the omniauth.rb file.
My link is setup like this:
<%= link_to "Sign in with Twitter", 'https://api.twitter.com/oauth/authorize' %>
But I'm receiving an error message from twitter:
"Woah there! This page requires some information that was not provided. Please return to the site that sent you to this page and try again
Hey Ryan,
Thanks for the great tutorials!
I've a question - I want an additional field (besides name, email) from the user for sign up that's not present in the 'auth' returned. So I'll have to redirect the user to a page with a form
to get the additional fields as inputs and then create the new user. Please let me know what's the best way to do this.
def create
auth = request.env["omniauth.auth"]
user = User.find_by_provider_and_uid(auth["provider"], auth["uid"])
if (user == nil) #user doesn't exist in database, create new user
user = # directs to a page with a form for additional fields and use some info from auth to create new user. how do i do this?
end
session[user_id] = user.id
redirect_to root_url, :notice => "Signed in!"
end
Thanks!
Aswath
why in this episode "/auth/twitter" suddenly redirects to twitter authentication page? its neither in routes file nor there is such an action on the controller, please explain, im struggling to understand.
That's the whole point, and that's done by the omniauth gem itself. Once you authenticate against twitter, the 'callback' URL is visited which is handled within the Rails app - note the custom route to handle it in
routes.rb
There is a good post on how to use this with Cucumber:
http://pivotallabs.com/users/mgehard/blog/articles/1595-testing-omniauth-based-login-via-cucumber
It made me think though (which is never good),
is it not possible to log in as any user simply
by providing the correct provider and uid.
This worked once, but now whenever I try it, I get:
I think this is because Twitter only lets the app do something once (add itself?) and it is trying to do it again.
Does anyone know how to fix this?
Thanks!
Try restarting your Rails server.
Apropos my post above, it seems twitter have changed their data structure, so it was getting a null. Try this:
Thanks @Swart, I was getting auth/failure?message=invalid_response message. The RailsCast code was updated but not the ASCIICast version, so I was using the incorrect "user_info" key.
If we want to run this tutorial in higher versions of rails > 3.1.
please add gem 'prototype-rails' in your Gemfile.Since prototype js has been used in this screencasts.
or try to remove this from your environment file
config.action_view.debug_rjs = true
Great episode but I wasted some valuable time on a silly issue. The omniauth-aouth gem is gobbling the app errors and its pretty difficult to debug them.
In this case,the following needs to be changed in the user model to
instead of
Hopefully an easy question, but I haven't worked out the answer yet.
If someone knows my UID and the callback URL, what is to prevent them from skipping the actual authentication to log in as me? There must be some other piece of information in the request that lets me validate the source?
Hi I keep getting:
NoMethodError in SessionsController#create
undefined method `[]' for nil:NilClass
This appears after I logged into Twitter and before redirecting back to the callback page.
i've solved it thanks. Thanks to Raison D'souza's comment
What is the purpose ||= in ruby?
@current_user ||= User.find(session[:user_id]) if session[:user_id]
Same stuff as
Where do I get the CONSUMER_KEY/CONSUMER_SECRET for omniauth-google?
@Ryan is we can not fetch the email id while login with twitter??
Amazing railscast. Don't think I've seen a clearer explanation of anything, ever! Thanks!
The RailsApps project has a Rails 4.1 rails-omniauth example application with an in-depth OmniAuth Tutorial.
If anyone runs into a runtime error when trying to display the omniauth in yaml using this code
RuntimeError raise request.env["omniauth.auth"].to_yaml
Try this instead
render :text => "<pre>" + env["omniauth.auth"].to_yaml