Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generic error handling in Strategy #689

Merged

Conversation

joshjordan
Copy link
Contributor

Rescues from strategy calls by calling fail!, properly URL encodes message_key for FailureEndpoint handling

@coveralls
Copy link

Coverage Status

Coverage decreased (-0%) when pulling 7d4b496 on joshjordan:jsj-strategy-generic-error-handling into 0ce4596 on intridea:master.

@joshjordan
Copy link
Contributor Author

Any word on this pull request? Its been open for quite awhile.

This code is necessary for consumers of omniauth to define their own failure handling strategy.

@joshjordan
Copy link
Contributor Author

@BobbyMcWho ?

@BobbyMcWho
Copy link
Member

@joshjordan this had been open for 8 years, 7 since last activity, so I closed it as stale. If you're still interested in this, feel free to rebase your changes onto current master and we can go from there

@BobbyMcWho BobbyMcWho reopened this Dec 7, 2020
@joshjordan joshjordan force-pushed the jsj-strategy-generic-error-handling branch from 7d4b496 to e03a0b1 Compare December 7, 2020 18:38
@joshjordan
Copy link
Contributor Author

@BobbyMcWho understood, but last action was on omniauth to review, which is why I was surprised to see it closed with no comment.

Updated to resolve conflicts with master.

@BobbyMcWho
Copy link
Member

This would be a breaking change, and I'm not confident that the value that it provides is worth adding the breaking change here.

As it is, any failures in the strategy do not call fail! today, and an inherited strategy's before_x_phase and x_phase calls can already handle any errors that occur within them without bubbling them all the way up to base strategy code.

Is there a specific use case you can provide an example of that handling the error within one of those inherited implementations isn't an option?

@joshjordan
Copy link
Contributor Author

joshjordan commented Dec 7, 2020

Sure thing -- that's the encoded in the tests. The simplest example is a generic exception connecting to the third party service when trying to swap e.g. a token for auth credentials.

This isn't about strategies handling errors, its about the consumer being able to handle errors. We have the ability to set an on_failure endpoint, but notably, if there is an unhandled exception, the on_failure endpoint will not be called. OmniAuth will, in fact, just render the error top-level, meaning the user gets a 500 error. As a consumer, if the strategy has not handled the exception explicitly, it is extremely frustrating that there is currently nothing I can do to step my users from seeing errors, despite having properly configured and written a FailureEndpoint implementation according to the omniauth guidance.

As it is, any failures in the strategy do not call fail! today,

And that's the problem, wouldn't you agree?. They just cause the entire endpoint to return a 500, which is unexpected behavior and not useful. I would be quite surprised if anyone desires that behavior, based on the dozens of omniauth developers I've spoken with over the years. Even if it were desired, it can still be achieved because this PR puts it in the consumer's control what to do with the fail! in their FailureEndpoint. So maybe we'd call it a change in behavior, but perhaps not "breaking".

On that topic, I did a review of many of the most popular omniauth strategy implementations. Terribly few of them actually handle exceptions, and when I raised this issue with specific strategies' issue repos, the maintainers were surprised to find that omniauth was not already handling this. Critical implementations, such as ominauth-oauth2 do handle the most common exception cases, but not all of them -- and the vast majority of omniauth strategies have 0 error handling in them. So, sure, they could do the error handling, but I think it is fairly safe to say at this point that in general, they simply do not. Should we really be asking 275+ maintainers to handle errors in 4 different methods, vs. catching exceptions and giving consumers a chance to have their application deal with them?

@joshjordan
Copy link
Contributor Author

To put it differently, this seems to me to be stricly an improvement. If you prefer, I could also allow gem consumers to opt-out of this functionality with a "no thanks, just blow up if there are exceptions" config flag.

return callback_call if on_callback_path?
return other_phase if respond_to?(:other_phase)
rescue => ex
return fail! ex.message, ex
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return fail! ex.message, ex
return fail!(ex.message, ex)

@@ -312,32 +312,41 @@ def make_env(path = '/auth/test', props = {})
context 'disabled' do
it 'does not set omniauth.origin' do
@options = {:origin_param => false}
expect { strategy.call(make_env('/auth/test', 'QUERY_STRING' => 'return=/foo')) }.to raise_error('Request Phase')
strategy.should_receive(:fail!).with('Request Phase', kind_of(StandardError))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you change these to the expect(strategy).to receive(:fail!) syntax?

@joshjordan
Copy link
Contributor Author

joshjordan commented Dec 7, 2020 via email

@BobbyMcWho
Copy link
Member

You make good points, thanks for the detailed explanation.

Now is probably a good time to merge this since I will also be making breaking changes to close the CVE mentioned here: #960

I'm going to point these changes at the 2_0_indev branch.

@BobbyMcWho BobbyMcWho changed the base branch from master to 2_0-indev December 7, 2020 22:30
@BobbyMcWho
Copy link
Member

Can you rebase onto 2_0_indev and resolve any conflicts?

@joshjordan
Copy link
Contributor Author

joshjordan commented Dec 7, 2020 via email

@BobbyMcWho
Copy link
Member

I went ahead and pointed them at it in the GitHub GUI

@joshjordan joshjordan force-pushed the jsj-strategy-generic-error-handling branch from e03a0b1 to 83d2d30 Compare December 7, 2020 23:50
@joshjordan
Copy link
Contributor Author

@BobbyMcWho thanks! I updated the PR with the requested changes

BobbyMcWho added a commit that referenced this pull request Feb 12, 2021
As a consequence of the changes that were merged in #689, errors
thrown by strategies that utilize other_phase (or more specifically
call_app!), would be caught by omniauth, causing headaches for folks
looking to have those errors handled by their application. This
should allow for errors that come from the app to pass through, while
passing errors that come from the authentication phases to the fail!
handler.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants