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

Fix handle_auth_errors :raise NotImplementedError #1680

Merged

Conversation

camero2734
Copy link
Contributor

@camero2734 camero2734 commented Nov 23, 2023

Summary

Fixes #1679, and follow-up to #1676

ErrorResponse requires a subclass to override its exception_class method, otherwise it throws an error when raise_exception! is called. However, with the recent change in #1676, we call ErrorResponse#raise_exception! quite often, which causes NotImplementedErrors to be raised when handle_auth_errors is set to :raise

This PR fixes this by creating a new Error type for each standard OAuth error that Doorkeeper handles, so that you can rescue specific errors when in :raise mode.

Instead of validate taking a symbol, it now expects a class that extends BaseResponseError:

# Before
validate :something,  error: :some_symbol

# After
validate :something,  error: Errors::Something

This accounts for the majority of the changes in the PR. This is the error that will be thrown in :raise mode.

Possible Improvements

I just recovered the symbol name (which is used for the error query param according to the spec) via Class.to_s.demodulize.underscore, but perhaps we would like to explicitly provide this when constructing the classes.

Alternatives

We could create a XXXErrorResponse for every OAuth error, such as InvalidClientErrorResponse and InvalidGrantErrorResponse

We could just remove the NotImplementedError from ErrorResponse#exception_class and replace it with a new, single error type like Errors::GenericOAuth or something

@camero2734 camero2734 force-pushed the fix-not-implemented-error-raise branch 5 times, most recently from 7cdb9ec to 89b7562 Compare November 23, 2023 14:54
@camero2734 camero2734 marked this pull request as ready for review November 23, 2023 15:21
@camero2734 camero2734 force-pushed the fix-not-implemented-error-raise branch 2 times, most recently from 58b6722 to 0585cc5 Compare November 23, 2023 16:49
@nbulaj
Copy link
Member

nbulaj commented Nov 24, 2023

Looks dangerous 😟 need some proper review

@camero2734
Copy link
Contributor Author

camero2734 commented Nov 24, 2023

@nbulaj Hmmm, if you'd prefer we could just do the last alternative, which is to just remove the NotImplementedError and just create a single Errors::GenericOAuth that's raised. Not too big of an issue since you can find out the type of error via error.response.name I believe. Probably only a few files changed in that route as compared to 20+ 😅

ETA: Simpler one is here just in case main...camero2734:doorkeeper:fix-not-implemented-error-raise-generic

@nbulaj
Copy link
Member

nbulaj commented Nov 24, 2023

Yeah actually looks good, nice work 💪 Have to just check openid-connect gem - maybe it uses some custom errors and we can break something for it.

@camero2734
Copy link
Contributor Author

@nbulaj After the last commit I pushed, I got all ✅ in openid-connect gem tests locally, just had to change these tests:

--- a/spec/controllers/doorkeeper/authorizations_controller_spec.rb
+++ b/spec/controllers/doorkeeper/authorizations_controller_spec.rb
@@ -82,14 +82,14 @@ describe Doorkeeper::AuthorizationsController, type: :controller do
         it 'render error when client_id is missing' do
           authorize!(client_id: nil)

-          expect(response).to be_successful
+          expect(response).to have_http_status(:bad_request)
           expect(response).to render_template('doorkeeper/authorizations/error')
         end

         it 'render error when response_type is missing' do
           authorize!(response_type: nil)

-          expect(response).to be_successful
+          expect(response).to have_http_status(:bad_request)
           expect(response).to render_template('doorkeeper/authorizations/error')
         end
       end

which is just a result of the last PR's status code changes

@camero2734 camero2734 force-pushed the fix-not-implemented-error-raise branch 3 times, most recently from 04ec263 to 6d757ad Compare November 24, 2023 15:22
@camero2734 camero2734 force-pushed the fix-not-implemented-error-raise branch from 6d757ad to 051d9ac Compare November 24, 2023 15:26
lib/doorkeeper/errors.rb Outdated Show resolved Hide resolved
The "friendly" name of the error that's sent as a query param (?error=friendly_name)
on error responses is, by default, the name of the error class, formatted to snake case.

This change moves this definition to a method in the base class
`BaseResponseError#name_for_response`

This way, if ever needed, the `name_for_response` can be overridden by doing:
```rb
SomeName = Class.new(BaseResponseError) do
  def self.name_for_response
    :some_other_name
  end
end
```
@camero2734 camero2734 force-pushed the fix-not-implemented-error-raise branch from 051d9ac to bdf3d50 Compare November 28, 2023 10:26
@camero2734 camero2734 requested a review from nbulaj November 28, 2023 10:27
Copy link
Member

@nbulaj nbulaj left a comment

Choose a reason for hiding this comment

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

LGTM 👍

@nbulaj nbulaj merged commit eb849d0 into doorkeeper-gem:main Dec 1, 2023
17 of 20 checks passed
@camero2734 camero2734 deleted the fix-not-implemented-error-raise branch December 1, 2023 18:37
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.

NotImplementedError error response must define #exception_class after upgrading to 5.6.7 from 5.6.6
2 participants