Callback denied with OmniAuth - ruby-on-rails

When I initiate the logging in process using OmniAuth in a Rails 3 app, if I cancel on the provider's page, I get sent back to an URL that looks something like:
http://example.com/auth/twitter/callback?denied=aUho....
and my application throws a 500, that I can see it's a OAuth::Unauthorized: 401 Unauthorized, without ever touching any of my controller actions.
The stack trace is when I reproduce it in my computer is:
oauth (0.4.6) lib/oauth/consumer.rb:216:in `token_request'
oauth (0.4.6) lib/oauth/consumer.rb:136:in `get_request_token'
omniauth-oauth (1.0.1) lib/omniauth/strategies/oauth.rb:29:in `request_phase'
omniauth-twitter (0.0.11) lib/omniauth/strategies/twitter.rb:50:in `request_phase'
omniauth (1.1.0) lib/omniauth/strategy.rb:207:in `request_call'
omniauth (1.1.0) lib/omniauth/strategy.rb:174:in `call!'
omniauth (1.1.0) lib/omniauth/strategy.rb:157:in `call'
omniauth (1.1.0) lib/omniauth/strategy.rb:177:in `call!'
omniauth (1.1.0) lib/omniauth/strategy.rb:157:in `call'
omniauth (1.1.0) lib/omniauth/builder.rb:48:in `call'
sass (3.1.19) lib/sass/plugin/rack.rb:54:in `call'
warden (1.1.1) lib/warden/manager.rb:35:in `block in call'
warden (1.1.1) lib/warden/manager.rb:34:in `catch'
warden (1.1.1) lib/warden/manager.rb:34:in `call'
actionpack (3.2.6) lib/action_dispatch/middleware/best_standards_support.rb:17:in `call'
rack (1.4.1) lib/rack/etag.rb:23:in `call'
rack (1.4.1) lib/rack/conditionalget.rb:25:in `call'
actionpack (3.2.6) lib/action_dispatch/middleware/head.rb:14:in `call'
actionpack (3.2.6) lib/action_dispatch/middleware/params_parser.rb:21:in `call'
actionpack (3.2.6) lib/action_dispatch/middleware/flash.rb:242:in `call'
rack (1.4.1) lib/rack/session/abstract/id.rb:205:in `context'
rack (1.4.1) lib/rack/session/abstract/id.rb:200:in `call'
actionpack (3.2.6) lib/action_dispatch/middleware/cookies.rb:338:in `call'
activerecord (3.2.6) lib/active_record/query_cache.rb:64:in `call'
activerecord (3.2.6) lib/active_record/connection_adapters/abstract/connection_pool.rb:473:in `call'
actionpack (3.2.6) lib/action_dispatch/middleware/callbacks.rb:28:in `block in call'
activesupport (3.2.6) lib/active_support/callbacks.rb:405:in `_run__60653626266012267__call__4496837804684830799__callbacks'
activesupport (3.2.6) lib/active_support/callbacks.rb:405:in `__run_callback'
activesupport (3.2.6) lib/active_support/callbacks.rb:385:in `_run_call_callbacks'
activesupport (3.2.6) lib/active_support/callbacks.rb:81:in `run_callbacks'
actionpack (3.2.6) lib/action_dispatch/middleware/callbacks.rb:27:in `call'
actionpack (3.2.6) lib/action_dispatch/middleware/reloader.rb:65:in `call'
actionpack (3.2.6) lib/action_dispatch/middleware/remote_ip.rb:31:in `call'
actionpack (3.2.6) lib/action_dispatch/middleware/debug_exceptions.rb:16:in `call'
actionpack (3.2.6) lib/action_dispatch/middleware/show_exceptions.rb:56:in `call'
railties (3.2.6) lib/rails/rack/logger.rb:26:in `call_app'
railties (3.2.6) lib/rails/rack/logger.rb:16:in `call'
quiet_assets (1.0.1) lib/quiet_assets.rb:20:in `call_with_quiet_assets'
actionpack (3.2.6) lib/action_dispatch/middleware/request_id.rb:22:in `call'
rack (1.4.1) lib/rack/methodoverride.rb:21:in `call'
rack (1.4.1) lib/rack/runtime.rb:17:in `call'
activesupport (3.2.6) lib/active_support/cache/strategy/local_cache.rb:72:in `call'
rack (1.4.1) lib/rack/lock.rb:15:in `call'
actionpack (3.2.6) lib/action_dispatch/middleware/static.rb:62:in `call'
airbrake (3.1.1) lib/airbrake/rack.rb:30:in `call'
airbrake (3.1.1) lib/airbrake/user_informer.rb:12:in `call'
railties (3.2.6) lib/rails/engine.rb:479:in `call'
railties (3.2.6) lib/rails/application.rb:220:in `call'
rack (1.4.1) lib/rack/content_length.rb:14:in `call'
railties (3.2.6) lib/rails/rack/log_tailer.rb:17:in `call'
thin (1.3.1) lib/thin/connection.rb:80:in `block in pre_process'
thin (1.3.1) lib/thin/connection.rb:78:in `catch'
thin (1.3.1) lib/thin/connection.rb:78:in `pre_process'
thin (1.3.1) lib/thin/connection.rb:53:in `process'
thin (1.3.1) lib/thin/connection.rb:38:in `receive_data'
eventmachine (0.12.10) lib/eventmachine.rb:256:in `run_machine'
eventmachine (0.12.10) lib/eventmachine.rb:256:in `run'
thin (1.3.1) lib/thin/backends/base.rb:61:in `start'
thin (1.3.1) lib/thin/server.rb:159:in `start'
rack (1.4.1) lib/rack/handler/thin.rb:13:in `run'
rack (1.4.1) lib/rack/server.rb:265:in `start'
railties (3.2.6) lib/rails/commands/server.rb:70:in `start'
railties (3.2.6) lib/rails/commands.rb:55:in `block in <top (required)>'
railties (3.2.6) lib/rails/commands.rb:50:in `tap'
railties (3.2.6) lib/rails/commands.rb:50:in `<top (required)>'
script/rails:6:in `require'
script/rails:6:in `<top (required)>'
-e:1:in `load'
-e:1:in `<main>'
If I go on with log in (without clicking cancel at Twitter's page), then everything works correctly as expected. Same for Facebook, I can log in just fine, but if I press 'cancel' at Facebook's page, I get redirected back and I throw a 500.
Is there a way to handle this better? I'd like to be able to show a nice page.

When there's a failure, most of the times depending on the type of failure, OmniAuth will call OmniAuth.config.on_failure which by default is set to OmniAuth::FailureEndpoint. By default it is supposed to raise an exception in development mode and redirect otherwise:
def call
raise_out! if ENV['RACK_ENV'].to_s == 'development'
redirect_to_failure
end
The default endpoint, according to the docs, is /auth/failure.
If that is not working as expected for you, then you can force the redirection to always happen, even on dev mode, by adding this to your initializer:
class SafeFailureEndpoint < OmniAuth::FailureEndpoint
def call
redirect_to_failure
end
end
OmniAuth.config.on_failure = SafeFailureEndpoint
A more concise solution from https://github.com/intridea/omniauth/issues/616
# Added to config/initializers/omniauth.rb
OmniAuth.config.on_failure = Proc.new { |env|
OmniAuth::FailureEndpoint.new(env).redirect_to_failure
}

I had same issue, (facebook cancel clicked)
after adding
# Added to config/initializers/omniauth.rb
OmniAuth.config.on_failure = Proc.new { |env|
OmniAuth::FailureEndpoint.new(env).redirect_to_failure
}
implemented auth callback route as
in config/routes.rb
match '/auth/failure' => 'sessions#failure'
session controller will look like
class SessionsController < ApplicationController
def failure
redirect_to #route that you want redirect
end
end

I had the same issue, and with Pramod's solution I was getting an "Unknown action" error, but worked after I changed the callback route to
config/routes.rb
devise_scope :user do
get '/users/auth/failure' => 'sessions#failure'
end
Rails 3.2.14
Devise 3.1.1
Omniauth 1.1.4

For those using omniauth_facebook and something like Users::OmniauthCallbacksController use:
config/routes.rb
devise_scope :user do
get '/omniauth/failure' => 'users/omniauth_callbacks#failure'
end
app/controllers/users/omniauth_callbacks_controller.rb
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def facebook
...
end
def failure
redirect_to root_path
end
end
If you are using the FB popup
app/controllers/users/omniauth_callbacks_controller.rb
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def facebook
...
end
def failure
if request.env['HTTP_REFERER'] == "https://www.facebook.com/"
render 'failure', :layout => false
else
redirect_to root_path
end
end
end
app/views/users/omniauth_callbacks/failure.html.haml
:javascript
window.close();

Related

Execution expired error with facebook login, using omniauth-facebook

Users are not able lo login from Facebook since July 3rd.
I'm using omniauth-facebook. I tested login successfully from localhost (pointing to another FB test app). But in production the app shows this error:
Started GET "/auth/facebook" for 190.238.101.80 at 2019-07-10 17:53:51 -0500
I, [2019-07-10T17:53:51.594796 #4707] INFO -- omniauth: (facebook) Request phase initiated.
Started GET "/auth/facebook/callback?code=AQAj5FOJuHu7UY656lbwZ4Sfcf_J_ZX9Z_t0wRT-LDfnPLU530zKj5CNGEK53yJ9maNj8O80fWgGmxCq4zWqBK7CPN-ovokGZVIvfY0KaqzNRXWOC20kH4KhkYOHjPyRh4tMYTIcHZ1a0BvHfbBLVolYECVtfD1OKJ2Xob07LCpS0SHNhYc6PA3rBAnb6GnkvOZI-8S7nwXIICdFoKu0BbHd-6L8_Dq-dPFTOpJDSWgmoJUBc65EyCnuw7NCI4IFP1UtxtOmB_QjuzRQV-voQs_SV6N97c2ICK_Qc-IqL_WBwqd54aEzdnW5UOsDV4Wo0jA&state=cee86047aecb4d282b80d33bbd0469815a17d25566167d95" for 190.238.101.80 at 2019-07-10 17:53:52 -0500
I, [2019-07-10T17:53:52.082829 #4707] INFO -- omniauth: (facebook) Callback phase initiated.
Faraday::ConnectionFailed (execution expired):
/usr/lib/ruby/2.5.0/net/http.rb:937:in `initialize'
/usr/lib/ruby/2.5.0/net/http.rb:937:in `open'
/usr/lib/ruby/2.5.0/net/http.rb:937:in `block in connect'
/usr/lib/ruby/2.5.0/timeout.rb:103:in `timeout'
/usr/lib/ruby/2.5.0/net/http.rb:935:in `connect'
/usr/lib/ruby/2.5.0/net/http.rb:920:in `do_start'
/usr/lib/ruby/2.5.0/net/http.rb:909:in `start'
/usr/lib/ruby/2.5.0/net/http.rb:1458:in `request'
faraday (0.15.4) lib/faraday/adapter/net_http.rb:87:in `perform_request'
faraday (0.15.4) lib/faraday/adapter/net_http.rb:43:in `block in call'
faraday (0.15.4) lib/faraday/adapter/net_http.rb:92:in `with_net_http_connection'
faraday (0.15.4) lib/faraday/adapter/net_http.rb:38:in `call'
faraday (0.15.4) lib/faraday/request/url_encoded.rb:15:in `call'
faraday (0.15.4) lib/faraday/rack_builder.rb:143:in `build_response'
faraday (0.15.4) lib/faraday/connection.rb:387:in `run_request'
oauth2 (1.4.1) lib/oauth2/client.rb:99:in `request'
oauth2 (1.4.1) lib/oauth2/client.rb:146:in `get_token'
oauth2 (1.4.1) lib/oauth2/strategy/auth_code.rb:30:in `get_token'
omniauth-oauth2 (1.6.0) lib/omniauth/strategies/oauth2.rb:89:in `build_access_token'
omniauth-facebook (5.0.0) lib/omniauth/strategies/facebook.rb:110:in `build_access_token'
omniauth-oauth2 (1.6.0) lib/omniauth/strategies/oauth2.rb:73:in `callback_phase'
omniauth-facebook (5.0.0) lib/omniauth/strategies/facebook.rb:67:in `block in callback_phase'
omniauth-facebook (5.0.0) lib/omniauth/strategies/facebook.rb:131:in `with_authorization_code!'
omniauth-facebook (5.0.0) lib/omniauth/strategies/facebook.rb:66:in `callback_phase'
omniauth (1.9.0) lib/omniauth/strategy.rb:238:in `callback_call'
omniauth (1.9.0) lib/omniauth/strategy.rb:189:in `call!'
omniauth (1.9.0) lib/omniauth/strategy.rb:169:in `call'
omniauth (1.9.0) lib/omniauth/builder.rb:64:in `call'
rack (1.6.11) lib/rack/etag.rb:24:in `call'
rack (1.6.11) lib/rack/conditionalget.rb:25:in `call'
rack (1.6.11) lib/rack/head.rb:13:in `call'
actionpack (4.2.8) lib/action_dispatch/middleware/params_parser.rb:27:in `call'
actionpack (4.2.8) lib/action_dispatch/middleware/flash.rb:260:in `call'
rack (1.6.11) lib/rack/session/abstract/id.rb:225:in `context'
rack (1.6.11) lib/rack/session/abstract/id.rb:220:in `call'
actionpack (4.2.8) lib/action_dispatch/middleware/cookies.rb:560:in `call'
activerecord (4.2.8) lib/active_record/query_cache.rb:36:in `call'
activerecord (4.2.8) lib/active_record/connection_adapters/abstract/connection_pool.rb:653:in `call'
actionpack (4.2.8) lib/action_dispatch/middleware/callbacks.rb:29:in `block in call'
activesupport (4.2.8) lib/active_support/callbacks.rb:88:in `__run_callbacks__'
activesupport (4.2.8) lib/active_support/callbacks.rb:778:in `_run_call_callbacks'
activesupport (4.2.8) lib/active_support/callbacks.rb:81:in `run_callbacks'
actionpack (4.2.8) lib/action_dispatch/middleware/callbacks.rb:27:in `call'
actionpack (4.2.8) lib/action_dispatch/middleware/remote_ip.rb:78:in `call'
actionpack (4.2.8) lib/action_dispatch/middleware/debug_exceptions.rb:17:in `call'
actionpack (4.2.8) lib/action_dispatch/middleware/show_exceptions.rb:30:in `call'
railties (4.2.8) lib/rails/rack/logger.rb:38:in `call_app'
railties (4.2.8) lib/rails/rack/logger.rb:20:in `block in call'
activesupport (4.2.8) lib/active_support/tagged_logging.rb:68:in `block in tagged'
activesupport (4.2.8) lib/active_support/tagged_logging.rb:26:in `tagged'
activesupport (4.2.8) lib/active_support/tagged_logging.rb:68:in `tagged'
railties (4.2.8) lib/rails/rack/logger.rb:20:in `call'
actionpack (4.2.8) lib/action_dispatch/middleware/request_id.rb:21:in `call'
rack (1.6.11) lib/rack/methodoverride.rb:22:in `call'
rack (1.6.11) lib/rack/runtime.rb:18:in `call'
activesupport (4.2.8) lib/active_support/cache/strategy/local_cache_middleware.rb:28:in `call'
actionpack (4.2.8) lib/action_dispatch/middleware/static.rb:120:in `call'
rack (1.6.11) lib/rack/sendfile.rb:113:in `call'
actionpack (4.2.8) lib/action_dispatch/middleware/ssl.rb:24:in `call'
railties (4.2.8) lib/rails/engine.rb:518:in `call'
railties (4.2.8) lib/rails/application.rb:165:in `call'
rack (1.6.11) lib/rack/content_length.rb:15:in `call'
thin (1.7.2) lib/thin/connection.rb:86:in `block in pre_process'
thin (1.7.2) lib/thin/connection.rb:84:in `catch'
thin (1.7.2) lib/thin/connection.rb:84:in `pre_process'
thin (1.7.2) lib/thin/connection.rb:53:in `process'
thin (1.7.2) lib/thin/connection.rb:39:in `receive_data'
eventmachine (1.2.7) lib/eventmachine.rb:195:in `run_machine'
eventmachine (1.2.7) lib/eventmachine.rb:195:in `run'
thin (1.7.2) lib/thin/backends/base.rb:73:in `start'
thin (1.7.2) lib/thin/server.rb:162:in `start'
rack (1.6.11) lib/rack/handler/thin.rb:19:in `run'
rack (1.6.11) lib/rack/server.rb:287:in `start'
railties (4.2.8) lib/rails/commands/server.rb:80:in `start'
railties (4.2.8) lib/rails/commands/commands_tasks.rb:80:in `block in server'
railties (4.2.8) lib/rails/commands/commands_tasks.rb:75:in `tap'
railties (4.2.8) lib/rails/commands/commands_tasks.rb:75:in `server'
railties (4.2.8) lib/rails/commands/commands_tasks.rb:39:in `run_command!'
railties (4.2.8) lib/rails/commands.rb:17:in `<top (required)>'
bin/rails:8:in `require'
bin/rails:8:in `<main>'
I tried creating a test app with Facebook using localhost and it works.
I tried with another app in production with another domain and it works.
It does not work with this particular application in production. I messaged Facebook support, but they don't reply, and days have passed.
I'm using RoR 4.2.8, with Bundler 1.17.3
I tried with ruby-2.5.1 and ruby-2.3.3 just in case (same error)
I tried with another Facebook app with identical settings, using another RoR v5 app with ruby-2.6 and it worked, so the FB app settings seem to be ok.
I created another FB app, to try with the failing RoR v4.2.8 app, and it fails with the same "Faraday::ConnectionFailed (execution expired):" error.
config/initializers/omniauth.rb
Rails.application.config.middleware.use OmniAuth::Builder do
provider :facebook, 'APP-ID', 'SECRET',
scope: 'email'
end
Users should be able lo login using Facebook, but it fails with "Faraday::ConnectionFailed (execution expired):"
From what it looks like is you are having a network issue where Faraday isn't set up to wait long enough for a response. All I can really tell from the trace is that somewhere along the trail to facebook and back you're encountering network issues.
A couple of things I can think to check:
If your site is running through HTTPS, ensure your certificate is working properly.
Check that your gemfile is set to require a specific version of omniauth-facebook that is compatible with your version of Rails and dependencies.
Extend the timeout length for Faraday
Use a retry gem like https://github.com/ooyala/retries to try and give the network enough time to respond before Faraday closes the connection.
A few other people have commented on this issue in omniauth-facebook's github https://github.com/mkdynamic/omniauth-facebook/issues/283

