Devise: Make user login in two ways - ruby-on-rails

I am trying a weird thing in devise. Here I have got two types of login.
1) Default devise login using username and password.
2) Login with user id and password.
The password (password2) in second step is different from that (password1) in first step.
I want to login through both using same interface, i.e. there will be one login page where you need to enter email or user id and corresponding password (password1 or password2 respectively).
Is it possible to do the same in devise?
Thanks
Paritosh

Allowing multiple user identifiers is discussed on the Devise wiki which I have linked here.
Update: However, as I now understand, you want two separate sets of credentials (userid/pw1, and email/pw2) for some reason.
I think the answer to your question is that "while it's possible to accomplish with Devise, it's far more effort to change Devise than it is to write yourself". If you look at the link, there's actually a fair amount of work needed to make the simpler change of accepting either userid or email for the same password. It gets even more complicated when implementing your requirements.
Unless you really create your own system from scratch, either Devise or Rails' built-in has_secure_password both make several assumptions about the name of the attribute holding the password (i.e. that it's called password). And while there's an assumption that there's a (single) model containing the authentication information and this attribute, I see no reason why you couldn't have two models, perhaps both belonging to a User model, each of which provide the basic functionality of encrypting, storing, and validating the attributes for the method the user has used, but for which all of the other functionality is provided by the parent User record, and its controllers and views. Some simple logic in the User model determines which method is being used and farms off that functionality to the appropriate sub-model.
So yeah, it can be done, and I would suggest has_secure_password will be simpler in your unusual case.
But perhaps it's worth asking: if I am the first person to encounter this situation, perhaps there's an alternative that could meet my requirements that follows some existing convention or approach. For example, is this a "single sign-on" interface that provides authentication for several unrelated services? If so, that might be the thing to search for.

here is a complete tutorial to login with both username and email. you can replace username with user_id or whatever you required.

Related

Ruby on rails. How safe is an admin attribute for user model?

