Skip to content

Commit

Permalink
Merge pull request #1680 from camero2734/fix-not-implemented-error-raise
Browse files Browse the repository at this point in the history
Fix handle_auth_errors :raise NotImplementedError
  • Loading branch information
nbulaj committed Dec 1, 2023
2 parents 6692812 + bdf3d50 commit eb849d0
Show file tree
Hide file tree
Showing 21 changed files with 142 additions and 76 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ User-visible changes worth mentioning.

## main

- [#ID] Add your PR description here.
- [#1680] Fix handle_auth_errors :raise NotImplementedError

## 5.6.7

Expand Down
17 changes: 17 additions & 0 deletions lib/doorkeeper/errors.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ class BaseResponseError < DoorkeeperError
def initialize(response)
@response = response
end

def self.name_for_response
self.name.demodulize.underscore.to_sym
end
end

UnableToGenerateToken = Class.new(DoorkeeperError)
Expand All @@ -47,6 +51,19 @@ def initialize(response)

InvalidRequest = Class.new(BaseResponseError)
InvalidToken = Class.new(BaseResponseError)
InvalidClient = Class.new(BaseResponseError)
InvalidScope = Class.new(BaseResponseError)
InvalidRedirectUri = Class.new(BaseResponseError)
InvalidCodeChallengeMethod = Class.new(BaseResponseError)
InvalidGrant = Class.new(BaseResponseError)

UnauthorizedClient = Class.new(BaseResponseError)
UnsupportedResponseType = Class.new(BaseResponseError)
UnsupportedResponseMode = Class.new(BaseResponseError)

AccessDenied = Class.new(BaseResponseError)
ServerError = Class.new(BaseResponseError)

TokenExpired = Class.new(InvalidToken)
TokenRevoked = Class.new(InvalidToken)
TokenUnknown = Class.new(InvalidToken)
Expand Down
10 changes: 5 additions & 5 deletions lib/doorkeeper/oauth/authorization_code_request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
module Doorkeeper
module OAuth
class AuthorizationCodeRequest < BaseRequest
validate :params, error: :invalid_request
validate :client, error: :invalid_client
validate :grant, error: :invalid_grant
validate :params, error: Errors::InvalidRequest
validate :client, error: Errors::InvalidClient
validate :grant, error: Errors::InvalidGrant
# @see https://datatracker.ietf.org/doc/html/rfc6749#section-5.2
validate :redirect_uri, error: :invalid_grant
validate :code_verifier, error: :invalid_grant
validate :redirect_uri, error: Errors::InvalidGrant
validate :code_verifier, error: Errors::InvalidGrant

attr_reader :grant, :client, :redirect_uri, :access_token, :code_verifier,
:invalid_request_reason, :missing_param
Expand Down
2 changes: 1 addition & 1 deletion lib/doorkeeper/oauth/base_request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def authorize
@response = TokenResponse.new(access_token)
after_successful_response
@response
elsif error == :invalid_request
elsif error == Errors::InvalidRequest
@response = InvalidRequestResponse.from_request(self)
else
@response = ErrorResponse.from_request(self)
Expand Down
2 changes: 1 addition & 1 deletion lib/doorkeeper/oauth/client_credentials/issuer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def initialize(server, validator)
def create(client, scopes, attributes = {}, creator = Creator.new)
if validator.valid?
@token = create_token(client, scopes, attributes, creator)
@error = :server_error unless @token
@error = Errors::ServerError unless @token
else
@token = false
@error = validator.error
Expand Down
6 changes: 3 additions & 3 deletions lib/doorkeeper/oauth/client_credentials/validator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ class Validator
include Validations
include OAuth::Helpers

validate :client, error: :invalid_client
validate :client_supports_grant_flow, error: :unauthorized_client
validate :scopes, error: :invalid_scope
validate :client, error: Errors::InvalidClient
validate :client_supports_grant_flow, error: Errors::UnauthorizedClient
validate :scopes, error: Errors::InvalidScope

def initialize(server, request)
@server = server
Expand Down
2 changes: 1 addition & 1 deletion lib/doorkeeper/oauth/code_request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def authorize
end

def deny
pre_auth.error = :access_denied
pre_auth.error = Errors::AccessDenied
pre_auth.error_response
end
end
Expand Down
5 changes: 4 additions & 1 deletion lib/doorkeeper/oauth/error_response.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ class ErrorResponse < BaseResponse
def self.from_request(request, attributes = {})
new(
attributes.merge(
name: request.error,
name: request.error&.name_for_response,
exception_class: request.error,
state: request.try(:state),
redirect_uri: request.try(:redirect_uri),
),
Expand All @@ -21,6 +22,7 @@ def self.from_request(request, attributes = {})

def initialize(attributes = {})
@error = OAuth::Error.new(*attributes.values_at(:name, :state))
@exception_class = attributes[:exception_class]
@redirect_uri = attributes[:redirect_uri]
@response_on_fragment = attributes[:response_on_fragment]
end
Expand Down Expand Up @@ -72,6 +74,7 @@ def realm
end

def exception_class
return @exception_class if @exception_class
raise NotImplementedError, "error response must define #exception_class"
end

Expand Down
8 changes: 4 additions & 4 deletions lib/doorkeeper/oauth/password_access_token_request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ module OAuth
class PasswordAccessTokenRequest < BaseRequest
include OAuth::Helpers

validate :client, error: :invalid_client
validate :client_supports_grant_flow, error: :unauthorized_client
validate :resource_owner, error: :invalid_grant
validate :scopes, error: :invalid_scope
validate :client, error: Errors::InvalidClient
validate :client_supports_grant_flow, error: Errors::UnauthorizedClient
validate :resource_owner, error: Errors::InvalidGrant
validate :scopes, error: Errors::InvalidScope

attr_reader :client, :credentials, :resource_owner, :parameters, :access_token

Expand Down
22 changes: 11 additions & 11 deletions lib/doorkeeper/oauth/pre_authorization.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@ module OAuth
class PreAuthorization
include Validations

validate :client_id, error: :invalid_request
validate :client, error: :invalid_client
validate :client_supports_grant_flow, error: :unauthorized_client
validate :resource_owner_authorize_for_client, error: :invalid_client
validate :redirect_uri, error: :invalid_redirect_uri
validate :params, error: :invalid_request
validate :response_type, error: :unsupported_response_type
validate :response_mode, error: :unsupported_response_mode
validate :scopes, error: :invalid_scope
validate :code_challenge_method, error: :invalid_code_challenge_method
validate :client_id, error: Errors::InvalidRequest
validate :client, error: Errors::InvalidClient
validate :client_supports_grant_flow, error: Errors::UnauthorizedClient
validate :resource_owner_authorize_for_client, error: Errors::InvalidClient
validate :redirect_uri, error: Errors::InvalidRedirectUri
validate :params, error: Errors::InvalidRequest
validate :response_type, error: Errors::UnsupportedResponseType
validate :response_mode, error: Errors::UnsupportedResponseMode
validate :scopes, error: Errors::InvalidScope
validate :code_challenge_method, error: Errors::InvalidCodeChallengeMethod

attr_reader :client, :code_challenge, :code_challenge_method, :missing_param,
:redirect_uri, :resource_owner, :response_type, :state,
Expand Down Expand Up @@ -47,7 +47,7 @@ def scope
end

def error_response
if error == :invalid_request
if error == Errors::InvalidRequest
OAuth::InvalidRequestResponse.from_request(
self,
response_on_fragment: response_on_fragment?,
Expand Down
10 changes: 5 additions & 5 deletions lib/doorkeeper/oauth/refresh_token_request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ module OAuth
class RefreshTokenRequest < BaseRequest
include OAuth::Helpers

validate :token_presence, error: :invalid_request
validate :token, error: :invalid_grant
validate :client, error: :invalid_client
validate :client_match, error: :invalid_grant
validate :scope, error: :invalid_scope
validate :token_presence, error: Errors::InvalidRequest
validate :token, error: Errors::InvalidGrant
validate :client, error: Errors::InvalidClient
validate :client_match, error: Errors::InvalidGrant
validate :scope, error: Errors::InvalidScope

attr_reader :access_token, :client, :credentials, :refresh_token
attr_reader :missing_param
Expand Down
16 changes: 9 additions & 7 deletions lib/doorkeeper/oauth/token_introspection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ module OAuth
#
# @see https://datatracker.ietf.org/doc/html/rfc7662
class TokenIntrospection
attr_reader :error

def initialize(server, token)
@server = server
@token = token
Expand All @@ -20,12 +22,12 @@ def authorized?
def error_response
return if @error.blank?

if @error == :invalid_token
if @error == Errors::InvalidToken
OAuth::InvalidTokenResponse.from_access_token(authorized_token)
elsif @error == :invalid_request
elsif @error == Errors::InvalidRequest
OAuth::InvalidRequestResponse.from_request(self)
else
OAuth::ErrorResponse.new(name: @error)
OAuth::ErrorResponse.from_request(self)
end
end

Expand All @@ -36,7 +38,7 @@ def to_json(*)
private

attr_reader :server, :token
attr_reader :error, :invalid_request_reason
attr_reader :invalid_request_reason

# If the protected resource uses OAuth 2.0 client credentials to
# authenticate to the introspection endpoint and its credentials are
Expand All @@ -58,7 +60,7 @@ def to_json(*)
def authorize!
# Requested client authorization
if server.credentials
@error = :invalid_client unless authorized_client
@error = Errors::InvalidClient unless authorized_client
elsif authorized_token
# Requested bearer token authorization
#
Expand All @@ -69,9 +71,9 @@ def authorize!
# HTTP 401 code as described in Section 3 of OAuth 2.0 Bearer Token
# Usage [RFC6750].
#
@error = :invalid_token unless valid_authorized_token?
@error = Errors::InvalidToken unless valid_authorized_token?
else
@error = :invalid_request
@error = Errors::InvalidRequest
@invalid_request_reason = :request_not_authorized
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/doorkeeper/oauth/token_request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def authorize
end

def deny
pre_auth.error = :access_denied
pre_auth.error = Errors::AccessDenied
pre_auth.error_response
end
end
Expand Down
46 changes: 45 additions & 1 deletion spec/controllers/authorizations_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1156,7 +1156,7 @@ def query_params
default_scopes_exist :public
end

it "does not redirect" do
it "raises InvalidRequest error" do
expect { get :new, params: { an_invalid: "request" } }.to raise_error(Doorkeeper::Errors::InvalidRequest)
end

Expand All @@ -1165,6 +1165,50 @@ def query_params
expect(Doorkeeper::AccessToken.count).to eq 0
end
end

context "invalid client_id" do
before do
default_scopes_exist :public
end

it "raises InvalidClient error" do
expect { get :new, params: { client_id: "invalid" } }.to raise_error(Doorkeeper::Errors::InvalidClient)
end
end

context "invalid scope" do
before do
default_scopes_exist :public
end

it "raises InvalidScope error" do
expect do
get :new, params: {
client_id: client.uid,
response_type: "token",
scope: "invalid",
redirect_uri: client.redirect_uri,
state: "return-this",
}
end.to raise_error(Doorkeeper::Errors::InvalidScope)
end
end

context "invalid redirect_uri" do
before do
default_scopes_exist :public
end

it "raises InvalidRedirectUri error" do
expect do
get :new, params: {
client_id: client.uid,
response_type: "token",
redirect_uri: "invalid",
}
end.to raise_error(Doorkeeper::Errors::InvalidRedirectUri)
end
end
end

describe "GET #new with callbacks" do
Expand Down
20 changes: 10 additions & 10 deletions spec/lib/oauth/authorization_code_request_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,39 +50,39 @@
it "requires the grant to be accessible" do
grant.revoke
request.validate
expect(request.error).to eq(:invalid_grant)
expect(request.error).to eq(Doorkeeper::Errors::InvalidGrant)
end

it "requires the grant" do
request = described_class.new(server, nil, client, params)
request.validate
expect(request.error).to eq(:invalid_grant)
expect(request.error).to eq(Doorkeeper::Errors::InvalidGrant)
end

it "requires the client" do
request = described_class.new(server, grant, nil, params)
request.validate
expect(request.error).to eq(:invalid_client)
expect(request.error).to eq(Doorkeeper::Errors::InvalidClient)
end

it "requires the redirect_uri" do
request = described_class.new(server, grant, nil, params.except(:redirect_uri))
request.validate
expect(request.error).to eq(:invalid_request)
expect(request.error).to eq(Doorkeeper::Errors::InvalidRequest)
expect(request.missing_param).to eq(:redirect_uri)
end

it "matches the redirect_uri with grant's one" do
request = described_class.new(server, grant, client, params.merge(redirect_uri: "http://other.com"))
request.validate
expect(request.error).to eq(:invalid_grant)
expect(request.error).to eq(Doorkeeper::Errors::InvalidGrant)
end

it "matches the client with grant's one" do
other_client = FactoryBot.create :application
request = described_class.new(server, grant, other_client, params)
request.validate
expect(request.error).to eq(:invalid_grant)
expect(request.error).to eq(Doorkeeper::Errors::InvalidGrant)
end

it "skips token creation if there is a matching one reusable" do
Expand Down Expand Up @@ -150,7 +150,7 @@

it "responds with invalid_grant" do
request.validate
expect(request.error).to eq(:invalid_grant)
expect(request.error).to eq(Doorkeeper::Errors::InvalidGrant)
end
end

Expand All @@ -159,7 +159,7 @@

it "invalidates when redirect_uri of the grant is not native" do
request.validate
expect(request.error).to eq(:invalid_grant)
expect(request.error).to eq(Doorkeeper::Errors::InvalidGrant)
end

it "validates when redirect_uri of the grant is also native" do
Expand Down Expand Up @@ -195,15 +195,15 @@
it "invalidates when code_verifier is missing" do
request.validate

expect(request.error).to eq(:invalid_request)
expect(request.error).to eq(Doorkeeper::Errors::InvalidRequest)
expect(request.missing_param).to eq(:code_verifier)
end

it "invalidates when code_verifier is the wrong value" do
params[:code_verifier] = "foobar"
request.validate

expect(request.error).to eq(:invalid_grant)
expect(request.error).to eq(Doorkeeper::Errors::InvalidGrant)
end
end

Expand Down

0 comments on commit eb849d0

Please sign in to comment.