How to access session from Warden/Devise after_authentication callback in Rails - ruby-on-rails

I'm trying to access the current session from Warden's after_authenticate callback (running underneath Devise) in Rails 3.
At the top of my application controller I want to do something like:
Warden::Manager.after_authentication do |user,auth,opts|
user.associate_with_ids(session[:pending_ids])
end
The ultimate goal is to take a list of record IDs that were stored in the session before sign up and associate them with the user model after sign in.
Any help would be much appreciated.

"auth.session" get/sets the data in the session key "warden.user.#{scope}.session".
Supposing you had saved pending_ids within your rails app:
session[:pending_ids] = ...
and you wanted to acces in the warden hook, you could access it this way:
Warden::Manager.after_authentication do |user,auth,opts|
user.associate_with_ids(auth.env['rack.session'][:pending_ids])
end
It took me a while to find that out, so I guess it might be of some help for somebody.
(originally taken from diegoscataglini.com/2012/02/09/383/manipulating-sessions-in-wardendevise, which is now dead).

You can access the session store via auth:
Warden::Manager.after_authentication do |user,auth,opts|
user.associate_with_ids(auth.session[:pending_ids])
end

You can also access the session through auth.request.session.
So your example would be:
Warden::Manager.after_authentication do |user,auth,opts|
user.associate_with_ids(auth.request.session[:pending_ids])
end

you can also find the whole session from the auth.raw_session

Related

undefined method admin Thredded Forum engine Ruby on rails

Im using a forum engine called Thredded. The installation goes well but when trying to access localhost:3000/forum , it gives me this error.
I already trying the suggested solution by adding a method admin? on user.rb but still it doesnt work.
def admin?
has_role?(:admin)
end
any ideas? thanks
Thredded maintainer here.
What version of the Gem are you using, by the way?
For the time being, if you haven't solidified how you would like your users' roles to be defined, I would consider making that method as simple as possible. For example - if the current user has an id of ... 4? or 5? Or whatever your personal user record id is - return true. Otherwise false.
Ask your user object if they are you! :)
def admin
self.name == 'Joel'
end
If the current user record has my name - then yes, I am an admin.
If there's anything I can do to help, please feel free to head over to the issues and open up a ticket. We'd be more than happy to help.
It looks like the missing method is admin, not admin?. Try defining that method instead:
def admin
has_role?(:admin)
end

How can I find a devise user by it's session id?

Given session["session_id"] is it possible to find the logged in User to which that session belongs to?
At least on my system (rails 3.2, devise 2.0.4), you can do it like this:
session is:
{"session_id"=>"be02f27d504672bab3408a0ccf5c1db5", "_csrf_token"=>"DKaCNX3/DMloaCHbVSNq33NJjYIg51X0z/p2T1VRzfY=", "warden.user.user.key"=>["User", [3], "$2a$10$5HFWNuz5p6fT3Z4ZvJfQq."]}
session["warden.user.user.key"][1][0], then is 3.
So, I'd find it as:
User.find(session["warden.user.user.key"][1][0])
I'm not sure what you are trying to accomplish but will try to answer
If you want only the User from the current session, a simple way would be to store his id on session, for example:
def login(username, pass)
# do the usual authentication stuff and get user
if logedin
session[:user_id] = user.id
end
end
Then get the current user would be something like
current_user =User.find(session[:user_id])
If what you want is finding all the users that are currently logged in, I think you need to config your app to save session at DB, because predefined is that session data is store in cookies in the browser. For more information on this check this answer
How to track online users in Rails?
EDIT: Just noticed you are using devise so the first way is actually there for you. You just need to call current_user method at any controller.
For the second way check this answer "Who's Online" using Devise in Rails
And i might add this, as i was trying to do it the other way, if you are using ActiveRecord session_store you can find all stored sessions of a user like so:
ActiveRecord::SessionStore::Session.select{ |s| s.data["warden.user.user.key"] && s.data["warden.user.user.key"][0][0] == user_id }

rails devise hook into on_login

