what is the omniauth & email-password registration best practice? - ruby-on-rails

What is the best practice for combining Facebook login (let's say I'll use Omniauth gem) and email+password login?
I saw a few blogs, saw the Railscasts, I know everyone is using Devise gem with Omniauth. But I'm looking for some different perspective.
subquestions:
I'm considering creating email+password sign-up from scratch (not using any gem for this, lets keep it fast and light) so do you have any advice for this ? Or if you have particular gem in mind, please let it be fast.
And do you have any other recommendations for Oauth2 gems (alternative to Omniauth) handling authentication to Facebook ?
I'm sorry I'm asking this fundamental questions here, but I didn't found many answers (and most of them I found are based on Devise)

This is how I saw it's done in most examples on the web
basicly when you signup with email+password, you are creating row directly to User model (not touching the Authent. model) and when signing up with Omniauth, than you are creating new authentication that communicates with User model.
And basicly on next login you are doing something like this :
if (user.password == 'xxx')
login
elsif user.authentication.uid == 'xxx'
login
else
'hello signup !'
end
so you are swiching between 2 models, and raping (sorry for the term) the User model witch should hold only user info
The solution, in a way, I think is correct (from my experience and discussions with my colleagues but I'm still not 100% sure this is the right answer)
as you see even the user+password is going trough Authent. model, that means the site user+password is acting as a provider on its own
so to be absolutly correct it should be look like this
scenario 1
signing up with FB: you save FB uid and authKey to authentication table, then create user
scenario 2
signing up with password: you create new row in AppPass table, then you create row in Authentication table (as a access to provider witch is actually your app) and than you create user
Why?
because now when user logs in, is always going trough Authent. model, not making condition between 2 models (the Authent. and the User model)
now can anyone please tell me, ...is this a good approach :D ?

Intridea offers an email & password strategy to enable this:
https://github.com/intridea/omniauth-identity
:-)

Omniauth is great, so you should probably use that for any/all social media logins.
As far as setting up your own authentication this shouldn't be too hard. Ryan Bates has a great screencast on this: Authentication from scratch
Here is a pretty good omniauth article (you will have to adapt it to your own users table though but its still a great resource) Omniauth rails rumble. Please note that I believe the article author uses the term authorization in the wrong context here. Omniauth has nothing to do with authorization, only authentication and this is a subtle but very important difference.

Here's a link to the ruby toolbox page for the most popular authentication gems: http://ruby-toolbox.com/categories/rails_authentication.html. You probably aren't going to find the exact functionality you are looking for right out of the box with any of the solutions.
I don't think that you are correct that having the different authentication methods go to different tables will put too much strain (perhaps a better term) on the models.
It seems to me that if everyone is doing this using devise, there is a reason for it. You could probably get better performance by writing something scaled down yourself, but it's a big time investment. My guess is that the small performance improvement in your application is not going to be worth the time you spend writing something yourself.
If you're working on a current project with many thousands of concurrent users that is having difficulty scaling, please ignore my advice, since I am not familiar with those type of problems.

I kinda dig in to these problematic more deeply an done some research on my own, these are the conclusions.
The problem is that I'm trying to combine my authentication functionality with site login/signup functionality, witch are two different behaviors. At the end of the FB signup with omniauth, you will have in your Authentication table the facebook uid and that is all that it takes to back login to FB for next time (of course you can store other info (like email) ... but logicly they are more users attributes and should go to user table).
note: its ok to store user information from provider, in Authentication table,
but if you want to work with them you should copy these informations to Users table
When you are signing up with email/password solution, you are writing information that define User on your site. (Authentication is just pointing to User) If we wanted to do password signup trough Authentication table, we would have to store the username & password inside authentications table, and this way merging User model and Authentication to one model. It will be much uglier solution, not talking about problem how to store multiple rows to one user. Also you the Authentication or Oauth are synonyms for "accessing your application trough other site" ( watch these oauth2 videos if you cannot imagine it http://www.youtube.com/view_play_list?p … 0139F609), yet with normal login you are accessing the site directly.
The only way around this problem is making a small app, that will handle the email/password or the user/password signup, generate password provider UID, and write those data to Users table, and than with our main applycation we will request trough omniauth to access the miniapp and store the UID in authentications table.
http://eq8scrapbook.heroku.com/equivalents_article/on_omniauth_and_password_login_best_practice

Related

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.

Rails best practice for app with only one user?

I am building a website for a client that wants to be able to make edits to things on their website. As such I need a way to allow the client to login to the site to make their changes.
My initial thought was to make an authentication system that relies on a User table in the database that is capped at one and only one user. It seems sort of overkill however to make a database table for just one result, so I was wondering if there were any other approaches or best practices that anyone could point to for building a site with just one user.
You could simply authenticate with a static password that is received from a file(encrypted), if you do not want a db model for that.
However, setting authentication with a gem like Devise is like 10 minutes of work. In order to be more secure(it can be a matter even in single user apps), you can set it up and be fine :)
I would highly recommend you set up authentication. As SpyrosP said it does not take long when you use Devise.

Restful authentication + Facebook connect - User model redesign

I have a site with Restful authentication as authentication plugin. I need to integrate Facebook connect. Facebook does not provide email address for the user (maybe only if user agrees if), and of course does not provide a password.
The main issue is that the User model has a lot of validates_** on those 2 fields (from Restful authentication modules).
Another little issue would be that we already have a lot of code (observers sending emails after user creation, etc etc) that depends on email address.
The solution present in the facebook_connect tutorials was to save the user model bypassing validations, but this is sooo wrong..
How would you redesign the User model to include any/both of the authentication methods(standard and/or facebook_connect)?
Refactor all validations (with :unless => :is_facebook_user), put conditions on observers, etc.
Implement STI on User table (and have StandardUser / FacebookUser, each with custom authentication modules)
User table having polymorphic reference to standard_user and facebook_user
Other ideea
Please notice that the functionality to link a 'standard' account to a 'facebook' account is also required, which complicates things.
References:
http://crazyviraj.blogspot.com/2010/01/test-cases-for-basic-facebook-connect.html
http://blog.yangtheman.com/2009/08/23/how-to-integrate-facebook-connect-with-a-rails-app/comment-page-1/
A good example to get your started here.

What are people's opinions vis-a-vis my choice of authorization plugins?

I'm slowly but surely putting together my first rails app (first web-app of any kind in fact - I'm not really a programmer) and it's time to set up a user registration/login system. The nature of my app is such that each user will be completely separated from each other user (except for admin roles). When users log in they will have their own unique index page looking at only their data which they and no-one else can ever see or edit. However, I may later want to add a role for a user to be able to view and edit several other user's data (e.g. a group of users may want to allow their secretary to access and edit their data but their secretary would not need any data of their own).
My plan is to use authlogic to create the login system and declarative authorization to control permissions but before I embark on this fairly major and crucial task I thought I would canvas a few opinions as to whether this combo was appropriate for the tasks I envisage or whether there would be a better/simpler/faster/cheaper/awesomer option.
What about cancan by Ryan Bates?
Here you can get a complete visual guided implementation
Take a look at this, it might help:
Basic Rails 3 engine utilizing Authlogic, CanCan and Easy Roles
What about Devise? Take a look at the railscasts.com site.

Resources