I have Devise for user authentication.
I want to sign out a user with a specific id.
in my controller
def exit
#user = User.find(5)
sign_out(#user) # this line here signs out the current_user
end
The sign out command of devise, even though I pass the #user, it signs out the current_user.
How can I select a user from the database and sign him out with the devise commands?
I am assuming this is part of some admin module, where you want to sign out a particular user.
However, this is not easy to solve. Whether or not a user is signed in or not is stored in the session. So to sign out another user, you would have to have access to its session.
Note: afaik the sign_out method only works in the current session, or maybe through warden (do not know warden well enough) it could extend to all sessions this current server has ever touched. However: if you use passenger, or some form of rails server cluster (which is pretty common), afaik this will not work. I would be interested to hear otherwise, with some explanation :) The sign_out uses the given parameter to determine the scope to sign out from in (afaik) the current session.
So what we generally did was add a kind of emergency button to sign out all users: which destroys all sessions. Note this is of course only possible if you use some database or document-store backed session-store.
Alternatively you could open all sessions, and look for the correct session (for your user), and then destroy those sessions.
To read data from a specific session in stored in activerecord, you can write the following:
#session = ActiveRecord::Base.connection.select_all( "SELECT * FROM sessions WHERE session_id = '#{sess_id}'" )
Marshal.load(ActiveSupport::Base64.decode64(#session.data))
There are alternative approaches:
use Timeoutable module, and force a timeout for a user?
if you use Rememberable you could do #user.forget_me, but I am not sure that this actually affects the current session?
from the device api doc http://rubydoc.info/github/plataformatec/devise/master/Devise/Controllers/SignInOut#sign_out-instance_method the sign_out(#user) method should works. Is it possible that the current_user by chance has the id 5?
Related
I'm working on a Rails 4.2 Application and using devise gem for authentication.
For remember_me feature, devise generates a cookie remember_user_token which gets destroy after sign_out.
Is there a way such that Devise should not destroy remember_user_token ?
I tried to false the below config in the initializer
config.expire_all_remember_me_on_sign_out = false
But it didn't help.
I need that cookie after sign-out such that it will populate the login form.
Please help.
Thanks
Coupling authentication with form pre-filling isn't necessarily a good idea. You can store the login in a cookie upon successful login. You can override the create method in your SessionsController, call super to call Devise::SessionsController#create and pass it a block. The block will be executed after a successful log in and will receive the user as a parameter.
class SessionsController < Devise::SessionsController
def create
super do |user|
cookies[:login] = user.login
end
end
end
Here is the low down on cookie store. First off, everything in a cookie is there permanently once it's set or until the user deletes the cookie manually somehow. This means, that if you set user_id and user_group_id, it's there for good in the cookie until updated or deleted. This is different from a session since the session is like ram on a computer, once the browser is closed, the session closes with it as well as all of it's data.
So, this means that when you log out your user, you need to specify that their cookie empties anything you don't wan't it to have. When your user logs in, you set anything that you want the user to have while they are logged in. So, since the session and cookie are separate things completely, they never interact together unless you choose to make them. So your session will never dump its self into the cookie store unless you make it do that.
Every time your users go to your site, you could have a single handshake that makes sure that the cookie matches the db if necessary. Otherwise, you could have differing data what only gets updated on login or what not and without the handshake, the user would have to keep logging in to make sure they are still valid which defeats the purpose of having a cookie in the first place.
The downside of client side cookie storage is security concerns. Depending on how you use the cookie to store data, a person could hijack somebodies cookie on your site and pretend they are them. This can be avoided by careful design, but just assume that whatever is in your cookie store is fair game to everybody so use it carefully and for only non secret data.
Hope this helps!
I'm using devise in my rails app, but I'm also using angular within rails. In the angular context I don't have access to the typical rails methods like session or current_user or signed_in?
I'd like to check if the user is signed in, but I don't want to make a a server request to ask if there is a current_user. I'd like to just check the session or cookie store to determine this.
Is this possible?
Devise uses warden as a dependency and warden stores the information something like this inside the session if the user with id 1 is logged in
session["warden.user.user.key"] = [[1], "$2a$10$O3RAeV9c04lrlQ3T/I0PXe"]
and if not you will get it as nil.
This may be a dumb question, but I'm finishing up this app using Devise & am just wondering, is there any significant difference between authenticate_user!, user_signed_in?, & if current_user? If so, then in what cases would I not use one or the other?
Thanks
Not sure what you mean by 'significant difference', all these do different things:
authenticate_user! # Signs user in or redirect
user_signed_in? # Checks whether there is a user signed in or not
current_user # Current signed in user
Source: https://github.com/plataformatec/devise/blob/master/lib/devise/controllers/helpers.rb
Just reading the variable names you can see they are not the same thing.
authenticate_user!
This is a method to check user authentication, i.e., check if login and password matches.
user_signed_in?
This method checks if a user is signed in on the application. If there are any data inside the session that tells the application a user is signed in.
current_user
This gets the user that is logged in the application.
I'm currently working on an application that in addition to the usual visual web application goop also will expose a few RESTful API services for use by outside applications. I am using Devise to manage user authentication but I'm struggling with how to "manually" authenticate a user given certain input.
The case I have is that I want a user of the API to log in w/o actually going to the visual log in screen etc. I want them to submit a username and password and then authenticate and sign them in in my API services.
I know that you can sign a user in using the sign_in method that Devise provides, but that seems to ignore authentication entirely. here's what I wanted to do explained in a bit more detail:
Assume a GET route called connect in the user controller. the controller is replacing entirely the Devise registrations controller, but not the session one. The URL to my service would be:
<server>/users/connect
and it would expect 'email', 'password' parameters in addition to some service specific and unimportant to my question goop.
What I want to know is how to implement something that is equivalent to the following pseudocode:
def connect
user = User.find_by_email(params[:email])
password = params[:password]
# here is the part I'm pseudo coding out
if user.is_valid_password(password)
...do my stuff...
end
render :json ...etc...
end
I have been unable to find a method in the Devise source to do this--it's so generalized in so many ways that I'm likely just missing it.
Anyone have any ideas? I'm hoping not to a) have to implement my own thing and b) not have to move away from Devise. It provides me with so much for the non-API services...
thanks!
I've left out th
Devise's token_authenticatable is the way to go for this. We've successfully used it many times to do api-based logins.
In config/initializers/devise.rb
config.token_authentication_key = :nameofyourapikeyhere
In user.rb:
devise … token_authenticatable, ...
In the above, you can name the api key anything and then have your route as /users/connect?apikey=whatever (using apikey as an example). In the database, it'll be authentication_token, but it'll work fine.
To clarify, if the user has an authentication_token and it's sent in the params (or it's alias- in the above example: apikey), they'll login.
I see similar usage all the time, even in Rails guide such as http://guides.rubyonrails.org/security.html
For example, current_user returns the current logged in user, logged_in? returns whether there is a logged in user, #current_user stores
the logged in user (so no need to look into DB again), session[:user_id] stores the user id
of the current logged in user so as to know what the logged in user is on a second or later webpage request (need to look into DB), remember_token is the users table field to check against cookies[:auth_token],
so as to remember the user even when the user closes the browser (so the session ends and session cookie disappears)
Do Devise, AuthLogic, and Restful Authentication all use these names / mechanism?
I am not sure but I think they don't because restful uses logged_in? while devise uses user_signed_in? where user can be replaced by your model...