-
Notifications
You must be signed in to change notification settings - Fork 113
/
controller.rb
115 lines (97 loc) · 3.69 KB
/
controller.rb
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
module Doorkeeper
module OpenidConnect
module Helpers
module Controller
private
def authenticate_resource_owner!
super.tap do |owner|
next unless oidc_authorization_request?
handle_oidc_prompt_param!(owner)
handle_oidc_max_age_param!(owner)
end
rescue Errors::OpenidConnectError => exception
handle_oidc_error!(exception)
end
def oidc_authorization_request?
controller_path == Doorkeeper::Rails::Routes.mapping[:authorizations][:controllers] &&
action_name == 'new' &&
pre_auth.valid? &&
pre_auth.scopes.include?('openid')
end
def handle_oidc_error!(exception)
# clear the previous response body to avoid a DoubleRenderError
self.response_body = nil
# FIXME: workaround for Rails 5, see https://github.com/rails/rails/issues/25106
@_response_body = nil
error_response = if exception.type == :invalid_request
::Doorkeeper::OAuth::InvalidRequestResponse.new(
name: exception.type,
state: params[:state],
redirect_uri: params[:redirect_uri],
)
else
::Doorkeeper::OAuth::ErrorResponse.new(
name: exception.type,
state: params[:state],
redirect_uri: params[:redirect_uri],
)
end
response.headers.merge!(error_response.headers)
if error_response.redirectable?
render json: error_response.body, status: :found, location: error_response.redirect_uri
else
render json: error_response.body, status: error_response.status
end
end
def handle_oidc_prompt_param!(owner)
prompt_values ||= params[:prompt].to_s.split(/ +/).uniq
prompt_values.each do |prompt|
case prompt
when 'none'
raise Errors::InvalidRequest if (prompt_values - [ 'none' ]).any?
raise Errors::LoginRequired unless owner
raise Errors::ConsentRequired if oidc_consent_required?
when 'login'
reauthenticate_oidc_resource_owner(owner) if owner
when 'consent'
render :new
when 'select_account'
# TODO: let the user implement this
raise Errors::AccountSelectionRequired
else
raise Errors::InvalidRequest
end
end
end
def handle_oidc_max_age_param!(owner)
max_age = params[:max_age].to_i
return unless max_age > 0 && owner
auth_time = instance_exec(
owner,
&Doorkeeper::OpenidConnect.configuration.auth_time_from_resource_owner
)
if !auth_time || (Time.zone.now - auth_time) > max_age
reauthenticate_oidc_resource_owner(owner)
end
end
def reauthenticate_oidc_resource_owner(owner)
return_to = URI.parse(request.path)
return_to.query = request.query_parameters.tap do |params|
params['prompt'] = params['prompt'].to_s.sub(/\blogin\s*\b/, '').strip
params.delete('prompt') if params['prompt'].blank?
end.to_query
instance_exec(
owner,
return_to.to_s,
&Doorkeeper::OpenidConnect.configuration.reauthenticate_resource_owner
)
raise Errors::LoginRequired unless performed?
end
def oidc_consent_required?
!skip_authorization? && !matching_token?
end
end
end
end
Helpers::Controller.send :prepend, OpenidConnect::Helpers::Controller
end