omniauth
omniauth copied to clipboard
Unable to test auth failure when test_mode is true
I've been playing around with the latest version of Omniauth and its various strategies, and I have come across a rather annoying issue. When I have test_mode set to true in my spec_helper and I am trying to test authentication failures, the authentication callback is always coming back as successful.
For example I have an acceptance test to check that if a user tries to log in using Identity but does not fill in the password field, they should see the authentication error. when I try this in my browser I get the expected outcome, however when I run my spec for this it is always logging in the user even without a password. I have verified this by changing the email address the test users to try and log in.
Yet if I turn test_mode off, all the tests I have pass as expected.
Am I using Omniauths test_mode in the wrong manner or is there a way of acceptance testing with it set to true that means I can actually test what happens when someone tried logging in with invalid credentials.
I've got something similar with the identity strategy, manifesting as /auth/identity/register
returning a 404. Turning off test mode fixes, but it's kind of a pain, since test mode needs to be ON to mock social auth.
thats exactly what I get, its almost as though you should be adding extra routes to your routes file just for testing which seems a little off to me.
Worked around it by adding this middleware to my stack right before OmniAuth::Builder
pretty hacky, but it makes it work. I'm not sure if there's a better way to do this or not.
class OmniAuthMockEnable
def initialize(app)
@app = app
end
def call(env)
if env['PATH_INFO'] =~ /identity/
test = OmniAuth.config.test_mode
OmniAuth.config.test_mode = false
end
@app.call(env)
ensure
OmniAuth.config.test_mode = test
end
end
I was having an issue when I was using: OmniAuth.config.mock_auth[:identity]
When I switch to: OmniAuth.config.add_mock(:identity, :invalid_credentials)
it at least started working, but it is successful every time regardless of setting it to fail.
Same issue. Right now i am not able to test failure endpoint.
The mock auth OmniAuth.config.mock_auth[:facebook] = :invalid_credentials
is ignored and always redirect to the auth/facebook/callback
phase.
Using OmniAuth.config.add_mock(:facebook, :invalid_credentials)
raise an error because it expects an Hash
instead of a Symbol
Testing with browser in development env it's ok. This issue is really annoying because it's impossible to have a complete test. The only different thing i see from other examples is that I am using the setup phase because i need to manage different social apps. Are you using setup phase or it is an independent behaviour?
I currently have the same problem in test mode.
OmniAuth.config.mock_auth[:twitter] = :invalid_credentials
is ignored and the failure endpoint is never used.
Switching test_mode to false does not help though.
Has anybody found a solution to this?
I will take a seat here.
I have just encountered this problem and I was able to trace it to the following lines:
https://github.com/omniauth/omniauth/blob/fce9e23dd4ed33c275485a43b9cc18c1412db9a9/lib/omniauth/strategy.rb#L299-L307
as you can see if you mock the "invalid credentials" scenario with
OmniAuth.config.mock_auth[:twitter] = :invalid_credentials
the code will call fail!
with :invalid_credentials
as a param. fail!
is defined as:
https://github.com/omniauth/omniauth/blob/fce9e23dd4ed33c275485a43b9cc18c1412db9a9/lib/omniauth/strategy.rb#L480-L492
which accepts an optional exception which is never passed.
Also, the setup code above never calls OmniAuth.config.before_callback_phase
so there's no way you can prepare env['omniauth.error']
or the other variables before hand (which would be overridden anyway).
BUT
if you look closely, the last thing fail!
does is call OmniAuth.config.on_failure.call(env)
so I thought to myself: "maybe there's an opportunity there".
I ended up with something like:
OmniAuth.config.mock_auth[:twitter] = :invalid_credentials
global_failure_handler = OmniAuth.config.on_failure
local_failure_handler = proc do |env|
error = OmniAuth::Strategies::OAuth2::CallbackError.new(
"Callback error", "Error reason", "https://example.com/error"
)
env["omniauth.error"] = error
env
end
# here we compose the two handlers into a single function,
# the result will be global_failure_handler(local_failure_handler(env))
failure_handler = global_failure_handler << local_failure_handler
OmniAuth.config.on_failure = failure_handler
visit path
# check stuff
# set `OmniAuth.config.on_failure = global_failure_handler` when you're done
hope it helps someone!