I'm looking to hook into devise after login / after session create. How would I go about doing this?
Basically I want to set a users location every time they login, and to do that I need an after login hook of sorts.
Devise is built on Warden, so you can use Warden's after_authentication hook.
Put this in an initializer:
Warden::Manager.after_authentication do |user,auth,opts|
# do something with user
end
The remote IP address and other request info is stored in auth.request (i.e. auth.request.remote_ip).
See https://github.com/hassox/warden/wiki/callbacks
Devise updates the value of the user.current_sign_in_at timestamp on successful login. So, you could simply add a before_save filter to your User model. In that filter, check to see if the value of this field has changed, and if it has, set the users location.
BTW - I'm not sure what you mean by "location" - if you mean IP address, Devise already stores that for you.
Here's a page from the devise wiki: How To: Redirect to a specific page on successful sign in.
In summary, the recommendation is to add the following method to the application controller:
app/controllers/application_controller.rb
def after_sign_in_path_for(resource)
custom_location_for(resource) || welcome_path
end
In the above code, resource means the object (user, account, etc) that you've implemented devise authentication for. (The object that has the devise_for in your routes.)

Authlogic and Single Access Token

I am having a hard time finding a simple tutorial on how to enable single access token authentication using authlogic. There is some documentation but it isn't very helpful.
I added single_access_token to my db, I added this:
single_access_allowed_request_types :any
to my Session class. but I still don't understand how a user is authenticated using the credentials param that is passed over every call. My require_authentication before filter does a standard check for current_user like this:
def current_session
return #current_session if #current_session
#current_session = Session.find
end
def current_user
#current_user = current_session && current_session.record
end
But is that enough to work? Does the Session.find method do the magic to log the user is based on my params or do I have to create separate method that actually check if the user_credentials param is there and then find the user based on it and then log that user in. I am confused if I really am "creating" a new session everytime I use a SAT or if I'm just setting current user in a before filter every time an API call is made.
Any help would be amazing! Thanks!
I implemented a single_access_token solution with authlogic and what I had to do was add single_access_allowed_request_types :all to the UserSession model.
Then I added the following to the controller where I wanted to allow single_access_token authentication.
def single_access_allowed?
["some_action_1","some_action_2","some_action_3"].include?(action_name)
end
It looks like you're missing the controller code. So if you had two actions "get_user_info" and "update_user_info" you would add.
def single_access_allowed?
["get_user_info","update_user_info"].include?(action_name)
end
The only thing I had to do make this work was
add a field called single_access_token to my users-table
add a method called single_access_allowed? to each controller where single access should be allowed.
This method would look like this:
# method for authlogic: defines for which action the single-access-token can be used
def single_access_allowed?
(action_name == "deliver") || (action_name == "delivery_status")
end
I did not have to add anything in UserSessionsController or the UserSession object. Authlogic handles that for you. With a single-access-token only one request is authenticated, so there is not a persistent session. Each request has to send the single-access-token. Hence the name: a token to get a single access :)
Hope this helps.
The source code of authlogic is the best documentation on the single access token. This is the specific section that discusses it.
You will need to add a private method called single_access_allowed? in the controller where you are trying to let users access. The Single Access Token is passed by default as a URL encoded parameter using the name user_credentials. So to hit your controller without logging in it will be /your_route/?user_credentials=xxxxxx

How can I get authlogic to use the Rails session instead of its own cookie?

I would like authogic to never set a user_credentials cookie, and only use the standard Rails session cookie.
I see Session is included in Authlogic::Session::Session::Base after Cookies. If I log into my app and then delete the user_credentials cookie, I still stay logged in. So apparently authlogic is storing the credentials in both places and checking both places? Or ignoring the cookie but still setting it? How can I have it never set or reference the user_credentials cookie?
According to the answer to my question here…
How can I remove callbacks inserted by vendor code?
…the answer to THIS question is to do this above my UserSession definition:
Authlogic::Session::Base.after_save.delete_if{ |callback| callback.method == :save_cookie }
class UserSession < Authlogic::Session::Base
end
If you use vendored authlogic then you can prevent to user_credentials cookie by using and change some code on save_cookie method on "authlogic-2.1.5/lib/authlogic/session/cookies.rb"

Resources