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 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
|
# frozen_string_literal: true
module Doorkeeper
class AuthorizationsController < Doorkeeper::ApplicationController
before_action :authenticate_resource_owner!
def new
if pre_auth.authorizable?
render_success
else
render_error
end
end
def create
redirect_or_render(authorize_response)
end
def destroy
redirect_or_render(authorization.deny)
rescue Doorkeeper::Errors::InvalidTokenStrategy => e
error_response = get_error_response_from_exception(e)
if Doorkeeper.configuration.api_only
render json: error_response.body, status: :bad_request
else
render :error, locals: { error_response: error_response }
end
end
private
def render_success
if skip_authorization? || can_authorize_response?
redirect_or_render(authorize_response)
elsif Doorkeeper.configuration.api_only
render json: pre_auth
else
render :new
end
end
def render_error
pre_auth.error_response.raise_exception! if Doorkeeper.config.raise_on_errors?
if Doorkeeper.configuration.redirect_on_errors? && pre_auth.error_response.redirectable?
redirect_or_render(pre_auth.error_response)
elsif Doorkeeper.configuration.api_only
render json: pre_auth.error_response.body, status: pre_auth.error_response.status
else
render :error, locals: { error_response: pre_auth.error_response }, status: pre_auth.error_response.status
end
end
def can_authorize_response?
Doorkeeper.config.custom_access_token_attributes.empty? && pre_auth.client.application.confidential? && matching_token?
end
# Active access token issued for the same client and resource owner with
# the same set of the scopes exists?
def matching_token?
# We don't match tokens on the custom attributes here - we're in the pre-auth here,
# so they haven't been supplied yet (there are no custom attributes to match on yet)
@matching_token ||= Doorkeeper.config.access_token_model.matching_token_for(
pre_auth.client,
current_resource_owner,
pre_auth.scopes,
)
end
def redirect_or_render(auth)
if auth.redirectable?
if Doorkeeper.configuration.api_only
if pre_auth.form_post_response?
render(
json: { status: :post, redirect_uri: pre_auth.redirect_uri, body: auth.body },
status: auth.status,
)
else
render(
json: { status: :redirect, redirect_uri: auth.redirect_uri },
status: auth.status,
)
end
elsif pre_auth.form_post_response?
render :form_post, locals: { auth: auth }
else
redirect_to auth.redirect_uri, allow_other_host: true
end
else
render json: auth.body, status: auth.status
end
end
def pre_auth
@pre_auth ||= OAuth::PreAuthorization.new(
Doorkeeper.configuration,
pre_auth_params,
current_resource_owner,
)
end
def pre_auth_params
params.slice(*pre_auth_param_fields).permit(*pre_auth_param_fields)
end
def pre_auth_param_fields
custom_access_token_attributes + %i[
client_id
code_challenge
code_challenge_method
response_type
response_mode
redirect_uri
scope
state
]
end
def custom_access_token_attributes
Doorkeeper.config.custom_access_token_attributes.map(&:to_sym)
end
def authorization
@authorization ||= strategy.request
end
def strategy
@strategy ||= server.authorization_request(pre_auth.response_type)
end
def authorize_response
@authorize_response ||= begin
return pre_auth.error_response unless pre_auth.authorizable?
context = build_context(pre_auth: pre_auth)
before_successful_authorization(context)
auth = strategy.authorize
context = build_context(auth: auth)
after_successful_authorization(context)
auth
end
end
def build_context(**attributes)
Doorkeeper::OAuth::Hooks::Context.new(**attributes)
end
def before_successful_authorization(context = nil)
Doorkeeper.config.before_successful_authorization.call(self, context)
end
def after_successful_authorization(context)
Doorkeeper.config.after_successful_authorization.call(self, context)
end
end
end
|