Uninitialized constant OmniauthCallbacksController when trying to sign up user
devise, omniauth, omniauth-linkedin, ruby, ruby-on-rails
Solution
You have namespaced `OmniauthCallbacksController` under users as `Users::OmniauthCallbacksController`, make sure the controller path is `your_app/app/controllers/users/omniauth_callbacks_controller.rb` i.e., it resides under `users` folder. Similarly, your `devise` routes should look something like:
devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks" }
Note: `users/omniauth_callbacks`
UPDATE
Looking at the routes that you shared, you need to update routes for `upgrade` and `setup` as:
devise_scope :user do
get '/users/auth/:provider/upgrade' => 'users/omniauth_callbacks#upgrade', as: :user_omniauth_upgrade
get '/users/auth/:provider/setup', :to => 'users/omniauth_callbacks#setup'
end
Again, note: `users/omniauth_callbacks`
Problem
I'm having an issue with getting OmniAuth to work. I've been following this tutorial here to try and implement it with my existing app, but am coming up with the `ActionController::RoutingError at /users/auth/github/upgrade uninitialized constant OmniauthCallbacksController` error. I've looked at several other SO posts but most of those answers deal with misspellings and I've triple-checked that everything is spelled correctly. What might be interfering? User Model: ``` class User < ActiveRecord::Base devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :omniauthable has_many :identities def github identities.where( :provider => "github" ).first end def github_client @github_client ||= Github.client( access_token: github.accesstoken ) end def linkedin identities.where( :provider => "linkedin" ).first end def linkedin_client @linkedin_client ||= Linkedin.client( access_token: linkedin.accesstoken ) end end ``` Identity Model: ``` class Identity < ActiveRecord::Base belongs_to :user validates_presence_of :uid, :provider validates_uniqueness_of :uid, :scope => :provider def self.find_for_oauth(auth) identity = find_by(provider: auth.provider, uid: auth.uid) identity = create(uid: auth.uid, provider: auth.provider) if identity.nil? identity.accesstoken = auth.credentials.token identity.refreshtoken = auth.credentials.refresh_token identity.name = auth.info.name identity.email = auth.info.email identity.nickname = auth.info.nickname identity.image = auth.info.image identity.phone = auth.info.phone identity.urls = (auth.info.urls || "").to_json identity.save identity end end ``` Devise Model: ``` Devise.setup do |config| # config.omniauth :google_oauth2, ENV['GOOGLE_OAUTH2_APP_ID'], ENV['GOOGLE_OAUTH2_APP_SECRET'], scope: "email,profile,offline", prompt: "consent" config.omniauth :github, ENV['GITHUB_APP_ID'], ENV['GITHUB_APP_SECRET'], setup: true # config.omniauth :facebook, ENV['FACEBOOK_APP_ID'], ENV['FACEBOOK_APP_SECRET'], scope: "email" config.omniauth :linkedin, ENV['LINKEDIN_APP_ID'], ENV['LINKEDIN_APP_SECRET'], setup: true ``` Omniauth Model: ``` Rails.application.config.middleware.use OmniAuth::Builder do provider :github, ENV['GITHUB_KEY'], ENV['GITHUB_SECRET'] provider :linkedin, ENV['LINKEDIN_KEY'], ENV['LINKEDIN_SECRET'] end ``` FormUser Model ``` class FormUser < User attr_accessor :current_password validates_presence_of :email, if: :email_required? validates_uniqueness_of :email, allow_blank: true, if: :email_changed? validates_format_of :email, with: Devise.email_regexp, allow_blank: true, if: :email_changed? validates_presence_of :password, if: :password_required? validates_confirmation_of :password, if: :password_required? validates_length_of :password, within: Devise.password_length, allow_blank: true def password_required? return false if email.blank? !persisted? || !password.nil? || !password_confirmation.nil? end def email_required? true end end ``` Omniauth Callbacks Controller: ``` class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController def instagram generic_callback( 'instagram' ) end def facebook generic_callback( 'facebook' ) end def twitter generic_callback( 'twitter' ) end def google_oauth2 generic_callback( 'google_oauth2' ) end def generic_callback( provider ) @identity = Identity.find_for_oauth env["omniauth.auth"] # @user = @identity.user || current_user @user = @identity.user || User.find_by(email: @identity.email) || current_user if @user.nil? @user = User.create( email: @identity.email || "" ) @identity.update_attribute( :user_id, @user.id ) end if @user.email.blank? && @identity.email @user.update_attribute( :email, @identity.email) end if @user.persisted? @identity.update_attribute( :user_id, @user.id ) # This is because we've created the user manually, and Device expects a # FormUser class (with the validations) @user = FormUser.find @user.id sign_in_and_redirect @user, event: :authentication set_flash_message(:notice, :success, kind: provider.capitalize) if is_navigational_format? else session["devise.#{provider}_data"] = env["omniauth.auth"] redirect_to new_user_registration_url end end def upgrade scope = nil if params[:provider] == "google_oauth2" scope = "email,profile,offline,https://www.googleapis.com/auth/admin.directory.user" end redirect_to user_omniauth_authorize_path( params[:provider] ), flash: { scope: scope } end def setup request.env['omniauth.strategy'].options['scope'] = flash[:scope] || request.env['omniauth.strategy'].options['scope'] render :text => "Setup complete.", :status => 404 end end ``` Registrations Controller: ``` class Users::RegistrationsController < Devise::RegistrationsController def create unless params["user"]["code"] == ENV["CODE_TO_SIGN_UP"] respond_to do |format| format.html { return redirect_to new_user_registration_path, notice: 'The code you entered was wrong. Please contact ' + ENV["ADMIN_EMAIL"] } end end super end def update_resource(resource, params) if resource.encrypted_password.blank? # || params[:password].blank? resource.email = params[:email] if params[:email] if !params[:password].blank? && params[:password] == params[:password_confirmation] logger.info "Updating password" resource.password = params[:password] resource.save end if resource.valid? resource.update_without_password(params) end else resource.update_with_password(params) end end ``` Routes ``` Rails.application.routes.draw do devise_for :users, class_name: 'FormUser', :controllers => { omniauth_callbacks: 'users/omniauth_callbacks', registrations: 'users/registrations' } devise_scope :user do get '/users/auth/:provider/upgrade' => 'omniauth_callbacks#upgrade', as: :user_omniauth_upgrade get '/users/auth/:provider/setup', :to => 'omniauth_callbacks#setup' end end ``` UPDATE rake routes: ``` Prefix Verb URI Pattern Controller#Action new_user_session GET /users/sign_in(.:format) devise/sessions#new user_session POST /users/sign_in(.:format) devise/sessions#create destroy_user_session DELETE /users/sign_out(.:format) devise/sessions#destroy user_github_omniauth_authorize GET|POST /users/auth/github(.:format) users/omniauth_callbacks#passthru user_github_omniauth_callback GET|POST /users/auth/github/callback(.:format) users/omniauth_callbacks#github user_linkedin_omniauth_authorize GET|POST /users/auth/linkedin(.:format) users/omniauth_callbacks#passthru user_linkedin_omniauth_callback GET|POST /users/auth/linkedin/callback(.:format) users/omniauth_callbacks#linkedin user_password POST /users/password(.:format) devise/passwords#create new_user_password GET /users/password/new(.:format) devise/passwords#new edit_user_password GET /users/password/edit(.:format) devise/passwords#edit PATCH /users/password(.:format) devise/passwords#update PUT /users/password(.:format) devise/passwords#update cancel_user_registration GET /users/cancel(.:format) users/registrations#cancel user_registration POST /users(.:format) users/registrations#create new_user_registration GET /users/sign_up(.:format) users/registrations#new edit_user_registration GET /users/edit(.:format) users/registrations#edit PATCH /users(.:format) users/registrations#update PUT /users(.:format) users/registrations#update DELETE /users(.:format) users/registrations#destroy user_omniauth_upgrade GET /users/auth/:provider/upgrade(.:format) users/omniauth_callbacks#upgrade GET /users/auth/:provider/setup(.:format) users/omniauth_callbacks#setup typing_tests GET /typing_tests(.:format) typing_tests#index POST /typing_tests(.:format) typing_tests#create new_typing_test GET /typing_tests/new(.:format) typing_tests#new edit_typing_test GET /typing_tests/:id/edit(.:format) typing_tests#edit typing_test GET /typing_tests/:id(.:format) typing_tests#show PATCH /typing_tests/:id(.:format) typing_tests#update PUT /typing_tests/:id(.:format) typing_tests#update DELETE /typing_tests/:id(.:format) typing_tests#destroy prompts GET /prompts(.:format) prompts#index POST /prompts(.:format) prompts#create new_prompt GET /prompts/new(.:format) prompts#new edit_prompt GET /prompts/:id/edit(.:format) prompts#edit prompt GET /prompts/:id(.:format) prompts#show PATCH /prompts/:id(.:format) prompts#update PUT /prompts/:id(.:format) prompts#update DELETE /prompts/:id(.:format) prompts#destroy universities GET /universities(.:format) universities#index POST /universities(.:format) universities#create new_university GET /universities/new(.:format) universities#new edit_university GET /universities/:id/edit(.:format) universities#edit university PATCH /universities/:id(.:format) universities#update PUT /universities/:id(.:format) universities#update DELETE /universities/:id(.:format) universities#destroy programs GET /programs(.:format) programs#index POST /programs(.:format) programs#create new_program GET /programs/new(.:format) programs#new edit_program GET /programs/:id/edit(.:format) programs#edit program PATCH /programs/:id(.:format) programs#update PUT /programs/:id(.:format) programs#update DELETE /programs/:id(.:format) programs#destroy users GET /users(.:format) users#index edit_user GET /users/:id/edit(.:format) users#edit user GET /users/:id(.:format) users#show PATCH /users/:id(.:format) users#update PUT /users/:id(.:format) users#update DELETE /users/:id(.:format) users#destroy root GET / typing_tests#index unauthenticated_root GET / devise/sessions#new ``` Stack trace: ``` Started GET "/" for 127.0.0.1 at 2017-05-03 18:24:26 -0500 ActiveRecord::SessionStore::Session Load (0.5ms) SELECT "sessions".* FROM "sessions" WHERE "sessions"."session_id" = '430aa65b41ec7892dd1581f14a9fbd16' ORDER BY "sessions"."id" ASC LIMIT 1 Processing by Devise::SessionsController#new as HTML Rendered devise/shared/_links.html.erb (0.3ms) Rendered devise/sessions/new.html.erb within layouts/application (4.5ms) Completed 200 OK in 90ms (Views: 88.9ms | ActiveRecord: 0.0ms) (0.1ms) BEGIN SQL (0.3ms) UPDATE "sessions" SET "data" = $1, "updated_at" = $2 WHERE "sessions"."id" = 45 [["data", "BAh7BkkiEF9jc3JmX3Rva2VuBjoGRUZJIjFjakIxRFIwRzIxaEl6SkZoNEsv\nMVdGeHZUSGNUS0R0d3cxWFB3aENBbWVjPQY7AEY=\n"], ["updated_at", "2017-05-03 23:24:26.682877"]] (6.5ms) COMMIT Started GET "/users/auth/github/upgrade" for 127.0.0.1 at 2017-05-03 18:24:27 -0500 Processing by Users::OmniauthCallbacksController#upgrade as HTML Parameters: {"provider"=>"github"} Completed 500 Internal Server Error in 19ms NoMethodError - undefined method `user_omniauth_authorize_path' for #<Users::OmniauthCallbacksController:0x007f9a1e0012b0> Did you mean? user_omniauth_upgrade_path user_github_omniauth_authorize_path: app/controllers/users/omniauth_callbacks_controller.rb:51:in `upgrade' actionpack (4.1.9) lib/action_controller/metal/implicit_render.rb:4:in `send_action' actionpack (4.1.9) lib/abstract_controller/base.rb:189:in `process_action' actionpack (4.1.9) lib/action_controller/metal/rendering.rb:10:in `process_action' actionpack (4.1.9) lib/abstract_controller/callbacks.rb:20:in `block in process_action' activesupport (4.1.9) lib/active_support/callbacks.rb:113:in `call' activesupport (4.1.9) lib/active_support/callbacks.rb:149:in `block in halting_and_conditional' activesupport (4.1.9) lib/active_support/callbacks.rb:229:in `block in halting' activesupport (4.1.9) lib/active_support/callbacks.rb:166:in `block in halting' activesupport (4.1.9) lib/active_support/callbacks.rb:166:in `block in halting' activesupport (4.1.9) lib/active_support/callbacks.rb:166:in `block in halting' activesupport (4.1.9) lib/active_support/callbacks.rb:86:in `run_callbacks' actionpack (4.1.9) lib/abstract_controller/callbacks.rb:19:in `process_action' actionpack (4.1.9) lib/action_controller/metal/rescue.rb:29:in `process_action' actionpack (4.1.9) lib/action_controller/metal/instrumentation.rb:31:in `block in process_action' activesupport (4.1.9) lib/active_support/notifications.rb:159:in `block in instrument' activesupport (4.1.9) lib/active_support/notifications/instrumenter.rb:20:in `instrument' activesupport (4.1.9) lib/active_support/notifications.rb:159:in `instrument' actionpack (4.1.9) lib/action_controller/metal/instrumentation.rb:30:in `process_action' actionpack (4.1.9) lib/action_controller/metal/params_wrapper.rb:250:in `process_action' activerecord (4.1.9) lib/active_record/railties/controller_runtime.rb:18:in `process_action' actionpack (4.1.9) lib/abstract_controller/base.rb:136:in `process' actionview (4.1.9) lib/action_view/rendering.rb:30:in `process' actionpack (4.1.9) lib/action_controller/metal.rb:196:in `dispatch' actionpack (4.1.9) lib/action_controller/metal/rack_delegation.rb:13:in `dispatch' actionpack (4.1.9) lib/action_controller/metal.rb:232:in `block in action' actionpack (4.1.9) lib/action_dispatch/routing/route_set.rb:82:in `dispatch' actionpack (4.1.9) lib/action_dispatch/routing/route_set.rb:50:in `call' actionpack (4.1.9) lib/action_dispatch/routing/mapper.rb:45:in `call' actionpack (4.1.9) lib/action_dispatch/journey/router.rb:73:in `block in call' actionpack (4.1.9) lib/action_dispatch/journey/router.rb:59:in `each' actionpack (4.1.9) lib/action_dispatch/journey/router.rb:59:in `call' actionpack (4.1.9) lib/action_dispatch/routing/route_set.rb:685:in `call' omniauth (1.4.2) lib/omniauth/strategy.rb:186:in `call!' omniauth (1.4.2) lib/omniauth/strategy.rb:164:in `call' omniauth (1.4.2) lib/omniauth/strategy.rb:186:in `call!' omniauth (1.4.2) lib/omniauth/strategy.rb:164:in `call' meta_request (0.3.4) lib/meta_request/middlewares/app_request_handler.rb:13:in `call' meta_request (0.3.4) lib/meta_request/middlewares/meta_request_handler.rb:13:in `call' warden (1.2.6) lib/warden/manager.rb:35:in `block in call' warden (1.2.6) lib/warden/manager.rb:34:in `catch' warden (1.2.6) lib/warden/manager.rb:34:in `call' rack (1.5.5) lib/rack/etag.rb:23:in `call' rack (1.5.5) lib/rack/conditionalget.rb:25:in `call' rack (1.5.5) lib/rack/head.rb:11:in `call' actionpack (4.1.9) lib/action_dispatch/middleware/params_parser.rb:27:in `call' actionpack (4.1.9) lib/action_dispatch/middleware/flash.rb:254:in `call' rack (1.5.5) lib/rack/session/abstract/id.rb:225:in `context' rack (1.5.5) lib/rack/session/abstract/id.rb:220:in `call' actionpack (4.1.9) lib/action_dispatch/middleware/cookies.rb:562:in `call' activerecord (4.1.9) lib/active_record/query_cache.rb:36:in `call' activerecord (4.1.9) lib/active_record/connection_adapters/abstract/connection_pool.rb:621:in `call' activerecord (4.1.9) lib/active_record/migration.rb:380:in `call' actionpack (4.1.9) lib/action_dispatch/middleware/callbacks.rb:29:in `block in call' activesupport (4.1.9) lib/active_support/callbacks.rb:82:in `run_callbacks' actionpack (4.1.9) lib/action_dispatch/middleware/callbacks.rb:27:in `call' actionpack (4.1.9) lib/action_dispatch/middleware/reloader.rb:73:in `call' actionpack (4.1.9) lib/action_dispatch/middleware/remote_ip.rb:76:in `call' better_errors (2.1.1) lib/better_errors/middleware.rb:84:in `protected_app_call' better_errors (2.1.1) lib/better_errors/middleware.rb:79:in `better_errors_call' better_errors (2.1.1) lib/better_errors/middleware.rb:57:in `call' rack-contrib (1.2.0) lib/rack/contrib/response_headers.rb:17:in `call' meta_request (0.3.4) lib/meta_request/middlewares/headers.rb:16:in `call' actionpack (4.1.9) lib/action_dispatch/middleware/debug_exceptions.rb:17:in `call' actionpack (4.1.9) lib/action_dispatch/middleware/show_exceptions.rb:30:in `call' railties (4.1.9) lib/rails/rack/logger.rb:38:in `call_app' railties (4.1.9) lib/rails/rack/logger.rb:20:in `block in call' activesupport (4.1.9) lib/active_support/tagged_logging.rb:68:in `block in tagged' activesupport (4.1.9) lib/active_support/tagged_logging.rb:26:in `tagged' activesupport (4.1.9) lib/active_support/tagged_logging.rb:68:in `tagged' railties (4.1.9) lib/rails/rack/logger.rb:20:in `call' quiet_assets (1.1.0) lib/quiet_assets.rb:27:in `call_with_quiet_assets' actionpack (4.1.9) lib/action_dispatch/middleware/request_id.rb:21:in `call' rack (1.5.5) lib/rack/methodoverride.rb:21:in `call' rack (1.5.5) lib/rack/runtime.rb:17:in `call' activesupport (4.1.9) lib/active_support/cache/strategy/local_cache_middleware.rb:26:in `call' rack (1.5.5) lib/rack/lock.rb:17:in `call' actionpack (4.1.9) lib/action_dispatch/middleware/static.rb:84:in `call' rack (1.5.5) lib/rack/sendfile.rb:112:in `call' railties (4.1.9) lib/rails/engine.rb:514:in `call' railties (4.1.9) lib/rails/application.rb:144:in `call' rack (1.5.5) lib/rack/lock.rb:17:in `call' rack (1.5.5) lib/rack/content_length.rb:14:in `call' rack (1.5.5) lib/rack/handler/webrick.rb:60:in `service' /Users/jimmiejackson/.rvm/rubies/ruby-2.3.3/lib/ruby/2.3.0/webrick/httpserver.rb:140:in `service' /Users/jimmiejackson/.rvm/rubies/ruby-2.3.3/lib/ruby/2.3.0/webrick/httpserver.rb:96:in `run' /Users/jimmiejackson/.rvm/rubies/ruby-2.3.3/lib/ruby/2.3.0/webrick/server.rb:296:in `block in start_thread' ``` Please let me know if there is any other code you might need to see. Thanks for your help, this is driving me crazy!