Rails - ActiveRecord::RecordNotUnique in OmniauthCallbacksController#facebook - ruby-on-rails

I am using facebook authentication for logging in to my app. I did exactly as in this link http://willschenk.com/setting-up-devise-with-twitter-and-facebook-and-other-omniauth-schemes-without-email-addresses/#conclusion
First signup is always successful. But when trying to signup with a second account. I am getting the following error.
I think (not sure) i have to use allow_blank: true. Any help? Thanks in advance.

If you don't intend to use Devise's password authentication you could simply create a migration to remove the index:
rails g migration RemoveEmailIndexFromUsers
And then in the migration:
def change
remove_index :users, :email
end
And get rid of the :database_authenticatable module from your User model (remove it from the devise call).
But IMHO I would not use Devise for a pure OAuth app. The main draw of Devise is that it is a ready made auth solution for password auth. It tries to fill a lot of shoes and is quite complicated as a result.
Sure you can use it with OmniAuth but overriding Devise's controllers, views and params sanitation is almost as much work as rolling your own with Warden.

Related

Ruby on Rails: Devise - Is it bad to have a Users Controller separate from devise?

So from the beginning of the project, I installed devise gem, did the migrations and everything. Would it be bad practice, if I created a new controller:
rails g controller Users
Along side with devise? Sorry for the n00b question. Is there like a secrete place that devise creates this controller already and I can just customize and modify?
I think that it depends what you're trying to accomplish. If you want to customize Devise, Devise provides some hooks that you can use to customize certain things such as after_sign_up_path etc, or you can subclass Devise built-in controllers, for example:
class MyRegistrationsController < Devise::RegistrationsController
end
If you want something that devise doesn't provide, eg a list of users, or a detail page for a user, you might want to just create your own users controller as you mentioned - not bad practice, and Devise doesn't have any secrets, you can poke around in the gem code on Devise to find out what it's providing and what you might want to add or customize.

How to override the Devise lockable warning

Ruby on rails app using Devise for authentication. Successfully added lockable devise module, migrations, etc. However, I want the user to be given a warning when they are one attempt away from being locked out and when they are locked out. What is the best strategy for implementing this without interfering too much with devise?
Devise should add the field failed_attempts to your model.
You could check that field for the user on Devise's redirect and insert your own flash message if you'd like. See https://github.com/plataformatec/devise/wiki/How-To:-Redirect-to-a-specific-page-when-the-user-can-not-be-authenticated

Devise: Registering log in attempts

I have a Rails 3.0 project using devise and I've been requested to register in DB every succesful login and every failed attempt.
From the devise documentation I think I'd have to extend FailureApp but the examples are just redirecting users and not using the model at all. In stackoverflow I've just found this question but it remained unanswered, which is not encouraging
Can anyone tell me if I'm correct in this approach or it can't be done this way, or if there is some easier alternative I'm missing?
(I know there is no code yet, I'm just looking for a small guidance before diving in)
Thanks.
Spent a little bit of time looking into this myself and figured someone else might find this useful.
The create action in the devise controller calls warden.authenticate!, which attempts to authenticate the user with the supplied params. If authentication fails then authenticate! will call the devise failure app, which then runs the SessionsController#new action. Note, any filters you have for the create action will not run if authentication fails.
So the solution is to add a filter after the new action which checks the contents of env["warden.options"] and takes the appropriate action.
e.g.
def instrument_failed_login
instrument "failed_login.staff" if failed_login?
end
def failed_login?
(options = env["warden.options"]) && options[:action] == "unauthenticated"
end
An alternative and more maintainable way of adding logging around Devise authentication is to use the Warden Callbacks in an initializer. This is preferable because it uses the Warden API's designed for this and doesn't involve copy/pasting controller code.
Warden::Manager.before_failure do |env, opts|
logger.error("opts[:scope] authentication failure: #{opts[:message]}")
end
You can do the same with Warden::Manager#after_authentication and Warden::Manager#before_logout.
Modifying Devise::SessionsController to do your dirty work will do the trick.
Simply copy that file into your app/controllers/devise/sessions_controller.rb
Once you've done that, just add some code to where the user successfully logs in and where he fails to log in that will do what you want.
You'll probably want to create a new model for tracking login records.

User CRUD in web application that handles registration and login with Devise

I am currently working on application that is build on rails 3.0.9. All of a sudden the client decided that there should be a place to create a user and edit a user in the admin section of the website.
Now here is the case. The authentication and registration in the web application is handled by devise. If I try to implement a custom USER create method in my controller how should I hash the password in the very same way devise is doing so that I can store that in the database. This also applies to editing the already registered users as well.
I have tried to find the solution but no use. Any help in resolving this would be appreciated.
That's easy. You can setup another controller and form but set it up on your User model. Your form will need to include :email, :password, and :password_confirmation. When you do #user.save in your controller's create action, this will have devise take care of all the hashing requirements under the hood.
If you want to check that your save works (just for testing), add a bang at the end like #user.save! - this is only for testing. Either drop into rails console and you can see the newly added records or tail your log file.
Editing should work along the same lines and you can do #user.update_attribute() in your edit action, or #user.update_attributes() if you prefer mass assignment (this will be subject to any attr_accessible restrictions in your model)

Rails authentication with custom fields

I have a rails app where I need to add authentication. The problem is that I have a legacy database with custom user and password fields (t_user and t_pass). Plus, t_pass is not encrypted.
What I'm looking for is something like http_basic, but where I can have methods like current_user, and probably with a better user interface. I don't need validation, password reset, anything. Just a way to authenticate my way. I'd use restful_authentication but I'm on rails 3. I saw a fork that works with rails 3 but I was wondering if there is a better way to handle this situation?
It looks to me like you could probably do what you need using Devise and a bit of extra playing around. Specifically, you'll want to:
Make sure you create your user model table using your legacy auth table.
Override valid_password? on this model to check against your t_pass field.
Override self.find_for_database_authentication to find your model based on the t_user field.
If you want to support registration, you'll probably need to write a new encryption strategy as well.
Just a word of warning though: Storing passwords in plain text is very bad practice. If you have any choice at all, I'd seriously consider doing a migration of existing users into Devise's standard structure, with crypted passwords.
If you are looking for alternative gems to use then you can try Devise. You can extend/change the default settings to achieve what you want.
Devise and Authlogic are two potential options. Can't comment on Devise I'm afraid as I've never used it. Seems to be very popular at the moment though.
The following would get you started with Authlogic:
class User < ActiveRecord::Base
acts_as_authentic do |config|
config.login_field = :t_user
config.crypted_password_field = :t_pass
config.crypto_provider = YourCryptoProvider
end
...
end
There's a railscast on the basics of getting authlogic going.
The difficult part of this is that you would need to create your own crypto provider class as described http://rdoc.info/github/binarylogic/authlogic/master/Authlogic/CryptoProviders as authlogic doesn't provide a plain text password check method.
As discussed above, look into migrating your passwords to encrypted versions if that's an option for you, it will stop you from fighting against the auth frameworks so much.

Resources