Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use dynamic scoping with devise and omniauth

I am upgrading an old app from rails 3.0 to rails 4.1 and having trouble setting up the routes for devise and omniauth. Currently the routes look like this:

scope "(:locale)", locale: /#{I18n.available_locales.join("|")}/ do
      devise_for :users, controllers: {
            omniauth_callbacks: "users/omniauth_callbacks"
      }

When I run this I get the following error:

 Devise does not support scoping omniauth callbacks under a dynamic segment (RuntimeError)
 and you have set "/(:locale)/users". You can work around by passing
 `skip: :omniauth_callbacks` and manually defining the routes. Here is an example:

match "/users/auth/:provider",
  constraints: { provider: /google|facebook/ },
  to: "devise/omniauth_callbacks#passthru",
  as: :omniauth_authorize,
  via: [:get, :post]

match "/users/auth/:action/callback",
  constraints: { action: /google|facebook/ },
  to: "devise/omniauth_callbacks",
  as: :omniauth_callback,
  via: [:get, :post]

I've tried to manually define routes a number of ways but when I run my tests none of my routes work. Does any one know the correct way to handle these dynamic segments with devise_for?

like image 784
trueinViso Avatar asked Jul 24 '14 23:07

trueinViso


1 Answers

I added devise_for 2 times in routes.rb

devise_for :users, skip: [:session, :password, :registration], controllers: { omniauth_callbacks: "users/omniauth_callbacks" }

scope ":locale", locale: /#{I18n.available_locales.join("|")}/ do
   devise_for :users, skip: [:omniauth_callbacks]

Found the answer here

In addition, you need a custom failure block for omniauth to handle errors during login (E.g. user cancels):

# In config/initializers/omniauth.rb
require 'devise/omniauth'
# Work around for bug when scoping paths
# See: https://github.com/spree/spree_social/issues/130
OmniAuth.config.on_failure = Proc.new do |env|
  env['devise.mapping'] = Devise.mappings[:user]
  controller_name  = ActiveSupport::Inflector.camelize(env['devise.mapping'].controllers[:omniauth_callbacks])
  controller_klass = ActiveSupport::Inflector.constantize("#{controller_name}Controller")
  controller_klass.action(:failure).call(env)
end
like image 102
Dmitriy Avatar answered Oct 31 '22 21:10

Dmitriy