autologin in authlogic Rails - ruby-on-rails

I have added auhlogic in my Rails app to authenticate users. I have also included the code from the Reset password tutorial . All of it works, the only issue I have is that once a user registers he gets automatically logged in.
Anyone worked with authlogic, what would be the best & fastest way to disable the autologin after the registration?

You can use #save_without_session_maintenance:
#user = User.new(params[:user])
#user.save_without_session_maintenance

If you will use this way:
After registration save succeeds,
session = UserSession.find
session.destroy if session
You probably can loss your Admin session, who perhaps adding the user.
So, the better way will be is just to add some options to your model user.rb:
acts_as_authentic do |c|
c.maintain_sessions = false
#for more options check the AuthLogic documentation
end
Now it should work.

After registration save succeeds,
session = UserSession.find
session.destroy if session

Related

Why Rails session is being shared between multiple users

I am trying to use session mechanism to store information of an user that is logged like this: session[:user_id]=#user_id , and that its ok.
But when a new user login in the app, the variable session[:user_id] is updated to the new user id, making the first one perform requests with an invalid id.
I used different browsers, private browsers, a browser in a Virtual Machine and another one in the host, and still got the problem.
I appreciate some suggestions. Is it normal the session being shared between multiple users? There is another way to store some specific data, and prevent the share between users? I thought that session was unique, why that variable is changing? The same happens for cookies variable.
EDIT:
application_controller
def sign_in
if(password != "" && #user_id!= "" && jenkinsip != "")
#client = JenkinsApi::Client.new(:server_url => jenkinsip, :username=> #user_id, :password=> password)
if(#client.get_jenkins_version != nil)
session[:user_id]=#user_id
end
end
end
in html
Every time session[:user_id]=#user_id is called, the session[:user_id] is being set to whatever the #user_id variable is set as.
Try using||= instead of =
set the session withsession[:user_id]||= #user_id to only set session[:user_id] to #user_id when session[:user_id] is undefined.
Follow the excellent answer of koxtra and
also have a look on devise gem for the user authentication.
Devise will do everything for you like users signin, signup, creating sessions and many more functions. You have to only install the Devise
in your rails application.

How can I sign out a devise user from the Rails console?

My devise users are "database_authenticatable" and "token_authenticatable". I've tried deleting the "authentication_token" field in the database for that user from the console, but they still seem to be able to use their existing auth token. Deleting the user entirely works, but I don't want to go that far.
Edit: for clarity. I want to use the rails console to sign out a user. i.e. run rails console and then some command.
Devise provides helper methods to do these things:
user = User.find(params[:id])
sign_in user
sign_out user
Hope this helps.
If you are using Devise you could use the below in your rails console. This works perfect for me as in my app if you are using only 1 session per user account. I am storing my sessions in redisDB.
user = User.first
user.update_attributes(unique_session_id: "")
All I had to do was clear my users unique_session_id for that user and rails kicks the user out of the session.
But for multiple sessions for the same User account this does not work.
If you want to clear all user sessions you can do the below from terminal
rake db:sessions:clear
To sign_in by Devise check this way in console:
$ rails console
include Warden::Test::Helpers
def sign_in(resource_or_scope, resource = nil)
resource ||= resource_or_scope
scope = Devise::Mapping.find_scope!(resource_or_scope)
login_as(resource, scope: scope)
end
def sign_out(resource_or_scope)
scope = Devise::Mapping.find_scope!(resource_or_scope)
logout(scope)
end
#user = User.find(1)
sign_in #user
Then open http://127.0.0.1:3000/users/sign_in to test, in my case it will bypass this page and go to home page! Same to sign_out!
You may be able to use the helpers that others have mentioned after including the necessary module:
include Devise::Controllers::SignInOut
source: Module: Devise::Controllers::SignInOut
There's also another SO question where someone shares a method that doesn't involve using Devise helpers here.
I'm not a fan of the sign_out #user pattern because, at least for the devise version I'm using, that signs out the current user, regardless of the argument I pass it. If you're storing sessions in your database then you can do this:
#user.update_attributes(current_sign_in_token: "")
TBH I don't think that's the best way to do it, but it's the best way I've seen in my own research.
I believe you can simply update the password_salt and it will invalidate the user session on their next request.
user = User.first
user.update_column(:password_salt, 'reset')
Reference:
http://www.jonathanleighton.com/articles/2013/revocable-sessions-with-devise/
For old devise versions
Seems attribute tokens save sessions:
user.tokens = nil
user.save
You can create a logout link in views->layouts->application.html.erb as:-
<= link_to 'Log Out', destroy_user_session_path, method: :delete %>
It worked for me - hope it does for others as well.

In which file the current user is set in ruby on rails?

I am new to ruby. I want to know when/where the Current user set. I know cookie will be generated for each URL request. And where the session details are stored? And where the current user set(in which file). Any one please explain briefly.
Hope you have a users table in your Rails application, so devise will automatically load all columns of users table in current_user.
It all depends on how you implement it. If you're using a library like Devise it has its own implementation, but usually such things are stored in encrypted Rails session store and on every request 'session' controller verifies visitor's cookie and only after that current_user is set to the User object from the session.
i prefer it in applicaton_controller..so that i can check where user_signed_in on every request and check the session ..if it exits then its ok else redirect_to login page..
for example in application_controller.rb
before_filter :check_current_user
def check_current_user
if current_user
#check if current user exists in our session
session[:current_user_id] = User.find(session[:current_user_id]).id
else
#if not ,then create new and set it to the session and return the current_user as u
session[:current_user_id] = User.create(:username => "guest", :email => "guest_# {Time.now.to_i}#{rand(100)}#example.com")
u.save!(:validate => false)
session[:current_user_id] = u.id
u
end
end
the above code is not perfect though..but i just wanted to show how current_user can be implemented to check current_user on every request using session and sets it in the session if there is no current_user as guest...

Rails and Authlogic: Allow only one session per user?

Is there a way to limit the number of sessions in Ruby on Rails application (I'm using Authlogic for authentication)?
I would like to allow only 1 session per user account. When the same user is logging on another computer the previous session should be expired/invalidated.
I was thinking about storing the session data in database and then deleting it when a new session instance is created but probably there is an easier way? (configuration option)
I just ran into a possible solution, if you reset presistence token you can achieve the intended behaviour:
class UserSession < Authlogic::Session::Base
before_create :reset_persistence_token
def reset_persistence_token
record.reset_persistence_token
end
end
By doing this, old sessions for a user logging in are invalidated.
Earlier I implemented it as you mentioned: add a session_key field to the users table and make sure that the current session_id is stored for the user on login:
class UserSession < Authlogic::Session::Base
after_save :set_session_key
def set_session_key
record.session_key = controller.session.session_id
end
end
Then in the generic controller do something like this to kick out a user when someone else logged in with that same account:
before_filter :check_for_simultaneous_login
def check_for_simultaneous_login
# Prevent simultaneous logins
if #current_user && #current_user.session_key != session[:session_id]
flash[:notice] = t('simultaneous_logins_detected')
current_user_session.destroy
redirect_to login_url
end
end
i do exactly what your talking about, assign a session id to each uniq session, store that id in a cookie and the associated session data in a table. Works well. My aim wasnt to limit users to a single session, but rather keep the session variables server side to prevent user manipulation.

authlogic UserSession.create(#user) giving unauthorized_record

I am trying to create a session explicitly like this UserSession.create(#user, true) but the session is not getting created, current_user is nil.
But when I do this, I get < #UserSession: {:unauthorized_record=>""}>us = UserSession.create(#user, true)
RAILS_DEFAULT_LOGGER.info(us.inspect) #=> UserSession: {:unauthorized_record=>""}
I had a look at Authlogic::Session::UnauthorizedRecord here it says
Be careful with this, because Authlogic is assuming that you have already confirmed that the user is who he says he is. For example, this is the method used to persist the session internally. Authlogic finds the user with the persistence token. At this point we know the user is who he says he is, so Authlogic just creates a session with the record. This is particularly useful for 3rd party authentication methods, such as OpenID. Let that method verify the identity, once it’s verified, pass the object and create a session.
which is exactly what I am trying to do (i am authenticating using omniauth and creating session using authlogic).
How do I fix this, so that I can get a valid session in current_user ?
I had a similar issue caused by the persistence_token being nil on the user. Reset it before creating the UserSession. So...
#user.reset_persistence_token!
UserSession.create(#user, true)
I'm not sure about the .create(object, bool) method signature, but the following works using authlogic.
class Api::ApiBaseController < ApplicationController
protected
def verify_token
return false if params[:token].blank?
#session = UserSession.new(User.find_by_single_access_token(params[:token]))
#session.save
end
end
If that doesn't work for you -- I think the #user isn't being set correctly.
If you map the active_record_store to the authlogic user_sessions table your session information will be stored in the database, and you will be able to store larger sets of data.
Inside your config folder:
config/initializers/session_store.rb
Comment out App::Application.config.session_store :cookie_store, :key => '_App_session'
Add or uncomment App::Application.config.session_store :active_record_store
Inside of config/application.rb
At the end of the class for you application add:
ActiveRecord::SessionStore::Session.table_name = 'user_sessions'
Restart your app, and any information stored in the user session will be saved in the authlogic user_sessions table.
Goto: http://apidock.com/rails/ActiveRecord/SessionStore
For more information
For now you can replace
UserSession.create #user
to
UserSession.create :email => #user.email, :password => #user.password
not a big deal.
But that caught me other way. I forgot that my user got active? == false when created. I've set it to true and session is created.
I ran into this problem today. In my case it ended up being related to CSRF tokens.
We are creating a user and session in our app in response to an OAuth callback. It appears that if the CSRF token is invalid, which would be the case when coming from a third party, authlogic won't create the user session.
Can't verify CSRF token authenticity
The fix was simple:
class Oauth::UserSessionsController < ApplicationController
skip_before_action :verify_authenticity_token, only: :callback
def new
# code removed...
end
def callback
# code removed...
UserSession.create(#user)
redirect_to root_path
end
end

Resources