doorkeeper-openid_connect 1.6.3 → 1.7.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +55 -1
- data/README.md +11 -0
- data/app/controllers/doorkeeper/authorizations_controller.rb +17 -0
- data/app/controllers/doorkeeper/openid_connect/discovery_controller.rb +25 -19
- data/app/controllers/doorkeeper/openid_connect/userinfo_controller.rb +5 -1
- data/config/locales/en.yml +1 -0
- data/lib/doorkeeper/oauth/id_token_request.rb +8 -12
- data/lib/doorkeeper/oauth/id_token_response.rb +2 -0
- data/lib/doorkeeper/oauth/id_token_token_request.rb +2 -0
- data/lib/doorkeeper/oauth/id_token_token_response.rb +2 -0
- data/lib/doorkeeper/openid_connect.rb +26 -1
- data/lib/doorkeeper/openid_connect/claims/aggregated_claim.rb +2 -0
- data/lib/doorkeeper/openid_connect/claims/claim.rb +6 -4
- data/lib/doorkeeper/openid_connect/claims/distributed_claim.rb +2 -0
- data/lib/doorkeeper/openid_connect/claims/normal_claim.rb +2 -0
- data/lib/doorkeeper/openid_connect/claims_builder.rb +3 -1
- data/lib/doorkeeper/openid_connect/config.rb +20 -10
- data/lib/doorkeeper/openid_connect/engine.rb +2 -0
- data/lib/doorkeeper/openid_connect/errors.rb +4 -3
- data/lib/doorkeeper/openid_connect/helpers/controller.rb +58 -31
- data/lib/doorkeeper/openid_connect/id_token.rb +4 -2
- data/lib/doorkeeper/openid_connect/id_token_token.rb +2 -0
- data/lib/doorkeeper/openid_connect/oauth/authorization/code.rb +25 -8
- data/lib/doorkeeper/openid_connect/oauth/authorization_code_request.rb +4 -2
- data/lib/doorkeeper/openid_connect/oauth/password_access_token_request.rb +3 -1
- data/lib/doorkeeper/openid_connect/oauth/pre_authorization.rb +24 -3
- data/lib/doorkeeper/openid_connect/oauth/token_response.rb +3 -1
- data/lib/doorkeeper/openid_connect/orm/active_record.rb +2 -0
- data/lib/doorkeeper/openid_connect/orm/active_record/access_grant.rb +3 -1
- data/lib/doorkeeper/openid_connect/orm/active_record/request.rb +5 -3
- data/lib/doorkeeper/openid_connect/rails/routes.rb +3 -1
- data/lib/doorkeeper/openid_connect/rails/routes/mapper.rb +2 -0
- data/lib/doorkeeper/openid_connect/rails/routes/mapping.rb +2 -0
- data/lib/doorkeeper/openid_connect/response_mode.rb +30 -0
- data/lib/doorkeeper/openid_connect/response_types_config.rb +2 -2
- data/lib/doorkeeper/openid_connect/user_info.rb +2 -0
- data/lib/doorkeeper/openid_connect/version.rb +3 -1
- data/lib/doorkeeper/request/id_token.rb +2 -0
- data/lib/doorkeeper/request/id_token_token.rb +2 -0
- data/lib/generators/doorkeeper/openid_connect/install_generator.rb +4 -2
- data/lib/generators/doorkeeper/openid_connect/migration_generator.rb +3 -1
- data/lib/generators/doorkeeper/openid_connect/templates/initializer.rb +19 -5
- data/lib/generators/doorkeeper/openid_connect/templates/migration.rb.erb +3 -2
- metadata +29 -36
- data/.gitignore +0 -8
- data/.ruby-version +0 -1
- data/.travis.yml +0 -34
- data/CONTRIBUTING.md +0 -45
- data/Gemfile +0 -11
- data/Rakefile +0 -24
- data/bin/console +0 -9
- data/bin/setup +0 -8
- data/doorkeeper-openid_connect.gemspec +0 -30
@@ -1,9 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Doorkeeper
|
2
4
|
module OpenidConnect
|
3
5
|
module Errors
|
4
6
|
class OpenidConnectError < StandardError
|
5
|
-
def
|
6
|
-
self.class.name.demodulize.underscore
|
7
|
+
def type
|
8
|
+
self.class.name.demodulize.underscore.to_sym
|
7
9
|
end
|
8
10
|
end
|
9
11
|
|
@@ -24,7 +26,6 @@ module Doorkeeper
|
|
24
26
|
class LoginRequired < OpenidConnectError; end
|
25
27
|
class ConsentRequired < OpenidConnectError; end
|
26
28
|
class InteractionRequired < OpenidConnectError; end
|
27
|
-
class AccountSelectionRequired < OpenidConnectError; end
|
28
29
|
end
|
29
30
|
end
|
30
31
|
end
|
@@ -1,9 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Doorkeeper
|
2
4
|
module OpenidConnect
|
3
5
|
module Helpers
|
4
6
|
module Controller
|
5
7
|
private
|
6
8
|
|
9
|
+
# FIXME: remove after Doorkeeper will merge it
|
10
|
+
def current_resource_owner
|
11
|
+
return @current_resource_owner if defined?(@current_resource_owner)
|
12
|
+
|
13
|
+
super
|
14
|
+
end
|
15
|
+
|
7
16
|
def authenticate_resource_owner!
|
8
17
|
super.tap do |owner|
|
9
18
|
next unless oidc_authorization_request?
|
@@ -11,14 +20,14 @@ module Doorkeeper
|
|
11
20
|
handle_oidc_prompt_param!(owner)
|
12
21
|
handle_oidc_max_age_param!(owner)
|
13
22
|
end
|
14
|
-
rescue Errors::OpenidConnectError =>
|
15
|
-
handle_oidc_error!(
|
23
|
+
rescue Errors::OpenidConnectError => e
|
24
|
+
handle_oidc_error!(e)
|
16
25
|
end
|
17
26
|
|
18
27
|
def oidc_authorization_request?
|
19
28
|
controller_path == Doorkeeper::Rails::Routes.mapping[:authorizations][:controllers] &&
|
20
29
|
action_name == 'new' &&
|
21
|
-
pre_auth.
|
30
|
+
pre_auth.valid? &&
|
22
31
|
pre_auth.scopes.include?('openid')
|
23
32
|
end
|
24
33
|
|
@@ -29,14 +38,20 @@ module Doorkeeper
|
|
29
38
|
# FIXME: workaround for Rails 5, see https://github.com/rails/rails/issues/25106
|
30
39
|
@_response_body = nil
|
31
40
|
|
32
|
-
error_response = if
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
41
|
+
error_response = if exception.type == :invalid_request
|
42
|
+
::Doorkeeper::OAuth::InvalidRequestResponse.new(
|
43
|
+
name: exception.type,
|
44
|
+
state: params[:state],
|
45
|
+
redirect_uri: params[:redirect_uri],
|
46
|
+
response_on_fragment: pre_auth.response_on_fragment?,
|
47
|
+
)
|
48
|
+
else
|
49
|
+
::Doorkeeper::OAuth::ErrorResponse.new(
|
50
|
+
name: exception.type,
|
51
|
+
state: params[:state],
|
52
|
+
redirect_uri: params[:redirect_uri],
|
53
|
+
response_on_fragment: pre_auth.response_on_fragment?,
|
54
|
+
)
|
40
55
|
end
|
41
56
|
|
42
57
|
response.headers.merge!(error_response.headers)
|
@@ -53,17 +68,16 @@ module Doorkeeper
|
|
53
68
|
|
54
69
|
prompt_values.each do |prompt|
|
55
70
|
case prompt
|
56
|
-
when 'none'
|
57
|
-
raise Errors::InvalidRequest if (prompt_values - [
|
71
|
+
when 'none'
|
72
|
+
raise Errors::InvalidRequest if (prompt_values - ['none']).any?
|
58
73
|
raise Errors::LoginRequired unless owner
|
59
|
-
raise Errors::ConsentRequired if oidc_consent_required?
|
60
|
-
when 'login'
|
74
|
+
raise Errors::ConsentRequired if oidc_consent_required?
|
75
|
+
when 'login'
|
61
76
|
reauthenticate_oidc_resource_owner(owner) if owner
|
62
|
-
when 'consent'
|
77
|
+
when 'consent'
|
63
78
|
render :new
|
64
|
-
when 'select_account'
|
65
|
-
|
66
|
-
raise Errors::AccountSelectionRequired
|
79
|
+
when 'select_account'
|
80
|
+
select_account_for_oidc_resource_owner(owner)
|
67
81
|
else
|
68
82
|
raise Errors::InvalidRequest
|
69
83
|
end
|
@@ -74,40 +88,53 @@ module Doorkeeper
|
|
74
88
|
max_age = params[:max_age].to_i
|
75
89
|
return unless max_age > 0 && owner
|
76
90
|
|
77
|
-
auth_time = instance_exec
|
91
|
+
auth_time = instance_exec(
|
92
|
+
owner,
|
78
93
|
&Doorkeeper::OpenidConnect.configuration.auth_time_from_resource_owner
|
94
|
+
)
|
79
95
|
|
80
96
|
if !auth_time || (Time.zone.now - auth_time) > max_age
|
81
97
|
reauthenticate_oidc_resource_owner(owner)
|
82
98
|
end
|
83
99
|
end
|
84
100
|
|
85
|
-
def
|
101
|
+
def return_without_oidc_prompt_param(prompt_value)
|
86
102
|
return_to = URI.parse(request.path)
|
87
103
|
return_to.query = request.query_parameters.tap do |params|
|
88
|
-
params['prompt'] = params['prompt'].to_s.sub(/\
|
104
|
+
params['prompt'] = params['prompt'].to_s.sub(/\b#{prompt_value}\s*\b/, '').strip
|
89
105
|
params.delete('prompt') if params['prompt'].blank?
|
90
106
|
end.to_query
|
107
|
+
return_to.to_s
|
108
|
+
end
|
109
|
+
|
110
|
+
def reauthenticate_oidc_resource_owner(owner)
|
111
|
+
return_to = return_without_oidc_prompt_param('login')
|
91
112
|
|
92
|
-
instance_exec
|
113
|
+
instance_exec(
|
114
|
+
owner,
|
115
|
+
return_to,
|
93
116
|
&Doorkeeper::OpenidConnect.configuration.reauthenticate_resource_owner
|
117
|
+
)
|
94
118
|
|
95
119
|
raise Errors::LoginRequired unless performed?
|
96
120
|
end
|
97
121
|
|
98
|
-
def
|
99
|
-
|
100
|
-
Doorkeeper::AccessToken.scopes_match?(token.scopes, pre_auth.scopes, pre_auth.client.scopes)
|
101
|
-
end
|
122
|
+
def oidc_consent_required?
|
123
|
+
!skip_authorization? && !matching_token?
|
102
124
|
end
|
103
125
|
|
104
|
-
def
|
105
|
-
|
106
|
-
|
126
|
+
def select_account_for_oidc_resource_owner(owner)
|
127
|
+
return_to = return_without_oidc_prompt_param('select_account')
|
128
|
+
|
129
|
+
instance_exec(
|
130
|
+
owner,
|
131
|
+
return_to,
|
132
|
+
&Doorkeeper::OpenidConnect.configuration.select_account_for_resource_owner
|
133
|
+
)
|
107
134
|
end
|
108
135
|
end
|
109
136
|
end
|
110
137
|
end
|
111
138
|
|
112
|
-
Helpers::Controller.
|
139
|
+
Helpers::Controller.prepend OpenidConnect::Helpers::Controller
|
113
140
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Doorkeeper
|
2
4
|
module OpenidConnect
|
3
5
|
class IdToken
|
@@ -9,7 +11,7 @@ module Doorkeeper
|
|
9
11
|
@access_token = access_token
|
10
12
|
@nonce = nonce
|
11
13
|
@resource_owner = Doorkeeper::OpenidConnect.configuration.resource_owner_from_access_token.call(access_token)
|
12
|
-
@issued_at = Time.now
|
14
|
+
@issued_at = Time.zone.now
|
13
15
|
end
|
14
16
|
|
15
17
|
def claims
|
@@ -46,7 +48,7 @@ module Doorkeeper
|
|
46
48
|
end
|
47
49
|
|
48
50
|
def audience
|
49
|
-
@access_token.application.uid
|
51
|
+
@access_token.application.try(:uid)
|
50
52
|
end
|
51
53
|
|
52
54
|
def expiration
|
@@ -1,22 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Doorkeeper
|
2
4
|
module OpenidConnect
|
3
5
|
module OAuth
|
4
6
|
module Authorization
|
5
7
|
module Code
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
8
|
+
if Doorkeeper::OAuth::Authorization::Code.method_defined?(:issue_token!)
|
9
|
+
def issue_token!
|
10
|
+
super.tap do |access_grant|
|
11
|
+
create_openid_request(access_grant) if pre_auth.nonce.present?
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
alias issue_token issue_token!
|
16
|
+
else
|
17
|
+
# FIXME: drop this after dropping support of Doorkeeper < 5.4
|
18
|
+
def issue_token
|
19
|
+
super.tap do |access_grant|
|
20
|
+
create_openid_request(access_grant) if pre_auth.nonce.present?
|
13
21
|
end
|
14
22
|
end
|
15
23
|
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def create_openid_request(access_grant)
|
28
|
+
::Doorkeeper::OpenidConnect::Request.create!(
|
29
|
+
access_grant: access_grant,
|
30
|
+
nonce: pre_auth.nonce
|
31
|
+
)
|
32
|
+
end
|
16
33
|
end
|
17
34
|
end
|
18
35
|
end
|
19
36
|
end
|
20
37
|
|
21
|
-
OAuth::Authorization::Code.
|
38
|
+
OAuth::Authorization::Code.prepend OpenidConnect::OAuth::Authorization::Code
|
22
39
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Doorkeeper
|
2
4
|
module OpenidConnect
|
3
5
|
module OAuth
|
@@ -8,7 +10,7 @@ module Doorkeeper
|
|
8
10
|
super
|
9
11
|
|
10
12
|
nonce =
|
11
|
-
if openid_request = grant.openid_request
|
13
|
+
if (openid_request = grant.openid_request)
|
12
14
|
openid_request.destroy!
|
13
15
|
openid_request.nonce
|
14
16
|
end
|
@@ -20,5 +22,5 @@ module Doorkeeper
|
|
20
22
|
end
|
21
23
|
end
|
22
24
|
|
23
|
-
OAuth::AuthorizationCodeRequest.
|
25
|
+
OAuth::AuthorizationCodeRequest.prepend OpenidConnect::OAuth::AuthorizationCodeRequest
|
24
26
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Doorkeeper
|
2
4
|
module OpenidConnect
|
3
5
|
module OAuth
|
@@ -20,5 +22,5 @@ module Doorkeeper
|
|
20
22
|
end
|
21
23
|
end
|
22
24
|
|
23
|
-
OAuth::PasswordAccessTokenRequest.
|
25
|
+
OAuth::PasswordAccessTokenRequest.prepend OpenidConnect::OAuth::PasswordAccessTokenRequest
|
24
26
|
end
|
@@ -1,16 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Doorkeeper
|
2
4
|
module OpenidConnect
|
3
5
|
module OAuth
|
4
6
|
module PreAuthorization
|
5
7
|
attr_reader :nonce
|
6
8
|
|
7
|
-
def initialize(server,
|
8
|
-
|
9
|
+
def initialize(server, attrs = {}, resource_owner = nil)
|
10
|
+
if (Doorkeeper::VERSION::MAJOR >= 5 && Doorkeeper::VERSION::MINOR >= 4) ||
|
11
|
+
Doorkeeper::VERSION::MAJOR >= 6
|
12
|
+
super
|
13
|
+
else
|
14
|
+
super(server, attrs)
|
15
|
+
end
|
9
16
|
@nonce = attrs[:nonce]
|
10
17
|
end
|
18
|
+
|
19
|
+
# This method will be updated when doorkeeper move to version > 5.2.2
|
20
|
+
# TODO: delete this method and refactor response_on_fragment? method (below) when doorkeeper gem version constrains is > 5.2.2
|
21
|
+
def error_response
|
22
|
+
if error == :invalid_request
|
23
|
+
Doorkeeper::OAuth::InvalidRequestResponse.from_request(self, response_on_fragment: response_on_fragment?)
|
24
|
+
else
|
25
|
+
Doorkeeper::OAuth::ErrorResponse.from_request(self, response_on_fragment: response_on_fragment?)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def response_on_fragment?
|
30
|
+
Doorkeeper::OpenidConnect::ResponseMode.new(response_type).fragment?
|
31
|
+
end
|
11
32
|
end
|
12
33
|
end
|
13
34
|
end
|
14
35
|
|
15
|
-
OAuth::PreAuthorization.
|
36
|
+
OAuth::PreAuthorization.prepend OpenidConnect::OAuth::PreAuthorization
|
16
37
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Doorkeeper
|
2
4
|
module OpenidConnect
|
3
5
|
module OAuth
|
@@ -19,5 +21,5 @@ module Doorkeeper
|
|
19
21
|
end
|
20
22
|
end
|
21
23
|
|
22
|
-
OAuth::TokenResponse.
|
24
|
+
OAuth::TokenResponse.prepend OpenidConnect::OAuth::TokenResponse
|
23
25
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Doorkeeper
|
2
4
|
module OpenidConnect
|
3
5
|
module AccessGrant
|
@@ -12,5 +14,5 @@ module Doorkeeper
|
|
12
14
|
end
|
13
15
|
end
|
14
16
|
|
15
|
-
AccessGrant.
|
17
|
+
AccessGrant.prepend OpenidConnect::AccessGrant
|
16
18
|
end
|
@@ -1,12 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Doorkeeper
|
2
4
|
module OpenidConnect
|
3
|
-
class Request <
|
5
|
+
class Request < ApplicationRecord
|
4
6
|
self.table_name = "#{table_name_prefix}oauth_openid_requests#{table_name_suffix}".to_sym
|
5
7
|
|
6
8
|
validates :access_grant_id, :nonce, presence: true
|
7
9
|
belongs_to :access_grant,
|
8
|
-
|
9
|
-
|
10
|
+
class_name: 'Doorkeeper::AccessGrant',
|
11
|
+
inverse_of: :openid_request
|
10
12
|
end
|
11
13
|
end
|
12
14
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'doorkeeper/openid_connect/rails/routes/mapping'
|
2
4
|
require 'doorkeeper/openid_connect/rails/routes/mapper'
|
3
5
|
|
@@ -12,7 +14,7 @@ module Doorkeeper
|
|
12
14
|
end
|
13
15
|
|
14
16
|
def self.install!
|
15
|
-
ActionDispatch::Routing::Mapper.
|
17
|
+
ActionDispatch::Routing::Mapper.include Doorkeeper::OpenidConnect::Rails::Routes::Helper
|
16
18
|
end
|
17
19
|
|
18
20
|
attr_accessor :routes
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Doorkeeper
|
4
|
+
module OpenidConnect
|
5
|
+
class ResponseMode
|
6
|
+
attr_reader :type
|
7
|
+
|
8
|
+
def initialize(response_type)
|
9
|
+
@type = response_type
|
10
|
+
end
|
11
|
+
|
12
|
+
def fragment?
|
13
|
+
mode == 'fragment'
|
14
|
+
end
|
15
|
+
|
16
|
+
def query?
|
17
|
+
mode == 'query'
|
18
|
+
end
|
19
|
+
|
20
|
+
def mode
|
21
|
+
case type
|
22
|
+
when 'token', 'id_token', 'id_token token'
|
23
|
+
'fragment'
|
24
|
+
else
|
25
|
+
'query'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|