Using FacebookOmniauth in Rails 5 - ruby-on-rails

I'm trying to implement Facebook Authentication and I'm stuck.
I exactly followed this guide
https://www.crondose.com/2016/12/guide-integrating-omniauth-rails-5-facebook-login-feature/
and get this error
I, [2017-11-07T00:55:47.114884 #12099] INFO -- omniauth: (facebook)
Callback phase initiated. E, [2017-11-07T00:55:47.489634 #12099] ERROR
-- omniauth: (facebook) Authentication failure! invalid_credentials: OAuth2::Error, :
Facebook API Version v2.10
I am using ruby 2.4.0 and Rails 5.1.4

You are likely getting this error because your App ID or App Secret are incorrect. Make sure your initializer has the correct Facebook API credentials:
# config/initializers/devise.rb
config.omniauth :facebook, <your App Id>, <your App Secret>,
callback_url: "http://localhost:3000/users/auth/facebook/callback"
Another Tip: Facebook now requires you to specify the fields you want back from Facebook. In other words, if you want the Facebook user's email address, you need to specifically request it. In the past it was returned by default. You can request fields by using the scope parameter in the Devise configuration.
For example, to request the Facebook user's email and name, do this:
# config/initializers/devise.rb
config.omniauth :facebook, <your App Id>, <your App Secret>,
callback_url: "http://localhost:3000/users/auth/facebook/callback",
scope: 'email,name'

Related

React-native FBSDK with rails omniauth-facebook

In rails omniauth-facebook, it requires a signed_request or a code as
params in auth/facebook/callback?
However, my problem is I can only get AccessToken from react-native fbsdk in app only, I tried using code: accessToken and signed_request: accessToken, but they doesn't seem fit, as I get this error
ERROR -- omniauth: (facebook) Authentication failure! invalid_credentials: OAuth2::Error, {"message"=>"Invalid verification code format.", "type"=>"OAuthException", "code"=>100,
I tried passing access_token: accessToken but it returns
ERROR -- omniauth: (facebook) Authentication failure! no_authorization_code: OmniAuth::Strategies::Facebook::NoAuthorizationCodeError, must pass either a `code` (via URL or by an `fbsr_XXX` signed request cookie)
Any idea how can I get signedRequest or a code from react-native fbsdk? Or how can I use access_token in omniauth-facebook?

Devise/OmniAuth Override default callback url

I'm using Devise 3.5 with Omniauth in a Rails 4 app. I've created an integration with Facebook that allows a user to connect their Facebook account to my app. Currently when the user clicks the connect button, they're sent to /user/auth/facebook and then redirected to the callback url that Omniauth generates: /user/auth/facebook/callback. What I'd like to do is manually override this callback url in some cases - meaning that I don't want to override it in an initializer - with a fully qualified url. For example, if a user starts out on http://www.example.com/ I might want to override the default callback url with http://app.example.com/user/auth/facebook/callback.
My app has dynamic subdomains and a user will (almost) always begin the authentication process on a subdomain. Unfortunately it seems that Facebook doesn't support wildcards in oauth redirect urls, which is why I want the ability to detect if a user is on a subdomain and adjust the callback url to something that I have whitelisted on my Facebook app so that the authorization process succeeds.
From what I've read, the url helper omniauth_authorize_path accepts additional arguments to be passed on as parameters. I've tried passing a custom callback path in like so, but without success:
user_omniauth_authorize_path(:facebook, callback_path: #custom_callback)
I've also tried changing callback_path to redirect_url and redirect_uri, but nothing seems to work. When I look at the link that's generated, it does indeed include the callback as a parameter in the url, but when I click the link, I'm redirected back to the default callback url instead of the custom callback url.
Here's how I solved this problem. I'm sure there are other ways, but this seems like the simplest most elegant solution I could come up with.
In config/routes.rb I set up an auth subdomain. All my Oauth connect requests will start on different subdomains and then Facebook is set up to forward those users back to the auth.example.com subdomain.
constraints AuthRedirect do
devise_scope :contact do
get '/auth/facebook/callback' => 'omniauth_callbacks#facebook'
post '/auth/facebook/callback' => 'omniauth_callbacks#facebook'
end
end
Here is /lib/auth_redirect.rb. This just checks if the subdomain is auth and captures that traffic. This is placed at the top of my routes list so as to take precedence over other subdomains.
class AuthRedirect
def self.matches?(request)
request.subdomain.present? && request.subdomain == 'auth'
end
end
Then in my client, when a user clicks the Connect with Facebook button, I send them to /auth/facebook?contact_id=<id>. From here Devise directs them to Facebook, which then redirects them back to https://auth.example.com/.
Then in OmniauthCallbacksController#facebook I can pull the user's id from the omniauth params like so:
auth = env["omniauth.auth"]
contact = Contact.find(env['omniauth.params']['contact_id'])
From here I can persist the credentials to the database and the redirect the user back to the appropriate subdomain. This solution avoids problems with CSRF tokens and more importantly does not require me to use Ruby/ERB to build the omniauth authorize path that the user is sent to when they click the connect button.
have you tried with redirect_uri ?
user_omniauth_authorize_path(:facebook, redirect_uri: #custom_callback)
EDIT: sorry I missed the second part of your post.
I actually have the same problem in production but it works perfectly on a staging environment. The only difference is about the callback url on staging which has one more subdomain *.staging.domain.com
By the way you can provide a static callback_url in the devise initializer file:
config.oaumniauth :facebook, ..., callback_url: 'url right here'
I'm on this issue this yesterday.
Either I provide a static callback url but facebook raises me an CRSF error:
omniauth: (facebook) Authentication failure! csrf_detected: OmniAuth::Strategies::OAuth2::CallbackError, csrf_detected | CSRF detected
Or I let devise set the callback_url dynamically which gonna look like
https://*.domain.com/DEVISE_MODELS/auth/facebook
and in this case I get a straight non matching/whitelisted callback url during FG loggin in process.
EDIT2:
GOOD! I made it. I'm able to get oauth login in with wildcard subdomain.
Provide a static callback_url in your devise initializer
add the domain to your session store as :
domain: ".domain.com"
With that I'm getting neither CRSF error nor nunmatching CB url/whitelisted.
Hope it'll work for you !

OAuth2::Error with doorkeeper

Whenever I try to authenticate with doorkeeper provider, I always got the following error
invalid_grant: The provided authorization grant is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client. {"error":"invalid_grant","error_description":"The provided authorization grant is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client."}
I tried with other doorkeeper clients but still have the same error
Doorkeeper client:
https://github.com/doorkeeper-gem/doorkeeper-devise-client.git
http://dev.mikamai.com/post/112508735689/oauth2-on-rails-the-client-application
Doorkeeper provider:
https://github.com/doorkeeper-gem/doorkeeper-provider-app.git
Though downgrading to gem 'omniauth-oauth2', '~> 1.3.1' is a confirmed to be a solution, in Doorkeeper's Create-a-OmniAuth-strategy-for-your-provider Wiki Page it is mentioned that in your implementation of OmniAuth Strategy for Doorkeeper the following method should be present:
# https://github.com/intridea/omniauth-oauth2/issues/81
def callback_url
full_host + script_name + callback_path
end
There is long discussion in the referred omniauth-oauth2 issue #81
I personally faced the reported error when I was trying to test my Rails 5 Devise-based Doorkeeper Provider by using a Rails 5 Devise-based Client app to allow Provider's users connect their account on my client-app.
In absence of the mentioned method in my OmniAuth::Strategies::Doorkeeper
on front-end Devise OmniauthCallbacksController was flashing message Invalid Credentials and in the client-app server logs following error was seen:
Started GET "/users/auth/doorkeeper" for 127.0.0.1 at 2017-08-22 17:45:02 +0530
I, [2017-08-22T17:45:02.386866 #14535] INFO -- omniauth: (doorkeeper) Request phase initiated.
Started GET "/users/auth/doorkeeper/callback?code=1b833bcc09651f98b0424a7afb1e60bd50fdcc765daf7d499bcefb5554457187&state=c215fd707ecd71c6ad0f6b5e58fa0d2da7210d86946d41e3" for 127.0.0.1 at 2017-08-22 17:45:03 +0530
I, [2017-08-22T17:45:03.506424 #14535] INFO -- omniauth: (doorkeeper) Callback phase initiated.
E, [2017-08-22T17:45:03.523737 #14535] ERROR -- omniauth: (doorkeeper) Authentication failure! invalid_credentials: OAuth2::Error, invalid_grant: The provided authorization grant is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client.
{"error":"invalid_grant","error_description":"The provided authorization grant is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client."}
Processing by Users::OmniauthCallbacksController#failure as HTML
Parameters: {"code"=>"1b833bcc09651f98b0424a7afb1e60bd50fdcc765daf7d499bcefb5554457187", "state"=>"c215fd707ecd71c6ad0f6b5e58fa0d2da7210d86946d41e3"}
Redirected to http://localhost:5000/
Completed 302 Found in 0ms (ActiveRecord: 0.0ms)
So adding that method to the strategy can be considered as an alternate solution.
Thanks.
I solved it by downgrading omniauth-oauth2 gem version to 1.3.1 mentioned here - https://github.com/intridea/omniauth-oauth2/issues/81

OAuth::Unauthorized 400 error with Google+ login API

I'm trying to set up Google+ login with Devise and omniauth in an app I'm working on and running into an OAuth::Unauthorized 400 error. I'm using the omniauth-google gem. My Devise config sets up omniauth for Google:
config.omniauth :google, ENV['GOOGLE_KEY'], ENV['GOOGLE_SECRET'], scope: 'plus.login'
I'm running the site locally on dev.app.com:3000, and in my app settings in the Google Developers Console I've set the JavaScript origin to be http://dev.app.com:3000 and the redirect URI to be http://dev.app.com:3000/users/auth/google/callback. I've confirmed that my key and secret are correct. What's the problem here?
I am not seeing any problem there, you can get better picture with this tutorial
[https://www.digitalocean.com/community/tutorials/how-to-configure-devise-and-omniauth-for-your-rails-application
or u can try
omniauth-google-oauth2
https://github.com/zquestz/omniauth-google-oauth2
The omniauth-google 1.0 strategy for google is deprecated. That said, nothing appears wrong with your configuration.
You're better of switching to OAuth 2.0, unless you have a very compelling reason not to. Notice that the provider symbol has changed from :google to :google_oauth2. After you switch, it should look like:
provider :google_oauth2, ENV["GOOGLE_KEY"], ENV["GOOGLE_SECRET"]

Rails-api authentications for Facebook SDK iOS connect?

I'm planning to use rails-api for providing JSON API for iOS mobile application to consume. The process:
User open the mobile app
User taps on Facebook connect
Mobile app get fb_access_token and post it to API server to identify the user
API server get user profile on Facebook by using fb_access_token
API server either create and look up the user, then response with a api_token for this particular user
Mobile app use the api_token response for all communication afterward.
Which authentication should be the best option for this app? oAuth2 or BasicAuth? I tried rails-api with doorkeeper, but it doesn't work out of the box because doorkeeper need some assets.
I am doing a basic authentication for this integrated with devise.
First i get the post parameters from the mobile application (the access_token and other stuff).
Then I use open-api to get the user details from facebook:
url = "https://graph.facebook.com/me?access_token="
begin
content = open(URI.encode(url + params[:user][:access_token]))
rescue OpenURI::HTTPError #with this I handle if the access token is not ok
return render :json => {:error => "not_good_access_token" }
end
Now Facebook returns the response
status = content.status[0]
content = ActiveSupport::JSON.decode(content)
if status == "200"
#get the email and check if the user is already in the database. If there is not email, check by the facebook id
#If the user exists return the user. If the user does not exists create new
Hope this helps
Than you can user the same code also for google, just change the url to "https://www.googleapis.com/oauth2/v2/userinfo?access_token="
I'd give omniauth-facebook at try, as it uses OAuth2 and is pretty easy to use. All omniauth strategies are rails middleware, so you just need to add gem 'omniauth-facebook' to your gemfile and add the following to config/initializers/omniauth.rb and you will be able to use /auth/facebook to log in via facebook and /auth/facebook/callback to create the user session (you might want to alter the :display key-value as pop-ups in mobile might not be aesthetically pleasing):
Rails.application.config.middleware.use OmniAuth::Builder do
provider :facebook, ENV['FACEBOOK_KEY'], ENV['FACEBOOK_SECRET'],
:scope => 'email,user_birthday,read_stream', :display => 'popup'
end
The facebook auth token will be in the request.env['omniauth.auth'][:credentials][:token] that gets returned to your callback endpoint, which you can integrate into your mobile authentication strategy. see the above link and the omniauth main page for more details.

Resources