I'm following Ryan Bate's instructions for using Omniauth to set up third party authentication, except that I'm trying it with Facebook rather than Twitter, which he sets up in RailsCast 235.
After installing omniauth-facebook gem, and setting up the initializer
Rails.application.config.middleware.use OmniAuth::Builder do
provider :facebook, 'APP_ID', 'APP_SECRET'
end
I should be able to go to localhost:3000/auth/facebook and be presented with the Facebook login (even though it won't eventually work because we haven't set up the callback url yet) However, when i go to that url, I get this error
{
"error": {
"message": "Error validating application.",
"type": "OAuthException",
"code": 101
}
}
and the url actually changes to
https://graph.facebook.com/oauth/authorize?response_type=code&client_id=APP_ID&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fauth%2Ffacebook%2Fcallback&scope=email%2Coffline_access
On my app, I've set up Devise and followed the instructions on the Devise wiki for integrating Facebook authorization https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview
Can anyone tell me what the problem might be?
Doing a Google search on the error message revealed that quite a few people have experienced this problem in recent weeks but couldn't find anyone with a solution
I searched for 101 and I stumbled upon this page. As you can see, that error stands for Invalid API key, so I believe that the problem lies in where you defined your key.
You should set up your key and your secret in a separate file (for clarity and security) but be mindful that Rails loads files in alphabetical order so the file that defines those constants should have a name that comes before the file that configures the oauth connection. In my case, I created a file called constants.rb, which comes before devise.rb. Also, make sure to keep this file away from source control. You don't want other people to have your keys and secrets.
# config/initializers/constants.rb
FACEBOOK_KEY = 'string'
FACEBOOK_SECRET = 'string'
Then configure your connection in your devise file if you are using devise or in your omniauth file if you are using simple omniauth:
# config/initializers/devise.rb|omniauth.rb
require 'omniauth-facebook'
config.omniauth :facebook, FACEBOOK_KEY, FACEBOOK_SECRET
Now, there is a better way to do this using ENV variables. I recommend the Figaro gem as it really simplifies configuring apps.
If you want to display the facebook dialog page as a popup, you'll want to use
config.omniauth :facebook, FACEBOOK_KEY, FACEBOOK_SECRET, :display => 'popup'
And follow this question later down the road.
And, if you are on Windows, you'll need a certificate so that the SSL connection does not fail. The solution to this problem is clarified by Arcolye here.
Finally, to test your login locally, all you need to do is define your Site URL as http://localhost:3000/. That's all there is. You do not have to define your canvas URL.
In the past, I had an issue using localhost with Facebook applications. What I ended up doing was to create an entry in my host file on my computer to point fbdev.com to localhost and just used "fbdev.com" in place of localhost in the app settings on facebook.
I was getting the same error but I had forgotten to restart the server after adding my APP_ID and APP_SECRET :-P
Maybe that will help?
First, ensure you have the following in routes.rb:
# Auth callback routes
match '/auth/:provider/callback' => 'sessions#create' # This route is hit when a user gives the app permissions (the auth hash will be in request.env['omniauth.auth'])
match '/auth/failure' => 'sessions#failure' # This route is hit when a user doesn't give the app permissions
Second, ensure you have the following in config/initializers/omniauth.rb:
Rails.application.config.middleware.use OmniAuth::Builder do
provider :facebook, 'APP_ID', 'APP_SECRET', :scope => 'email', :display => 'page'
end
Third, ensure you have http://localhost:3000/ set as your Canvas URL in your Facebook app settings (https://developers.facebook.com/apps/).
You should then be able to simply redirect your users to http://localhost:3000/auth/facebook to display the authentication dialog to them.
Related
My application was working ok, and then I updated to Rails 5.0.1. After this my app no longer authenticated with Facebook and came up with the following error in the logs:
Authentication failure! csrf_detected:
OmniAuth::Strategies::OAuth2::CallbackError, csrf_detected | CSRF detected
So, in accordance to what people on StackOverflow suggested, I changed my omniauth config to include the provider_ignores_state: true setting, which suppressed that error.
config.omniauth :facebook, 'xxx', 'xxxxxxxxxxxxx',{
scope: 'public_profile,email,user_birthday,etc...',
info_fields: 'name,first_name,etc...',
provider_ignores_state: true
}
This made everything work just fine; at least in development running locally, but when I pushed the code to my staging server, the app successfully authenticates with Facebook, supposedly "signs" the user in and redirects to root_path() - and then fails authentication and redirects back to users/sign_in.
To help diagnose the problem i put a logging line above the relevant call (to see if it was being executed) such as:
logger.debug " (OmniauthCallbacksController#facebook) about to sign_in_and_redirect with id: #{#user.id} email: #{#user.email} uid: #{#user.provider_uid}"
sign_in_and_redirect #user, event: :authentication
My OmniauthCallbacksController handler for the Facebook provider there for does seem to reach 'sign_in_and_redirect' - but for reasons I cannot determine on my staging environment, it never actually saves the session to a cookie. There are no errors in the logs (in debug mode) to demonstrate there was any kind of exception thrown - except that the query to increment the log_in_count on the user doesn't actually run any query:
(2.4ms) COMMIT
(0.2ms) BEGIN
(0.2ms) COMMIT
Which looks weird (no actual update query, whereas in development i can see the log_in_count etc be incremented). But its the only other indication that something goes wrong. After that, it fails the authenticate_user! check and redirects back to the sign_in_url.
This is sending me mad - Is this a bug, or is there a fix for this issue?
We had the same error come up for omniauth-github. What fixed it for us (aside from the provider_ignores_state: true hack) was the URL in the link to github's authentication site. Originally we'd entered the entire URL for github OAuth (https://github.com/login/oauth/authorize?client_id=#{ENV["GITHUB_CLIENT_ID"]}&scope=repo), but changing it to the omniauth format of just /auth/github fixed this CSRF error (as well as a no route found error when we tried mocking out / testing our OAuth). Leaving this here in case anyone else has a similar issue in the future!
I was finally able to solve this issue, but I still don't understand WHAT went wrong. Basically, created a "empty" Rails 5 project and setup a brand new devise using the omniauth-facebook gem and settings for my main app - deployed to a cloned instance of the staging server and it worked! Most of the code was the same; but when I replaced the devise.rb initializer with the one from the new app, the old code proceeded to work on the stagingg server again. Interestingly, I coped the Omniauth config from the old one to the new app, so it must have been something wrong with another of Devise's modules...and not with Omniauth itself.
In either case, it's working now. So I will put this to bed and leave this here in case another person encounters the same problem; and while I cant say what was specifically wrong, these are the steps I used to debug/fix my particular problem.
I've got a rails app in which I am trying to implement twitter omniauth so many users can post/get to/from many twitter accounts from within the app. I have followed the railscasts (until about 3 minutes in) on the topic exactly yet am getting a 400 http response.
In my gemfile:
gem 'omniauth'
gem 'omniauth-twitter'
In /config/initializers/omniauth.rb
Rails.application.config.middleware.use OmniAuth::Builder do
provider :twitter, ENV['TWITTER_KEY'], ENV['TWITTER_SECRET'],
end
In my view I naturally have <%= link_to "Connect", "/auth/twitter" %> and in my routes.rb I have (this is the only difference to the railscast as I am not using it to signup/login users but rather to post to twitter):
get 'auth/:provider/callback', to: 'twitter_accounts#create'
get 'auth/failure', to: redirect('/')
Clicking the link in the view results in the following error:
OAuth::Unauthorized
400 Bad Request
As far as I can see my api key & secret are correct so it seems that it is not setting the http header correctly. The request and response params are empty on the rails error page. Any help would be greatly appreciated.
So as usual after tearing my hair out all day I got it to work the minute I post the question here. The issue was it was not picking up my environment variables. I had pasted in the strings directly to see if this was the problem however this also required a restart of the rails app to take effect which I had not done.
Just to extend on the answer of rorykoehler, you may also need to restart your terminal for it to pick up the environmental variables of your OAuth key and secret. If you have them stored in your bash profile you can just run
source ~/.bash_profile
in your terminal for it to pick it up.
If you are running your code in an IDE like RubyMine or Visual Studio Code you may need to restart your IDE.
Just change
Rails.application.config.middleware.use OmniAuth::Builder do
provider :twitter, ENV['TWITTER_KEY'], ENV['TWITTER_SECRET'],
end
with
Rails.application.config.middleware.use OmniAuth::Builder do
provider :twitter, 'TWITTER_KEY', 'TWITTER_SECRET'
end
I am interested in learning the omniauth authentication with rails so I checked different guides in which also contains Railscast #360.
When I create my own app with developers.facebook.com, it creates an App_id and secret for me. I set the application online and created a basic rails app that just uses the steps in the Ryan Bates guide.
This is my omniauth.rb file which generates the error that I am recieving,
OmniAuth.config.logger = Rails.logger
Rails.application.config.middleware.use OmniAuth::Builder do
provider :facebook, ENV['875829959136178'], ENV['<app_secret>']
end
I have tried to use
provider :facebook, ENV['FACEBOOK_875829959136178'], ENV['FACEBOOK_<app_secret>']
also.
When I call http://localhost:3000/auth/facebook, I am recieving an error that indicates that "the parameter app_id is required".
How I can pass this error,
It seems you misunderstand what ENV is. ENV[xxx] is a ruby method which retrieves the value for environment variable xxx. So ENV['875829959136178'] in your code snippet tries to retrieve the value for environment variable 875829959136178. It is very likely that you have not set your app_id to the environment variable 875829959136178, and thus ENV['875829959136178'] returns nil. provider is a method which takes the app_id and app_secret, but since you are giving nil as app_id, it is claiming that the app_id is not given even though it is required.
Let's say your app_id is 875829959136178 and your app_secret is APP_SECRET. The easiest way to make your app work is to give them as String.
provider :facebook, "875829959136178", "APP_SECRET"
You should note, though, that putting your app id and secret in source code as plain text is not desirable from security perspective. You should lean how to set environment variables by reading articles like this, or use gems like dotenv.
I have a Rails 3.1 app with devise 1.5.3, omniauth 1.0.1, and omniauth-github 1.0.1 as well.
config/initializers/devise.rb
config.omniauth :github, ENV['GITHUB_KEY'], ENV['GITHUB_SECRET']
config/routes.rb
devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks" } do
get '/users/auth/:provider' => 'users/omniauth_callbacks#passthru'
end
The key and secret are set up as Heroku variables and the application is registered on Github. Clicking the link you are sent to Github, authenticated and then sent back to the Github callback route with the code and all the info that the auth succeeded.
The problem is that it is getting picked up by the failure method of the users/omniiauth_callbacks controller. I added some put statements to see what the env['omniauth'] was getting sent back with.
env['omniauth.auth'] has all of the info from Github that it is supposed to.
env['omniauth.error'].response however is a an OAuth2::Response with a lot of info, the important parts being:
#parsed={"error"=>"bad_verification_code"}, #error=#<OAuth2::Error: OAuth2::Error>
I am wondering if this post is still valid since Github now has their new v3 API.
It would be possible to just put the code I need in the failure method of the callback controller but that feels kind of dirty and hackish.
Any suggestions would be much appreciated.
I am not really sure if this is going to help, but only yesterday when i was trying to authenticate with github using omniauth gem, i kinda was getting the same errors.
In the end, i ended up doing it the github way of sending the client_id,client_secret and redirect_uri to /github.com/oauth/authorize and got the callback on the redirect_uri.
Heres the link
I am using ruby-1.9, rails 3, and I am trying to login into crowd server using omniauth_crowd library. The configuration is very easy:
Rails.application.config.middleware.use OmniAuth::Builder do
provider :crowd, :crowd_server_url=>"http://some-crowd-server/crowd", :application_name=>"app-dev", :application_password=>"app-pass"
end
Also /auth/callback and /auth/failed is routed, but when I am trying to authenticate,
just after the login form when callback is called - I got:
uninitialized constant OmniAuth::Strategies::Crowd::CrowdValidator::Net
From looking into 'omniauth/strategies/crowd/crowd_validator.rb' I could
see a call Net:HTTP ... so I think I have not included some gem or else,
but not so experienced in ruby and have no idea now about what is wrong.
This sounds silly, but I ran into the same problem until I remembered to add my app server's IP to the application's list of allowed remote IPs. Try that.