Connecting with Steam's OpenId with Steam OmniAuth gem gives "invalid_credentials" error

I am trying to use the omniauth-steam gem to connect a user through Steam and retrieve the user's ID64. I am running Ruby on Rails 5.0.1 using a server on my local network sporting Apache with Passenger. Whenever I try to connect to /auth/steam I get redirected to the Steam web page with the "Connect" button (I am already logged in). When I click the button I get an error page with the message "invalid_credentials". I am logged in Steam and can browse the site without a problem. Where is that message coming from? How can I fix this? Here is my code so far.
Omniauth initializer:
# config/initializers/omniauth.rb
Rails.application.config.middleware.use OmniAuth::Builder do
provider :steam, Rails.application.secrets.steam_web_api_key
end
Controller:
skip_before_filter :verify_authenticity_token, :only => :auth_callback
def index
end
def auth_callback
auth = request.env['omniauth.auth']
session[:current_user] = {
:nickname => auth.info['nickname'],
:image => auth.info['image'],
:uid => auth.uid
}
redirect_to root_url
end
View:
<p><%= link_to image_tag("http://cdn.steamcommunity.com/public/images/signinthroughsteam/sits_large_noborder.png"), '/auth/steam' %></p>
Routes:
get 'admin/index'
post 'auth/steam/callback' => 'admin#auth_callback'
root 'admin#index'
Error stack:
invalid_credentials
Extracted source (around line #25):
23 def raise_out!
24 fail(env['omniauth.error'] || OmniAuth::Error.new(env['omniauth.error.type']))
25
26 end
27
28 def redirect_to_failure
omniauth (1.3.1) lib/omniauth/failure_endpoint.rb:25:in `raise_out!'
omniauth (1.3.1) lib/omniauth/failure_endpoint.rb:20:in `call'
omniauth (1.3.1) lib/omniauth/failure_endpoint.rb:12:in `call'
omniauth (1.3.1) lib/omniauth/strategy.rb:479:in `fail!'
omniauth-openid (1.0.1) lib/omniauth/strategies/open_id.rb:80:in `callback_phase'
omniauth (1.3.1) lib/omniauth/strategy.rb:227:in `callback_call'
omniauth (1.3.1) lib/omniauth/strategy.rb:184:in `call!'
omniauth (1.3.1) lib/omniauth/strategy.rb:164:in `call'
omniauth (1.3.1) lib/omniauth/builder.rb:63:in `call'
rack (2.0.1) lib/rack/etag.rb:25:in `call'
rack (2.0.1) lib/rack/conditional_get.rb:25:in `call'
rack (2.0.1) lib/rack/head.rb:12:in `call'
rack (2.0.1) lib/rack/session/abstract/id.rb:222:in `context'
rack (2.0.1) lib/rack/session/abstract/id.rb:216:in `call'
actionpack (5.0.1) lib/action_dispatch/middleware/cookies.rb:613:in `call'
activerecord (5.0.1) lib/active_record/migration.rb:553:in `call'
actionpack (5.0.1) lib/action_dispatch/middleware/callbacks.rb:38:in `block in call'
activesupport (5.0.1) lib/active_support/callbacks.rb:97:in `__run_callbacks__'
activesupport (5.0.1) lib/active_support/callbacks.rb:750:in `_run_call_callbacks'
activesupport (5.0.1) lib/active_support/callbacks.rb:90:in `run_callbacks'
actionpack (5.0.1) lib/action_dispatch/middleware/callbacks.rb:36:in `call'
actionpack (5.0.1) lib/action_dispatch/middleware/executor.rb:12:in `call'
actionpack (5.0.1) lib/action_dispatch/middleware/remote_ip.rb:79:in `call'
actionpack (5.0.1) lib/action_dispatch/middleware/debug_exceptions.rb:49:in `call'
web-console (3.4.0) lib/web_console/middleware.rb:135:in `call_app'
web-console (3.4.0) lib/web_console/middleware.rb:20:in `block in call'
web-console (3.4.0) lib/web_console/middleware.rb:18:in `catch'
web-console (3.4.0) lib/web_console/middleware.rb:18:in `call'
actionpack (5.0.1) lib/action_dispatch/middleware/show_exceptions.rb:31:in `call'
railties (5.0.1) lib/rails/rack/logger.rb:36:in `call_app'
railties (5.0.1) lib/rails/rack/logger.rb:24:in `block in call'
activesupport (5.0.1) lib/active_support/tagged_logging.rb:69:in `block in tagged'
activesupport (5.0.1) lib/active_support/tagged_logging.rb:26:in `tagged'
activesupport (5.0.1) lib/active_support/tagged_logging.rb:69:in `tagged'
railties (5.0.1) lib/rails/rack/logger.rb:24:in `call'
sprockets-rails (3.2.0) lib/sprockets/rails/quiet_assets.rb:13:in `call'
actionpack (5.0.1) lib/action_dispatch/middleware/request_id.rb:24:in `call'
rack (2.0.1) lib/rack/method_override.rb:22:in `call'
rack (2.0.1) lib/rack/runtime.rb:22:in `call'
activesupport (5.0.1) lib/active_support/cache/strategy/local_cache_middleware.rb:28:in `call'
actionpack (5.0.1) lib/action_dispatch/middleware/executor.rb:12:in `call'
actionpack (5.0.1) lib/action_dispatch/middleware/static.rb:136:in `call'
rack (2.0.1) lib/rack/sendfile.rb:111:in `call'
railties (5.0.1) lib/rails/engine.rb:522:in `call'
/usr/lib/ruby/vendor_ruby/phusion_passenger/rack/thread_handler_extension.rb:97:in `process_request'
/usr/lib/ruby/vendor_ruby/phusion_passenger/request_handler/thread_handler.rb:152:in `accept_and_process_next_request'
/usr/lib/ruby/vendor_ruby/phusion_passenger/request_handler/thread_handler.rb:113:in `main_loop'
/usr/lib/ruby/vendor_ruby/phusion_passenger/request_handler.rb:416:in `block (3 levels) in start_threads'
/usr/lib/ruby/vendor_ruby/phusion_passenger/utils.rb:113:in `block in create_thread_and_abort_on_exception'
It turns out that in this case it was because of a time difference between the server running the script and Steam's server. The date/time on my server was several minutes off and as soon as I corrected the time discrepancy the error message disappeared and the login process was successful.

Rails 3.2, handle corrupted request bodies (MultiJson::DecodeError)

I'm working on a Rails 3.2.11 application (MRI 1.9.3).
PArt of it is a webservice that receives POST requests with JSON serialized bodies.
Everything works, but I want it to be resilient to bad formatted requests, e.g. invalid JSON.
Right now, if it receives a JSON with – let's say – a missing comma, it will return a 500 error with an HTML response containing the default rails error view (plus the backtrace when in dev).
I want to customize it to return a JSON or XML response with info about the error.
The error is MultiJson::DecodeError and I know I can trap exceptions with rescue_from in the ApplicationController... but it doesn't seem to work.
It's like if the error happened outside of the normal request flow.
This is my code (once I get it working I'll expand the error message with more data):
class ApplicationController < ActionController::Base
#protect_from_forgery
rescue_from MultiJson::DecodeError do |exception|
#response = { :error => "the request body was not acceptable" }
respond_to do |format|
format.html { redirect_to :root, notice: "invalid params" }
format.xml { render :xml => #response, status: 400 }
format.json { render :json => #response, status: 400 }
end
end
end
And this is the backtrace:
MultiJson::DecodeError (795: unexpected token at '{
"json_with_missing_comma" : {
"foo" : "qqqqqqqqqqqqqqq"
"bar" : "aaaaaaaaaaaaaa"
}}'):
json (1.7.6) lib/json/common.rb:155:in `parse'
json (1.7.6) lib/json/common.rb:155:in `parse'
multi_json (1.5.0) lib/multi_json/adapters/json_common.rb:7:in `load'
multi_json (1.5.0) lib/multi_json.rb:96:in `load'
activesupport (3.2.11) lib/active_support/json/decoding.rb:15:in `decode'
actionpack (3.2.11) lib/action_dispatch/middleware/params_parser.rb:47:in `parse_formatted_parameters'
actionpack (3.2.11) lib/action_dispatch/middleware/params_parser.rb:17:in `call'
actionpack (3.2.11) lib/action_dispatch/middleware/flash.rb:242:in `call'
rack (1.4.4) lib/rack/session/abstract/id.rb:210:in `context'
rack (1.4.4) lib/rack/session/abstract/id.rb:205:in `call'
actionpack (3.2.11) lib/action_dispatch/middleware/cookies.rb:341:in `call'
activerecord (3.2.11) lib/active_record/query_cache.rb:64:in `call'
activerecord (3.2.11) lib/active_record/connection_adapters/abstract/connection_pool.rb:479:in `call'
actionpack (3.2.11) lib/action_dispatch/middleware/callbacks.rb:28:in `block in call'
activesupport (3.2.11) lib/active_support/callbacks.rb:405:in `_run__1562301902235545482__call__1964551201027599208__callbacks'
activesupport (3.2.11) lib/active_support/callbacks.rb:405:in `__run_callback'
activesupport (3.2.11) lib/active_support/callbacks.rb:385:in `_run_call_callbacks'
activesupport (3.2.11) lib/active_support/callbacks.rb:81:in `run_callbacks'
actionpack (3.2.11) lib/action_dispatch/middleware/callbacks.rb:27:in `call'
actionpack (3.2.11) lib/action_dispatch/middleware/reloader.rb:65:in `call'
actionpack (3.2.11) lib/action_dispatch/middleware/remote_ip.rb:31:in `call'
actionpack (3.2.11) lib/action_dispatch/middleware/debug_exceptions.rb:16:in `call'
actionpack (3.2.11) lib/action_dispatch/middleware/show_exceptions.rb:56:in `call'
railties (3.2.11) lib/rails/rack/logger.rb:32:in `call_app'
railties (3.2.11) lib/rails/rack/logger.rb:16:in `block in call'
activesupport (3.2.11) lib/active_support/tagged_logging.rb:22:in `tagged'
railties (3.2.11) lib/rails/rack/logger.rb:16:in `call'
actionpack (3.2.11) lib/action_dispatch/middleware/request_id.rb:22:in `call'
rack (1.4.4) lib/rack/methodoverride.rb:21:in `call'
rack (1.4.4) lib/rack/runtime.rb:17:in `call'
activesupport (3.2.11) lib/active_support/cache/strategy/local_cache.rb:72:in `call'
rack (1.4.4) lib/rack/lock.rb:15:in `call'
actionpack (3.2.11) lib/action_dispatch/middleware/static.rb:62:in `call'
railties (3.2.11) lib/rails/engine.rb:479:in `call'
railties (3.2.11) lib/rails/application.rb:223:in `call'
rack (1.4.4) lib/rack/content_length.rb:14:in `call'
railties (3.2.11) lib/rails/rack/log_tailer.rb:17:in `call'
thin (1.5.0) lib/thin/connection.rb:81:in `block in pre_process'
thin (1.5.0) lib/thin/connection.rb:79:in `catch'
thin (1.5.0) lib/thin/connection.rb:79:in `pre_process'
thin (1.5.0) lib/thin/connection.rb:54:in `process'
thin (1.5.0) lib/thin/connection.rb:39:in `receive_data'
eventmachine (1.0.0) lib/eventmachine.rb:187:in `run_machine'
eventmachine (1.0.0) lib/eventmachine.rb:187:in `run'
thin (1.5.0) lib/thin/backends/base.rb:63:in `start'
thin (1.5.0) lib/thin/server.rb:159:in `start'
rack (1.4.4) lib/rack/handler/thin.rb:13:in `run'
rack (1.4.4) lib/rack/server.rb:268:in `start'
railties (3.2.11) lib/rails/commands/server.rb:70:in `start'
railties (3.2.11) lib/rails/commands.rb:55:in `block in <top (required)>'
railties (3.2.11) lib/rails/commands.rb:50:in `tap'
railties (3.2.11) lib/rails/commands.rb:50:in `<top (required)>'
script/rails:6:in `require'
script/rails:6:in `<main>'
The gem: https://github.com/kares/request_exception_handler along with below lines works for me.
In Application controller:
"
rescue_from 'REXML::ParseException' do |exception|
render :text => "Bad Request: XML parse exception", :status => 422
end
rescue_from 'MultiJson::DecodeError' do |exception|
render :text => "Bad Request: JSON parse exception", :status => 422
end
"

Custrom 404 error, routing error stops the app

In ApplicationController I added:
class ApplicationController < ActionController::Base
# This code never reached when routing error occurs
unless Rails.application.config.consider_all_requests_local
rescue_from ActionController::RoutingError, with: :render_404
rescue_from ActionController::UnknownController, with: :render_404
rescue_from ActionController::UnknownAction, with: :render_404
rescue_from ActiveRecord::RecordNotFound, with: :render_404
end
As I am trying to catch exceptions for not found pages, I've noticed that when routing error triggered, the code above never reached, as a result, render_404 never called
Rails.application.config.consider_all_requests_local is false, Any idea ?
Here is what I get:
ActionController::RoutingError (No route matches [GET] "/not_there_route"):
actionpack (3.2.5) lib/action_dispatch/middleware/debug_exceptions.rb:21:in `call'
actionpack (3.2.5) lib/action_dispatch/middleware/show_exceptions.rb:56:in `call'
railties (3.2.5) lib/rails/rack/logger.rb:26:in `call_app'
railties (3.2.5) lib/rails/rack/logger.rb:16:in `call'
actionpack (3.2.5) lib/action_dispatch/middleware/request_id.rb:22:in `call'
rack (1.4.1) lib/rack/methodoverride.rb:21:in `call'
rack (1.4.1) lib/rack/runtime.rb:17:in `call'
activesupport (3.2.5) lib/active_support/cache/strategy/local_cache.rb:72:in `call'
rack (1.4.1) lib/rack/lock.rb:15:in `call'
actionpack (3.2.5) lib/action_dispatch/middleware/static.rb:62:in `call'
railties (3.2.5) lib/rails/engine.rb:479:in `call'
railties (3.2.5) lib/rails/application.rb:220:in `call'
railties (3.2.5) lib/rails/railtie/configurable.rb:30:in `method_missing'
rack (1.4.1) lib/rack/deflater.rb:13:in `call'
rack (1.4.1) lib/rack/content_length.rb:14:in `call'
railties (3.2.5) lib/rails/rack/log_tailer.rb:17:in `call'
thin (1.3.1) lib/thin/connection.rb:80:in `block in pre_process'
thin (1.3.1) lib/thin/connection.rb:78:in `catch'
thin (1.3.1) lib/thin/connection.rb:78:in `pre_process'
thin (1.3.1) lib/thin/connection.rb:53:in `process'
thin (1.3.1) lib/thin/connection.rb:38:in `receive_data'
eventmachine (0.12.10) lib/eventmachine.rb:256:in `run_machine'
eventmachine (0.12.10) lib/eventmachine.rb:256:in `run'
thin (1.3.1) lib/thin/backends/base.rb:61:in `start'
thin (1.3.1) lib/thin/server.rb:159:in `start'
rack (1.4.1) lib/rack/handler/thin.rb:13:in `run'
rack (1.4.1) lib/rack/server.rb:265:in `start'
railties (3.2.5) lib/rails/commands/server.rb:70:in `start'
railties (3.2.5) lib/rails/commands.rb:55:in `block in <top (required)>'
railties (3.2.5) lib/rails/commands.rb:50:in `tap'
railties (3.2.5) lib/rails/commands.rb:50:in `<top (required)>'
You should add catch all route, something like this:
match "*path", :to => "application#routing_error"
More detailed here http://www.bdunagan.com/2012/04/27/rescue_from-routingerror-in-rails-3/

OmniAuth 1.0: NoMethodError when clicking user_omniauth_authorize_path(:facebook) link

I'm having this problem when clicking on user_omniauth_authorize_path(:facebook) link:
Started GET "/users/auth/facebook" for 127.0.0.1 at 2012-02-24 10:57:03 +0200
NoMethodError (undefined method `include?' for nil:NilClass):
omniauth (1.0.2) lib/omniauth/strategy.rb:165:in `call!'
omniauth (1.0.2) lib/omniauth/strategy.rb:148:in `call'
omniauth (1.0.2) lib/omniauth/builder.rb:42:in `call'
warden (1.1.1) lib/warden/manager.rb:35:in `block in call'
warden (1.1.1) lib/warden/manager.rb:34:in `catch'
warden (1.1.1) lib/warden/manager.rb:34:in `call'
actionpack (3.2.1) lib/action_dispatch/middleware/best_standards_support.rb:17:in `call'
rack (1.4.1) lib/rack/etag.rb:23:in `call'
rack (1.4.1) lib/rack/conditionalget.rb:25:in `call'
actionpack (3.2.1) lib/action_dispatch/middleware/head.rb:14:in `call'
actionpack (3.2.1) lib/action_dispatch/middleware/params_parser.rb:21:in `call'
actionpack (3.2.1) lib/action_dispatch/middleware/flash.rb:242:in `call'
rack (1.4.1) lib/rack/session/abstract/id.rb:205:in `context'
rack (1.4.1) lib/rack/session/abstract/id.rb:200:in `call'
actionpack (3.2.1) lib/action_dispatch/middleware/cookies.rb:338:in `call'
activerecord (3.2.1) lib/active_record/query_cache.rb:64:in `call'
activerecord (3.2.1) lib/active_record/connection_adapters/abstract/connection_pool.rb:443:in `call'
actionpack (3.2.1) lib/action_dispatch/middleware/callbacks.rb:28:in `block in call'
activesupport (3.2.1) lib/active_support/callbacks.rb:405:in `_run__2667807547873405266__call__33580566203138325__callbacks'
activesupport (3.2.1) lib/active_support/callbacks.rb:405:in `__run_callback'
activesupport (3.2.1) lib/active_support/callbacks.rb:385:in `_run_call_callbacks'
I'm currently trying to migrate to use OmniAuth 1.0 with omniauth-facebook gem. All this stuff is running with Rails 3.2.1. I was following the tutorial here: https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview
Right now I can't find anything that I did differently than in that tutorial. Still I'm getting this problem when clicking on the Facebook login button on my page.
Digging into a strategy.rb of the omniauth gem, it fails at this point:
return request_call if on_request_path? && OmniAuth.config.allowed_request_methods.include?(request.request_method.downcase.to_sym)
I just added this to an initialization file and it seems to fix the issue.
OmniAuth.config.allowed_request_methods = [:post, :get]
From what I have found, the bug is not within the omniauth gem, but in rack. At least that's what the guys over at github have found. Check the issues:
OmniAuth: https://github.com/intridea/omniauth/issues/568
and
Rack: https://github.com/rack/rack/issues/322
I got it working when I switched from the gems to checking out the repos:
gem 'rack', git: 'https://github.com/rack/rack.git'
gem 'omniauth', git: 'https://github.com/intridea/omniauth.git'

Resources