Devise: after successful login hook - ruby-on-rails

In my rails app, I am using devise for my authentication system. I have a situation in which I want to encrypt some data using a key that is based off of the user's password. The easiest way that I can think to do this is during a successful sign in, to generate the user's private key from their plain-text password (passed in from the login form) and store that in the user's session. I don't really want to ask the user to enter their password more than once.
Does devise provide a way to specify a callback function after a successful login? Or is there a better way to do this?

http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/DatabaseAuthenticatable#after_database_authentication-instance_method
In the user model where you're using devise create a after_database_authentication instance method.

Assume you have Devise resourse User with attribut password, then you can access user password after login in after_sign_in_path_for, which is called after sucessful login.
# app/control,lers/application_controller.rb
class ApplicationController < ActionController::Base
def after_sign_in_path_for(resource)
password = param[:user][:password]
do_cool_stuf_with_password(password)
#...
return url_for_root
end
end

Related

Devise Reset Authentication Token

I am using Devise and I have an authentication_token that I pass in the header of my API calls
How do I reset that token when the user logs out?
I want a new token generated every time they are logging in.
You can try using the after_database_authentication callback on the model.
def after_database_authentication
self.update_attribute(:auth_token, generated_token)
end
def generated_token
...
end

Accessing newly singed up user in Rails app using devise

I am currently making Rails app using devise.
After a new user signs up, I need to access newly singed up user's information to run my customized function.
However it seems like devise's current_user is nil since the user is not logged in yet until the user confirms the email.
I essentially just need to check whether user's confirmed_at is nil.
Is there a way to do this?
I would do this in the User model with a callback:
# in app/model/user.rb (assuming you have a User model)
after_create :run_customized_function
private
def run_customized_function
# whatever need to be done with this user, for example:
# Rails.logger.info("User##{id} just signed up with email '#{email}'")
end

Displaying User Password With Devise Confirmation Page

I'm attempting to display a users password along in his confirmation page sent by the Devise mailer. The confirmation page is the default
Welcome test0#test.com!
You can confirm your account email through the link below:
Confirm my account
However, I wish to have
Welcome test0#test.com!
Your password is currently DASADSADS
You can confirm your account email through the link below:
Confirm my account
How do I access the user object in the view? Do I need to override the mailer controller with a custom one? If so, how do I tell what the methods of the current mailer do (tried looking at documentation but can't find any clues)?
I noticed that #email and #resource are used in the view. Can I use any of these to access the current password in its unhashed form?
Note that I am sending this email manually with user.find(1).send_confirmation_instructions
Although this can be done, I would caution very strongly against doing so. Hashed passwords are specifically used so that the password cannot be recreated easily. Passing the original password back to the user will cause it to be sent back in plain text which sort of defeats the whole purpose. Also, shouldn't the user already know their password (they did type it in twice after all)?!?
To do this, you would need to capture the original (unhashed) password in the registration create action and send the email at that point (passing along the password). You can do this by overriding the sign_up method - you can do this in an initializer:
class Devise::RegistrationsController < DeviseController
def sign_up(resource_name, resource)
sign_in(resource_name, resource)
resource.unhashed_password = resource_params[:password]
resource.send_confirmation_instructions
end
end
Alternatively, you can derive a new controller from Devise::RegistrationsController and put this override code there (the recommended approach - but then again, this whole operation isn't really recommended). You'll need to add the unhashed_password accessor for this to work:
class User < ActiveRecord::Base
attr_accessor :unhashed_password
end
And then you can update your confirmation view (at app/views/devise/mailer/confirmation_instructions.html.erb) to contain this:
<p>Your password is currently <%= #resource.unhashed_password %></p>
Devise save password in encrypted form: You can decrypt it using,
Generate new migration:
$ rails g migration AddLegacyPasswordToUser legacy_password:boolean
invoke active_record
create db/migrate/20120508083355_add_legacy_password_to_users.rb
$ rake db:migrate
Using legacy_password method in following code you can decrypt your password:
class User < ActiveRecord::Base
...
def valid_password?(password)
if self.legacy_password?
# Use Devise's secure_compare to avoid timing attacks
if Devise.secure_compare(self.encrypted_password, User.legacy_password(password))
self.password = password
self.password_confirmation = password
self.legacy_password = false
self.save!
else
return false
end
end
super(password)
end
# Put your legacy password hashing method here
def self.legacy_password(password)
return Digest::MD5.hexdigest("#{password}-salty-herring");
end
end
You can just use request.request_parameters[:user][:password] to get the plain text password on the create or update action.

Optional password during authentication with Devise

If I've got a rails application and I'd like to add authentication to with Devise, how would I allow users who have a null password in the database to sign in without one?
I'm interested in hearing answers along the lines of the lifecycle and what files I'd have to author to get it done.
Step 1: Allow the record to be saved.
Step 2: Sign in the record
To allow the record to be saved, you'll want to do validations yourself. I describe here how to do custom validations: http://jessewolgamott.com/blog/2011/12/08/the-one-where-devise-validations-are-customized/ .... In your case, you'll want to remove the password validations.
To sign in the record, you'll need to have a custom sign in path. You can override the devise sessions controller, but this could do the trick:
class SessionsController < ApplicationController
def create
user = User.find_by_email!(params[:session][:email])
sign_in user
redirect_to root_path
end
end
It turns out, Devise is built on Warden. This means that I only have to create my own custom Warden strategy:
https://github.com/hassox/warden/wiki/Strategies

Authlogic - Authentication via basic HTTP authentication

I want to use "authenticate_ with_ http_ basic" but I just can not get it
working.
In my RoR app Authlogic is working fine and I'm using User Sessions for that. While keeping that method as it is now i need to use authenticate_with_http_basic.I have a iPhone SDK app and now I need to fetch some products from my webapp and display as list. So I'm assuming that i need to send the request to my webapp like this; http://username:password#192.168.1.9/products/
So my question is to validate this username and password and what I need to do to my UserSession Controller?
You don't need to do anything with UserSessionController, since that controller would only handle login form submit and logout.
Authlogic and authenticate_with_http_basic is irrelevant to each other. If you want to authenticate via HTTP basic, you just need to create a method to authenticate using method provided by Rails, and put that method on the before_filter. By logging in via HTTP authentication, I assume that the username and password should be mandatory for every request.
So finally, your ProductsController would be something like this
class ProductsController < ApplicationController
before_filter :authenticate_via_http_basic
# In case you have some method to redirect user to login page, skip it
skip_before_filter :require_authentication
...
protected
def authenticate_via_http_basic
unless current_user
authenticate_with_http_basic do |username, password|
if user = User.find_by_username(username)
user.valid_password?(password)
else
false
end
end
end
end
Authentication via HTTP Auth is now integrated into AuthLogic, and it is enabled by default.

Resources