Checking submitted token against authenticity token in database with devise - ruby-on-rails

I'm using a Chrome extension to send data to my Rails app (the staged_images controller). So I have a form that sends the data, along with an authentication token. Each user has a token which is generated by Devise, and is saved into the Users table. What I need to do now is receive that data in the controller and check the submitted token against the one stored in the Users table.
So the create action in my controller should look something like this:
def create
#user = User.find(params[:staged_image][:user_id])
if #user.authentication_token == submitted_token # this is pseudo code, don't know exactly what to say here
# execute code
else
# raise error
end
end
I'm just having trouble with the specifics of how to check the one token against the other. I'm a newbie. Help me!
Thanks

You should pass to the token controller and have a filter on the top and pass a auth_token in your call (http://yoursite/staged_images?auth_token=YOUR_STORED_TOKEN').
class staged_images < ApplicationController
before_filter :authenticate_user!
end
Devise will raise an exception if the token is invalid.
You can access the user information with the helper current_user

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

Rails Devise - current_user is nil

For some reason, current_user returns nil in my model-less controller (Subscriptions). I have found nothing on the Internet to justify this behavior...
class SubscriptionsController < ApplicationController
def new
...
end
def create
current_user # returns nil
end
end
I have a csrf meta tag :
<meta content="xxx" name="csrf-token">
I can provide more code, but I'm not sure what would be useful.
UPDATE
So thanks to the comments/answers, I have pinpointed the problem to one particular action : create.
if I add #user = current_user to the new, I can show the current user's email in my new view. However, in my create controller, current_user returns nil.
I accessed the create action through a form (submit).
Before the form is submitted, I validate the input and then send a request to Stripe to get a token out of the form. If there are no errors (validation and stripe), I then send the form.
Could that be the cause?
UPDATE 2
In my error message, my session dump is empty, while it should contains the current_user info...
It turned out the AJAX request I was making didn't carry the CSRF token. For that reason, Rails was killing my session.
I added skip_before_filter :verify_authenticity_token in my SubscriptionsController and it is now working. It might not be the most secure solution, but it works for now, so I continue to develop and come back to this issue later.
Note that when you create forms using the form_tag helper, they do not automatically generate the hidden field which holds the token for CSRF authentication. I ran into this same issue with a form I had constructed using the form_tag which I sometimes prefer using.
I fixed the issue by including the following helpers within the form:
<%= hidden_field_tag 'authenticity_token', form_authenticity_token %>
It's basically a manual way of generating the hidden field you need for the CSRF stuff.
for current_user to work you need to add before_filter :authenticate_user! to your class, like:
class SubscriptionsController < ApplicationController
before_filter :authenticate_user!
def new
...
end
def create
curent_user # returns nil
end
end
and the authenticate_user! method will set the current user for you :)
I had a similar issue but I was editing the model. So everytime I updated the model suddenly that would happen:
current_model to nil
After analyzing things, it turns out that if you leave the password in the form, when the user tries to edit some attribute, the person is then forced to write a password.
Once the form is delivered and updated, Devise does the rational thing when someone updates a password, which is to destroy the session and ask the user to sign in again.
So that was why current_model was suddenly turning to nil. Hope this helps, have a great day!

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.

Devise: after successful login hook

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

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