1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
|
# frozen_string_literal: true
module Doorkeeper
module OAuth
class AuthorizationCodeRequest < BaseRequest
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: Errors::InvalidGrant
validate :code_verifier, error: Errors::InvalidGrant
attr_reader :grant, :client, :redirect_uri, :access_token, :code_verifier,
:invalid_request_reason, :missing_param
def initialize(server, grant, client, parameters = {})
@server = server
@client = client
@grant = grant
@grant_type = Doorkeeper::OAuth::AUTHORIZATION_CODE
@redirect_uri = parameters[:redirect_uri]
@code_verifier = parameters[:code_verifier]
end
private
def before_successful_response
grant.transaction do
grant.lock!
raise Errors::InvalidGrantReuse if grant.revoked?
if Doorkeeper.config.revoke_previous_authorization_code_token?
revoke_previous_tokens(grant.application, resource_owner)
end
grant.revoke
find_or_create_access_token(
client,
resource_owner,
grant.scopes,
custom_token_attributes_with_data,
server,
)
end
super
end
def resource_owner
if Doorkeeper.config.polymorphic_resource_owner?
grant.resource_owner
else
grant.resource_owner_id
end
end
def pkce_supported?
Doorkeeper.config.access_grant_model.pkce_supported?
end
def validate_params
@missing_param =
if grant&.uses_pkce? && code_verifier.blank?
:code_verifier
elsif client && !client.confidential && Doorkeeper.config.force_pkce? && code_verifier.blank?
:code_verifier
elsif redirect_uri.blank?
:redirect_uri
end
@missing_param.nil?
end
def validate_client
client.present?
end
def validate_grant
return false unless grant && grant.application_id == client.id
grant.accessible?
end
def validate_redirect_uri
Helpers::URIChecker.valid_for_authorization?(
redirect_uri,
grant.redirect_uri,
)
end
# if either side (server or client) request PKCE, check the verifier
# against the DB - if PKCE is supported
def validate_code_verifier
return true unless pkce_supported?
return grant.code_challenge.blank? if code_verifier.blank?
if grant.code_challenge_method == "S256"
grant.code_challenge == generate_code_challenge(code_verifier)
elsif grant.code_challenge_method == "plain"
grant.code_challenge == code_verifier
else
false
end
end
def generate_code_challenge(code_verifier)
Doorkeeper.config.access_grant_model.generate_code_challenge(code_verifier)
end
def custom_token_attributes_with_data
grant
.attributes
.with_indifferent_access
.slice(*Doorkeeper.config.custom_access_token_attributes)
.symbolize_keys
end
def revoke_previous_tokens(application, resource_owner)
Doorkeeper.config.access_token_model.revoke_all_for(application.id, resource_owner)
end
end
end
end
|