EzDev.org

devise

devise - Flexible authentication solution for Rails with Warden. Devise « Plataformatec Blog


Weird issue with devise valid_password?

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:

enter image description here 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)

different layout for sign_in action in devise

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)

rails - "WARNING: Can't verify CSRF token authenticity" for json devise requests

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)

Strong parameters with Rails and Devise

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)

Override devise registrations controller

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)

Is devise's token_authenticatable secure?

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)

RoR Devise: Sign in with username OR email

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)

Undefined local variable or method `unconfirmed_email' when registering users?

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?

Where is devise implementation of authenticate_user! method?

I have been looking for it and have not found it so far.


Source: (StackOverflow)

Customizing Devise views in Rails

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)

"WARNING: Can't mass-assign protected attributes"

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)

devise and multiple "user" models

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)

Rails 3 using Devise: How to allow someone to log in using their Facebook account?

I have a Rails 3 application using Devise for authentication. Now I need to allow someone to log in using their Facebook account. I think this is called Facebook Connect, but I've also heard the term Facebook Graph API, so I'm not sure which one I'm asking for.

What do I need to do in order to integrate Facebook Connect with Devise?

Solution:

This question is pretty old now. A year ago, Devise v1.2 introduced OmniAuth support. Now Devise is at v2.1 (as of this writing) and using OmniAuth is even easier. Here is a great tutorial from the Devise wiki on using the omniauth-facebook gem with Devise to allow sign-in using Facebook.

Also check out this great tutorial on registering your application and working with the Facebook Graph API.


Source: (StackOverflow)

undefined method `devise_for' in rails

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)

Is this Rails JSON authentication API (using Devise) secure?

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:

  1. Is this login system secure? Or is there something I've overlooked or misunderstood, e.g. when it comes to CSRF attacks?
  2. Is my understanding of how to authenticate requests once users are signed in correct? (See "thirdly..." above.)
  3. 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)