For the past 2 hours, I have been trying to debug a weird issue in devise which is not letting me login.
Here's the stuff I'm referring too:
password
=> 'vinodsobale'
password == 'vinodsobale'
=> true
resource.valid_password?(password)
=> false
resource.valid_password?('vinodsobale')
=> true
Attaching the screenshot as well:
Note: I have enabled debugger inside devise so the above code is devise internal code.
To me, it looks like a issue in Devise.secure_compare
.
Source: (StackOverflow)
I'm trying to use a different/custom layout named "devise" for the sign_in action. I found this page in the devise wiki, and the second example even says you can do it per-action (in this case, sign_in
action), but it shows no example of doing that. Someone on IRC told me I could try this:
class ApplicationController < ActionController::Base
protect_from_forgery
layout :layout_by_resource
def layout_by_resource
if devise_controller? && resource_name == :user && action_name == 'sign_in'
"devise"
else
"application"
end
end
end
But it does not seem to be working as it's still loading the default application layout. I would appreciate any help.
Source: (StackOverflow)
How can I retrieve the CSRF token to pass with a JSON request?
I know that for security reasons Rails is checking the CSRF token on all the request types (including JSON/XML).
I could put in my controller skip_before_filter :verify_authenticity_token
, but I would lose the CRSF protection (not advisable :-) ).
This similar (still not accepted) answer suggests to
Retrieve the token with <%= form_authenticity_token %>
The question is how? Do I need to do a first call to any of my pages to retrieve the token and then do my real authentication with Devise? Or it is an information one-off that I can get from my server and then use consistently (until I manually change it on the server itself)?
Source: (StackOverflow)
I am using the rails 4.0 branch of devise along with ruby 2.0.0p0 and Rails 4.0.0.beta1.
This is the kind of question where I am checking if I'm doing it the right way, or if there are other things I should be doing. I'm sure a lot of people moving to Rails 4.0 are facing the same problems (after googling for similar things).
I have read the following links:
Now using devise I created a User model, I created the following controller using the above gists (and made sure to include it in my routes file). My extra parameters are first_name and last_name.
class Users::RegistrationsController < Devise::RegistrationsController
def sign_up_params
params.require(:user).permit(:first_name, :last_name, :email, :password, :password_confirmation)
end
def account_update_params
params.require(:user).permit(:first_name, :last_name, :email, :password, :password_confirmation, :current_password)
end
private :sign_up_params
private :account_update_params
end
Is there anything else I should be doing? Is this the best way of doing things from now on (since dropping attr_accessor). My forms seem to be working fine (both the new and update). The gists said to use "resource_params" but that always gave the "Unpermitted parameters" error in my server log.
Source: (StackOverflow)
I have added a field to the sign-up form that is based on a different model, see How do I use nested attributes with the devise model for the gory details. This part is working fine.
The problem now is when I save, it is failing in the create action of the registrations controller that is supplied by devise with an Activerecord::UnknownAttributeError
on this field (company).
I am assuming I need to override the registrations controller, or is there a better/easier way I should be approaching this?
Source: (StackOverflow)
I'm building a simple api with Rails API, and want to make sure I'm on the right track here. I'm using devise to handle logins, and decided to go with Devise's token_authenticatable
option, which generates an API key that you need to send with each request.
I'm pairing the API with a backbone/marionette front end and am generally wondering how I should handle sessions. My first thought was to just store the api key in local storage or a cookie, and retrieve it on page load, but something about storing the api key that way bothered me from a security standpoint. Wouldn't be be easy to grab the api key either by looking in local storage/the cookie or sniffing any request that goes through, and use it to impersonate that user indefinitely? I currently am resetting the api key each login, but even that seems frequent - any time you log in on any device, that means you'd be logged out on every other one, which is kind of a pain. If I could drop this reset I feel like it would improve from a usability standpoint.
I may be totally wrong here (and hope I am), can anyone explain whether authenticating this way is reliably secure, and if not what a good alternative would be? Overall, I'm looking for a way I can securely keep users 'signed in' to API access without frequently forcing re-auth.
Source: (StackOverflow)
What's the best way to enable users to log in with their email address OR their username? I am using warden + devise for authentication. I think it probably won't be too hard to do it but i guess i need some advice here on where to put all the stuff that is needed. Perhaps devise already provides this feature? Like in the config/initializers/devise.rb you would write:
config.authentication_keys = [ :email, :username ]
To require both username AND email for signing in. But i really want to have only one field for both username and email and require only one of them. I'll just visualize that with some ASCII art, it should look something like this in the view:
Username or Email:
[____________________]
Password:
[____________________]
[Sign In]
Source: (StackOverflow)
I just installed Devise in my app, configured the views and everything. However, when I click the sign up button I get this error:
NameError in Devise::RegistrationsController#create
undefined local variable or method `unconfirmed_email' for #<User:0x00000103721b28>
Why is this? Also, I'm using tlsmail to send emails out through my gmail business account. This might be a problem as well.
Source: (StackOverflow)
Where is devise implementation of authenticate_user!
method?
I have been looking for it and have not found it so far.
Source: (StackOverflow)
I'm using devise for user auth, but I have nice mockups for the signup, login, etc. pages.
I've already done the rails generate devise:views User
command and have all of the views in the views folder, however, when I replaced the registration/new.html.erb with my own new.html.erb, nothing changes nor looks different. It's as if I had done anything.
Anyone know what I'm doing wrong or at least how to successfully customize devise views
P.S. Is it important to note that I changed the route of devise/registration#new to /signup?
Source: (StackOverflow)
I have used RESTful techniques to generate a model (in fact, I am using Devise gem, which does that for me), and I have added new fields called first_name and last_name to the model. Migration went fine. I added attr_accessor :first_name, :last_name to the model and expected it would just work. But when I try to mass-assign new instances with Doctor.create({:first_name=>"MyName"}) etc., I am getting errors saying I can't mass-assign protected attributes.
I thought the whole point of using attr_accessor was to get around the protectedness of the fields of a model. Can you help me make sense of this message?
Edit: oh, and by the way the records do not get created either. I thought they should be since this is just a warning, but they are not on the database.
Edit2: here is my model
class Doctor < User
has_many :patients
has_many :prescriptions, :through=> :patients
validates_presence_of :invitations, :on => :create, :message => "can't be blank"
attr_accessor :invitations
end
and the schema, which doesn't have the first_name and last_name because they are created in the users table, which is the ancestor of doctors. I used single table inheritance.
create_table :doctors do |t|
t.integer :invitations
t.timestamps
end
and this is the migration to change the users table
add_column :users, :first_name, :string
add_column :users, :last_name, :string
add_column :users, :type, :string
EDIT: here is the seed file. I am not including the truncate_db_table method, but it works.
%w{doctors patients}.each do |m|
truncate_db_table(m)
end
Doctor.create(:invitations=>5, :email=>"email@gmail.com", :first_name=>"Name", :last_name=>"LastName")
Patient.create(:doctor_id=>1, :gender=>"male", :date_of_birth=>"1991-02-24")
Source: (StackOverflow)
I'm using rails 3.2 and devise 2.0 and I'm quite new to Rails.
Requirements
I'd like to achieve the following:
- have 2 or more "user" models, eg. Member, Customer, Admin
- all models share some required fields (eg. email and password)
- each model may have some unique fields (eg. company for Customer only)
- some fields may be shared but not have the same validation (eg. name is required for Customer but optional for Member)
- all fields must be filled during the registration process, so the forms are different
- the login form should be unique
Possible solutions
I googled and searched StackOverflow for quite a long time, but nothing seems right to me (I'm a Java guy, sorry :) and now I'm quite confused. Two solutions came up:
Single devise user
That's the most frequent answer. Just create the default devise User and create relations between Member-->User and Customer-->User.
My concern here is how can I achieve a customized registration process for each model? I tried different things but all ended as a mess!
Multiple devise users
This solves the custom registration process, and seems right to me, but the unique login form is a blocker. I found an answer on SO (Devise - login from two model) which suggests to override Devise::Models::Authenticatable.find_for_authentication(conditions).
That seems complicated (?) and since I'm new to rails, I'd like to know if that could work?
Thanks for your advice!
Source: (StackOverflow)
After I install devise and create a user model. I rake db:migrate
and then I rake routes
. I then get a error with "undefined method `devise_for' for #". What could be causing this error?
Source: (StackOverflow)
My Rails app uses Devise for authentication. It has a sister iOS app, and users can log in to the iOS app using the same credentials that they use for the web app. So I need some kind of API for authentication.
Lots of similar questions on here point to this tutorial, but it seems to be out-of-date, as the token_authenticatable
module has since been removed from Devise and some of the lines throw errors. (I'm using Devise 3.2.2.) I've attempted to roll my own based on that tutorial (and this one), but I'm not 100% confident in it - I feel like there may be something I've misunderstood or missed.
Firstly, following the advice of this gist, I added an authentication_token
text attribute to my users
table, and the following to user.rb
:
before_save :ensure_authentication_token
def ensure_authentication_token
if authentication_token.blank?
self.authentication_token = generate_authentication_token
end
end
private
def generate_authentication_token
loop do
token = Devise.friendly_token
break token unless User.find_by(authentication_token: token)
end
end
Then I have the following controllers:
api_controller.rb
class ApiController < ApplicationController
respond_to :json
skip_before_filter :authenticate_user!
protected
def user_params
params[:user].permit(:email, :password, :password_confirmation)
end
end
(Note that my application_controller
has the line before_filter :authenticate_user!
.)
api/sessions_controller.rb
class Api::SessionsController < Devise::RegistrationsController
prepend_before_filter :require_no_authentication, :only => [:create ]
before_filter :ensure_params_exist
respond_to :json
skip_before_filter :verify_authenticity_token
def create
build_resource
resource = User.find_for_database_authentication(
email: params[:user][:email]
)
return invalid_login_attempt unless resource
if resource.valid_password?(params[:user][:password])
sign_in("user", resource)
render json: {
success: true,
auth_token: resource.authentication_token,
email: resource.email
}
return
end
invalid_login_attempt
end
def destroy
sign_out(resource_name)
end
protected
def ensure_params_exist
return unless params[:user].blank?
render json: {
success: false,
message: "missing user parameter"
}, status: 422
end
def invalid_login_attempt
warden.custom_failure!
render json: {
success: false,
message: "Error with your login or password"
}, status: 401
end
end
api/registrations_controller.rb
class Api::RegistrationsController < ApiController
skip_before_filter :verify_authenticity_token
def create
user = User.new(user_params)
if user.save
render(
json: Jbuilder.encode do |j|
j.success true
j.email user.email
j.auth_token user.authentication_token
end,
status: 201
)
return
else
warden.custom_failure!
render json: user.errors, status: 422
end
end
end
And in config/routes.rb:
namespace :api, defaults: { format: "json" } do
devise_for :users
end
I'm out of my depth a bit and I'm sure there's something here that my future self will look back on and cringe (there usually is). Some iffy parts:
Firstly, you'll notice that Api::SessionsController
inherits from Devise::RegistrationsController
whereas Api::RegistrationsController
inherits from ApiController
(I also have some other controllers such as Api::EventsController < ApiController
which deal with more standard REST stuff for my other models and don't have much contact with Devise.) This is a pretty ugly arrangement, but I couldn't figure out another way of getting access the methods I need in Api::RegistrationsController
. The tutorial I linked to above has the line include Devise::Controllers::InternalHelpers
, but this module seems to have been removed in more recent versions of Devise.
Secondly, I've disabled CSRF protection with the line skip_before_filter :verify_authentication_token
. I have my doubts about whether this is a good idea - I see a lot of conflicting or hard to understand advice about whether JSON APIs are vulnerable to CSRF attacks - but adding that line was the only way I could get the damn thing to work.
Thirdly, I want to make sure I understand how authentication works once a user has signed in. Say I have an API call GET /api/friends
which returns a list of the current user's friends. As I understand it, the iOS app would have to get the user's authentication_token
from the database (which is a fixed value for each user that never changes??), then submit it as a param along with every request, e.g. GET /api/friends?authentication_token=abcdefgh1234
, then my Api::FriendsController
could do something like User.find_by(authentication_token: params[:authentication_token])
to get the current_user. Is it really this simple, or am I missing something?
So for anyone who's managed to read all the way to the end of this mammoth question, thanks for your time! To summarise:
- Is this login system secure? Or is there something I've overlooked or misunderstood, e.g. when it comes to CSRF attacks?
- Is my understanding of how to authenticate requests once users are signed in correct? (See "thirdly..." above.)
- Is there any way this code can be cleaned up or made nicer? Particularly the ugly design of having one controller inherit from
Devise::RegistrationsController
and the others from ApiController
.
Thanks!
Source: (StackOverflow)