I can't find any definitive answers to this.
I have a user model with devise, and I have added an 'admin' attribute that is a boolean, which defaults to false. Currently I have to go to the console and manually change the attribute to true to give a user this admin status.
My question is, how secure is this? Is there any way for someone to change the status of their own user without accessing the server (Currently my computer)?
Could safety be compromised once I put the site into production? The admin attribute is not a permitted parameter on sign in, sign up or update.
I am asking as I want to add a personal dashboard for myself to view, edit or delete anything I might need to when the site goes into production.
If you use strong params then the risk is only if you allow setting this attribute from any action outside of admin panel.
To be extra safe you can use attr_readonly so you can only set this attribute when object is created.
Considering Devise, safety is the last thing that could go wrong, unless either one of Rails or Devise is broken, which is unlikely.
You have taken sufficient steps like not allowing the admin parameter, which should be enough for pretty much every situation.
Several Rails applications, including GitHub and Shopify have been doing this (possibly without Devise, but that's not a concern) without security issues. I myself use Devise and admin flags and can vouch that it is safe enough.
Any reason you are not using something like RoleModel? It will allow you to expand to other roles in the future in a much more manageable way than adding an attribute to User for each role.
Either way... unless you provide a way for them to update that field, it should be secure. If you want to ensure that there's no way a non-admin could update that field, you could always add something like this to UsersController#update:
params[:user].delete(:admin) unless current_user.admin?

Configuring shared login for two models (devise)

I got two models that have a login. Company and User. What I wish to accomplish is to have one shared login on the front page that logs you in, not one for Company and one for User.
I am also assuming I need to create certain parameters between those models. Such as check the uniqueness of the email you register with. To avoid a person registering on both models, and when logging in on the shared login it gets an error.
My train of though is that I either need to make the login check two tables. Or somehow merge email and password from both models into a new table, that also shows which model the email and password they are logging in with belongs to. That's my thought process so far.
However I have no clue where to start, or what the best practice is for this.
You should implement STI (Single Table Inheritance). Just google it, there is a lot of examples.

Devise - limit registrations by using the password reset mechanism?

I'm looking for a way to allow private registrations, or registrations that require manual approval. The latter can be done using the strategy as described here, but I figure the former method might be more convenient if I could somehow take advantage of the password reset module to simplify the process (send an email with a one-time use token but for the purpose of account creation). Has anyone attempted anything like this, or possibly have a better strategy that makes greater use of existing components in devise?
possibly related: Ruby on rails: Devise, want to add invite code?
I have to admit I am not a big fan of using features in a framework that are designed for other uses to accomplish some other goal.
What I usually do when I want a private Sign-Up where you have to be invited to the App is to simply put the user creation/registration inside the Application. After all Devise is just an authentication mechanism ontop of the User model.
So in my current app for example there is a explicit way inside the app for existing users to invite a friend.
The inviting User has a form that creates an entry in the Users table for the new guy with his email address and a field that tells me if the user has finished his registration. I create a little Token that also gets saved to the Database (SecureRandom.hex(8) is a nice way to create such Tokens).
The system shoots the new guy a email telling him where to sign up (with a URL that contains the token), and the sign up is just a form that sets password and additional fields.
All of this is no real magic in Rails, it's all in all 2 controller actions, 2 views and 1 mailer to accomplish it and you are in no way constrained by any API Devise is or is not giving you.
I only had to make sure Devise won't authenticate Users that have not yet redeemed their invitation token but that's it then.
Sure not having to write the sign up view is convenient, but especially when you are dealing with partial information (the inviting User in my case has to fill in some information about the new user already) that gets only complemented by the new user it's quite convenient to just have regular forms where you can do anything with them.
Unless someone writes a Gem that extends Devise to do exactly this, I think I'll stick to this approach.
Turns out there was a third strategy - I could simply lock new accounts (lockable, before_create filter) and provide a manual unlock facility.

Looking for good approach for two levels of authentication in Rails

I need two levels of authentication in a Rails app using the same username. One to login and a second to view more sensitive areas such as billing and credit card info. The first level is implemented with Devise. For second level can I use Devise again a different model like setting? Cancan require separate logins.
Not sure of the best approach.
Any ideas would be appreciated!
This problem is so unconventional that it seems there can not be used a ready solution. In my opinion, dual authorization is not necessary in this case (the second password is usually used to confirm some action, not for a second authorization), but sometimes we do not choose such things.
Dirty solution would be to hold another encrypted password, and when you enter to second level give the user a different role temporarily. This role will be checked at the cancan. The role resets during for a while or at the next login (so that an attacker have not at the same time access to billing). I think it's very rough, but a quick solution.
This is just my 50 cents, I doubt that this is a good solution.

Using Devise for Two Different Models but the same Login Form

I have seen lots of similar questions here but nothing that quite fits my need.
I am a pretty experience rails developer but this new project is my first time using both Rails 3 and Devise (I'm normally on authlogic).
My app has two different models that I want to authenticate via devise.
One, User is just a standard users model
Two, Business is similar to a user, (it has an email address column too) but it has additional info in the database (address, phone number, etc..)
I want to be able to log them both in via the same login form. Then obviously once they are logged in they will be presented with different info depending on what type of Model has logged in.
It may or may not be relevant that I was planning on using OmniAuth to allow Users (though probably not businesses) to sign up/on via facebook.
Thanks!
What's the easiest way to go about doing this?
I think the only way to handle this would be to have your own custom sign in form and controller that determined the type of user and then sign them in correctly. I would recommend an approach like what mark mentioned for simplicity (take a look at something like CanCan to manage roles).
Another potential problem with having multiple user models is that you will have multiple versions of all the devise helper methods. So for current_<resource> and <resource>_signed_in? you would have current_user, current_business_user, user_signed_in? and business_user_signed_in?. Then you would either have to implement your own versions of these methods or you would need to check both versions everywhere you used them.
Can do this in application_controller?
current_user = current_resource_a || current_resource_b

Resources