devise + omniauth facebook : current_user nil after sign_in - ruby-on-rails

We have registration and login via facebook using rails, devise, and omniauth. We're hosted on Heroku, running two web dynos.
sometimes login with facebook is failing. The actual handshake between our app and facebook is fine. In fact, in the code below #user is an actual User model instance, the omniauth data Hash contains all of the data from FB, sign_in seems successful AND the current_user is set.
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def facebook
#user = User.find_for_facebook(env["omniauth.auth"].extra.raw_info, current_user)
logger.info ">>>>>> OMNIAUTH FB BEGIN >>>>>>"
logger.info env["omniauth.auth"].inspect
logger.info "User is: #{#user.inspect}"
session["devise.facebook_data"] = request.env["omniauth.auth"].except("extra")
flash[:notice] = I18n.t "devise.omniauth_callbacks.success", :kind => "Facebook"
res = sign_in(:user, #user)
logger.info "Sign In Result: #{res.inspect}"
logger.info "CURRENT_USER: #{current_user.inspect}"
logger.info "<<<<<< OMNIAUTH FB END <<<<<<"
respond_to do |format|
format.json
end
end
end
The client-side does a redirect (different actions based on login context) to another URL on our site upon successful login. At that URL, we check for current_user... but current_user is returning nil. If the login process is repeated a few times, eventually it works.
We're on
Rails 3.2
Devise 2.1.2
Omniauth-facebook 1.4.0
Ruby 1.9.3 p194

I don't know whether this is really the solution to what you've described, but I wonder whether this:
#user = User.find_for_facebook(env["omniauth.auth"].extra.raw_info, current_user)
should read as this?
#user = User.find_for_facebook(request.env["omniauth.auth"].extra.raw_info, current_user)
that's how mine is anyways. NOt really sure that would explain why your app is arbitrarily letting the user sign in however.

Related

Are Cookies in Rails Site based (app based)?

I have decided to deal with sessions in my application on a cookie level, so I have a session controller that looks like:
module Xaaron
class SessionsController < ApplicationController
def new
end
def create
user = Xaaron::User.authenticate_user(params[:user_name], params[:password])
if sign_in(user)
if params[:remember_me]
cookies.permanent[:auth_token] = user.auth_token
else
cookies[:auth_token] = user.auth_token
end
flash[:notice] = "Welcome back, #{user.first_name}."
redirect_to root_path
else
flash[:alert] = "You have entered incorrect credentials."
redirect_to login_path
end
end
def destroy
cookies.delete(:auth_token)
redirect_to root_path
end
end
end
My application is kind of a "gate keeper" application so the user can login into say site.com and from there go to product1.site.com, their information such as user name, api key, all that jazz is shared between these two apps via promiscuous gem.
How ever my question is:
is the cookie created in site.com viable for use in product1.site.com thus allowing me to use specific helper methods such as: current_user in product1.site.com to see if said user is logged in?
The purpose for this is that if user A is not signed into site.com they cannot access product1.site.com
RFC 6265 has the answer in section 4.1.2.3. If the cookie domain attribute is set to dom.ain, then the cookie is sent by the user agent when making requests to dom.ain, www.dom.ain, sub.dom.ain, and other subdomains of dom.ain. You can control the cookie domain attribute via the domain key in the cookies hash, like this
cookies.signed[:secure_session] = {domain: 'dom.ain', value: "#{user.salt}#{user.id}"}

I keep getting "Not found. Authentication passthru" for Facebook connect login with Devise - Need debug advice

I've seen a couple people ask a similar question, but I really need advice on how to debug this issue. I'm trying to setup facebook connect using Devise using the article here: https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview
Every time I click on the login with facebook link, I get the blank page that just says: Not found. Authentication passthru. Clearly, there is no JavaScript/ajax setup on the prior page to pull up the facebook login screen.
I know this can work on my system, as I made a blank project with the exact same code from the link above and it works. Of course, my project is much bigger with lots of code, so I'm trying to figure out what in my project is causing this not to fire.
Any help on how to debug is appreciated.
Thanks!
This is the #passthru code from the devise source.
def passthru
render :status => 404, :text => "Not found. Authentication passthru."
end
Which means that devise is unable to recognize your facebook callback. Make sure you setup up your callback controller properly or post your user controller code.
I ran into the same error. I was missing the Facebook callback controller (app/controllers/users/omniauth_callbacks_controller.rb):
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
# ...
def facebook
respond_to do |format|
format.html {
#user = User.find_for_facebook(request.env["omniauth.auth"])
if #user.persisted?
sign_in_and_redirect #user
set_flash_message(:notice, :success, :kind => "Facebook") if is_navigational_format?
else
session["devise.facebook_data"] = request.env["omniauth.auth"]
redirect_to new_user_registration_url
end
}
end
end
end
This code references the method "find_for_facebook" in my user model (app/models/user.rb):
class User < ActiveRecord::Base
# ...
def self.find_for_facebook(auth_hash)
user = User.where(:email => auth_hash.info["email"]).first
unless user
user = User.create(
username: auth_hash.info["nickname"],
email: auth_hash.info["email"],
password: Devise.friendly_token[0,20])
end
user.provider = auth_hash["provider"]
user.uid = auth_hash["uid"]
user
end
end
Make sure to restart your development server so all the changes get picked up.

How to check if you are logged into Facebook in the GEM koala

The application is written in Ruby on Rails, using Koala GEM to support Facebook auth.
How to check if a given user. log on to our app now.
I have a code to login
def index
#oauth = Koala::Facebook::OAuth.new (APP_ID, SECRET, URL_US)
#a = #oauth.url_for_oauth_code (:permissions => "email")
redirect_to #a
end
I would if I worked Koala already logged as such it calls redirect_to client_app_path and how not to redirect_to #a
You could use this:
def index
#oauth = Koala::Facebook::OAuth.new (APP_ID, SECRET, URL_US)
facebook_user_id = #oauth.get_user_from_cookies(cookies)
#a = #oauth.url_for_oauth_code (:permissions => "email")
if facebook_user_id.present?
redirect_to client_app_path
else
redirect_to #a
end
end
I am not sure of the output of #oauth.get_user_from_cookies(cookies) if you are not connected to Facebook, maybe it's an empty string instead of nil. If so, change the if statement to redirect properly if connected or not.
Seen here: https://github.com/arsduo/koala/wiki/OAuth in Cookie Parsing

Omniauth Session expires when browser is closed

In my rails 3 app I use Omniauth for the user authentication part (fb/twitter).
Actually I follow this:
https://github.com/RailsApps/rails3-mongoid-omniauth
https://github.com/RailsApps/rails3-mongoid-omniauth/wiki/Tutorial
But,
when I close the browser session expires and I need to login again.
How can I keep the session for returning users?
Any help would be greatly appreciated!
What you want is not difficult, you only have to set a permanent cookie when the session is created and then retrieve this value when you set the current user.
In your ApplicationController, just change your current_user method to:
def current_user
return unless cookies.signed[:permanent_user_id] || session[:user_id]
begin
#current_user ||= User.find(cookies.signed[:permanent_user_id] || session[:user_id])
rescue Mongoid::Errors::DocumentNotFound
nil
end
end
And in your SessionsController, modify your create to set the cookie if user wants to:
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
cookies.permanent.signed[:permanent_user_id] = user.id if user.really_wants_to_be_permanently_remembered
redirect_to root_url, :notice => "Signed in!"
end
Devise offers this functionality through its Rememberable module. OmniAuth integrates easily with it through the (you'd never guess it) OmniAuth module. It's even mentioned in the second link you posted!
Please make sure the cookie policy that your rails app follows does have sensible settings for your use case (see the link in my comment above). All I can imagine right now (knowing what I know, sitting where I sit) is that the cookie(s) ha(s/ve) properties that are suboptimal/undesirable in your context.
Please check the cookie settings in a browser debug/development tool such as firebug, firecookie or the chrome development tools.
Sorry, that's all I can come up with given my knowledge of the problem. Feel free to contact me again with more details on your cookie- and testing-setup.
My 2Cents.
Here is how it works for me:
def google_oauth2
#user = User.from_google(google_params)
if #user.persisted?
#user.remember_me = true
sign_in #user
........
end
end
There is another way to do it

Registered user log in for the first time using Facebook - Omniauth

I am following Ryan's instruction on Omniauth here.
However, there is a scenario that Ryan didn't cover:
User already have an account with us, but they signin with Facebook/Linkedin for the first time. In this case, I would like the user to sign-in using traditional sign-in (via Devise), and if he succeeds, create a new Authenication object for future logins.
In particular, when registered user clicks "Signin with Facebook" for the first time, I'll get a hash from callback that contains his Facebook account information. But I don't want to create an authentication for him yet. Instead, I will redirect him to my Devise sign-in page, allowing him to put username and password in. If he signs in successfully, I would like to create a new Authentication object from the information I got from Facebook callback.
What would be a good way to store Facebook hash temporarily, until user logs in successfully?
Thank you.
Below is the code from AuthenticationController.rb that Ryan created, which did not handle the situation I just mentioned:
def create
omniauth = request.env["omniauth.auth"]
authentication = Authentication.find_by_provider_and_uid(omniauth['provider'], omniauth['uid'])
if authentication
flash[:notice] = "Signed in successfully."
sign_in_and_redirect(:user, authentication.user)
elsif current_user
current_user.authentications.create!(:provider => omniauth['provider'], :uid => omniauth['uid'])
flash[:notice] = "Authentication successful."
redirect_to authentications_url
else
user = User.new
user.apply_omniauth(omniauth)
if user.save
flash[:notice] = "Signed in successfully."
sign_in_and_redirect(:user, user)
else
session[:omniauth] = omniauth
redirect_to new_user_registration_url
end
end
end
Instead of doing this, could you just check to see if there is another user with the same email when they register with facebook? If so, add facebook as a second method of authentication, and if not, create a new account.

Resources