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
Related
Kind of new to rails and I'm in need of some help!
I'm using the devise gem and I'm trying to find the current user that just signed-up or that is trying to sign-in by setting up a cookies[:email].
I have the following inside the sessions_contoller.rb and the registrations_contoller.rb
def create
cookies[:email] = params[:user][:email]
#and some other code as well
end
def destroy
super
cookies.delete :email
end
The following method is to find the user according to the email:
def current_client
if cookies["email"].present?
User.find_by_email(params[:email])
end
end
If I check from the browser I can see the email cookie is there, not sure how to check from the rails c though.
But the current_client method doesn't seem to be working.
Any idea what might be wrong here?
Thanks in advance!
While setting the value of cookie, try to set it as below:
cookies[:email] = {:value => params[:user][:email], :domain => :your_domain, :expires => 30.days.from_now}
Also you can check the cookie by printing its value in controller to verify it was set or not.
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}"}
Is it possible to only allow certain google accounts to log on? for example myname#mycompany.com is host through google (they are actually google account). I want only user with the #mycompany to be able log on is this possible?
do you do this with devise or google api?
Thank you :)
If you are using omniauth-google-oauth2, you can accomplish domain restrictions using by providing a value for hd option during initialization.
Rails.application.config.middleware.use OmniAuth::Builder do
provider :google_oauth2, ENV['GOOGLE_CLIENT_ID'], ENV['GOOGLE_CLIENT_SECRET'], {
scope: 'email, profile',
hd: 'mycompany.com'
}
end
It's also possible to handle this in your controller which is handling the callback. You can deny users depending on values provided in request.env["omniauth.auth"].
class OmniauthCallbacksController < Devise::OmniauthCallbacksController
def google_oauth2
auth_details = request.env["omniauth.auth"]
if auth_details.info['email'].split("#")[1] == "yourdomain.com"
# do all the bits that come naturally in the callback controller
user = User.from_omniauth(request.env["omniauth.auth"])
if user.persisted?
flash.notice = "Signed in Through Google!"
sign_in_and_redirect user
else
session["devise.user_attributes"] = user.attributes
flash.notice = "You are almost Done! Please provide a password to finish setting up your account"
redirect_to new_user_registration_url
end
else
# This is where you turn away the poor souls who do not match your domain
render :text => "We're sorry, at this time we do not allow access to our app."
end
end
end
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.
I have a RoR application that's using the RESTful Authentication plug-in. Everything works great. I recently enabled cookie based authentication and that works fine too. The problem is that I want to change the default landing page when the user is authenticated using a cookie. I want to have a cookie authenticated user redirected to the same page they are redirected to upon successful login from the login form. They are always directed to the original request URL. I'm racking my brain on this as I thought I understood how it works and every change I make seems to have no impact.
I suspect this is something simple but I'm obviously missing it. I'd appreciate any feedback, guidance or suggestions you might offer.
I solved the problem but it's a bit ugly in my opinion. Here's what I did.
In the cookie authentication method I set a session variable indicating the cookie login method was used.
def login_from_cookie
user = cookies[:auth_token] && User.find_by_remember_token(cookies[:auth_token])
if user && user.remember_token?
session[:cookie_login] = true **# this is my addition**
self.current_user = user
handle_remember_cookie! false # freshen cookie token (keeping date)
self.current_user
end
end
Then in the :before_filter set_current_user I just check for that variable and redirect if it is set making sure to set the variable to nil.
def set_current_user
Authorization.current_user = current_user
if session[:cookie_login]
redirect_to :controller => :users, :action => :search
session[:cookie_login] = false
end
end
It's not pretty but it does work. I'm definitely open to any suggestions about how to clean this up.
You could add this line to the session controller after a successful login:
redirect_to :controller => 'dashboard', :action => 'index'
I'm using Bort so maybe this isn't part of Restful_Authentication itself but there is a successful_login method in the sessions controller that uses this restful_auth method:
redirect_back_or_default( root_path )
which is in defined in authenticated_system.rb
def redirect_back_or_default(default)
redirect_to(session[:return_to] || default)
session[:return_to] = nil
end
Can't you just have your routes setup so that
map.root :controller => :users, :action => :search
And then have a before_filter that checks to make sure that some "logged in" parameter is set? This param would just need to be set whenever the user logs in, either via cookie or via normal means. Then, whether the cookie authentication happens or normal auth happens, it will go to the default page. Maybe I'm misunderstanding the problem.
Restful Authentication stores the original URL that was trying to be accessed when the request is made. All of you have to do is prevent it from storing that value OR clear that value when a cookie authentication is performed and then the user will get redirected back to your default page.
I would probably do it like this in authenticated_system.rb
def login_from_cookie
user = cookies[:auth_token] && User.find_by_remember_token(cookies[:auth_token])
if user && user.remember_token?
self.current_user = user
session[:return_to] = nil # This clears out the return value so the user will get redirected to the default path
handle_remember_cookie! false # freshen cookie token (keeping date)
self.current_user
end
end
The is session[:return_to] = nil
Then just make sure you have set your default path in your sessions controller and you should be all set. The code in your sessions controller should be something like this:
redirect_back_or_default(the_path_you_want_to_send_them_to)