Back to Devise Wiki

OmniAuth With Multiple Models

OmniAuth-with-multiple-models.md

latest2.9 KB
Original Source

Currently, Devise's Omniauthable module does not work with multiple models. No need to worry though, as the Omniauthable module is but a simple wrapper around OmniAuth.

So to allow OmniAuth authentication for multiple models:

  1. Remove the :omniauthable argument from your models.

  2. Move the OmniAuth configuration out of Devise's configuration file and into a new file. So, instead of having this in devise.rb:

ruby
Devise.setup do |config|
  config.omniauth :twitter, ENV['TWITTER_KEY'], ENV['TWITTER_SECRET']
end

You now have this in your new file omniauth.rb:

ruby
Rails.application.config.middleware.use OmniAuth::Builder do
  provider :twitter, ENV['TWITTER_KEY'], ENV['TWITTER_SECRET']
end
  1. Create your own OmniAuth routes. Here's an example of a possible route, given you have an authentications_controller.rb:

For Rails 3 and 4:

ruby
get "/auth/:action/callback", :to => "authentications", :constraints => { :action => /twitter|google/ }

For Rails 5:

ruby
get "/auth/:action/callback", :controller => "authentications", :constraints => { :action => /twitter|google/ }

Or if you want all OmniAuth authentications to be directed to the same create action, independently of the provider used:

ruby
get "/auth/:provider/callback" => "authentications#create"

For Rails 6:

ruby
get "/auth/twitter/callback" => "authentications#twitter"
get "/auth/google/callback"  => "authentications#google"

If you get a mapping error, wrap the route in a devise_scope:

ruby
devise_scope :user do
  get "/auth/:provider/callback" => "authentications#create"
end
  1. Setup OmniAuth's on_failure hook. You can do this inside OmniAuth's configuration block:
ruby
Rails.application.config.middleware.use OmniAuth::Builder do
  on_failure { |env| AuthenticationsController.action(:failure).call(env) }
end

Or outside of it:

ruby
OmniAuth.config.on_failure = Proc.new { |env| AuthenticationsController.action(:failure).call(env) }

Devise implements this second option, but the first option is simpler since OmniAuth is already being configured on the omniauth.rb file.

With this set up, all authentication failures (such as a user cancelling logging in) will be redirected to the `failure` action in the `authentications_controller.rb`.

5. Handle OmniAuth failures. Since errors in this library aren't properly standardized, the only way to handle them is with lots of conditionals, like Devise is doing. Simply copy the relevant code and you should be good to go.

The Railscast on Simple OmniAuth should also help setting this up.