doorkeeper-openid_connect 1.8.11 → 1.9.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3f528fd39b26ece5800ff5a5cc38b8fdd0945c5bd9298e6a03bad7df0f7fe9c9
4
- data.tar.gz: cefcf626ab0f1cbf825a792b529b643081c3be96dcdbc922507e06cd3844218c
3
+ metadata.gz: b43afb85064c2b12a0837aec166ab720b352813fec7004dfce38cfc0b4338fc6
4
+ data.tar.gz: de24da5d37377dadf9cb2bffcdf15c2b725075327efe301e0a1c907748ced3b8
5
5
  SHA512:
6
- metadata.gz: 3a16a5cc0bf3de2e6232900126d111093f6313bc00264ee77e9385260bef586b22152971905b87e728eff7eeb7fde16fd67d73843c13ba88b17925ebc6d41f7b
7
- data.tar.gz: d7215370a0be9369fe05a61cd4fee8d2df68a79bdbd104f4cde638e704c83637f23af76369afa532dc68b349f180fdb2ccb6e7772d87647356b0e3018424230e
6
+ metadata.gz: 0e9c242e0e9dbf48500810be186040b6cdc4afdb564196453a005ae420b9f61e6b104afcfeb1e71be2f9d1356ccca8ec1265a1e8dfdd12a0e796a9d8d19d532e
7
+ data.tar.gz: b4832c67b7f870e9fa5b7745c5e1ddfd0ded602b0ca2f2cb9a351d4542f88b6e95b230c91cd24332ac6c6e6109035e589062db9c8a03faedf991a44a6ab7ddea
data/CHANGELOG.md CHANGED
@@ -1,6 +1,17 @@
1
1
  ## Unreleased
2
2
 
3
- - [#PR ID] Add your changelog entry here.
3
+ - Please add here
4
+
5
+ ## v1.9.0 (2026-03-16)
6
+
7
+ - [#229] Allow to application manage signing key and algorithm
8
+ - [#230] Add dynamic client registration
9
+ - [#233] fix: handle `DoubleRenderError` in library instead of requiring consumer workaround
10
+ - [#232] Implements customizable OpenID request class
11
+ - [#236] Derive `token_endpoint_auth_methods_supported` from Doorkeeper's client_credentials config
12
+ - [#225] Allow configuration of id_token expiration using a block.
13
+ - [#237] Fix dynamic client registration returning hashed secret when `hash_application_secrets` is enabled
14
+ - [#226] Respect Doorkeeper's configured `pkce_code_challenge_methods`
4
15
 
5
16
  ## v1.8.11 (2025-02-10)
6
17
 
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # Doorkeeper::OpenidConnect
2
2
 
3
- [![Build Status](https://github.com/doorkeeper-gem/doorkeeper-openid_connect/workflows/CI/badge.svg?branch=master)](https://github.com/doorkeeper-gem/doorkeeper-openid_connect/actions)
4
- [![Code Climate](https://codeclimate.com/github/doorkeeper-gem/doorkeeper-openid_connect.svg)](https://codeclimate.com/github/doorkeeper-gem/doorkeeper-openid_connect)
3
+ [![CI](https://github.com/doorkeeper-gem/doorkeeper-openid_connect/actions/workflows/ci.yml/badge.svg)](https://github.com/doorkeeper-gem/doorkeeper-openid_connect/actions/workflows/ci.yml)
4
+ [![Maintainability](https://qlty.sh/gh/doorkeeper-gem/projects/doorkeeper-openid_connect/maintainability.svg)](https://qlty.sh/gh/doorkeeper-gem/projects/doorkeeper-openid_connect)
5
5
  [![Gem Version](https://badge.fury.io/rb/doorkeeper-openid_connect.svg)](https://rubygems.org/gems/doorkeeper-openid_connect)
6
6
 
7
7
  #### :warning: **This project is looking for maintainers, see [this issue](https://github.com/doorkeeper-gem/doorkeeper-openid_connect/issues/89).**
@@ -150,7 +150,18 @@ The following settings are optional:
150
150
 
151
151
  - `expiration`
152
152
  - Expiration time after which the ID Token must not be accepted for processing by clients.
153
- - The default is 120 seconds
153
+ - The default is 120 seconds, it can be configured using a value or block.
154
+ ```ruby
155
+ # config/initializers/doorkeeper_openid_connect.rb
156
+ Doorkeeper::OpenidConnect.configure do
157
+ # ...
158
+ expiration do |resource_owner, application|
159
+ # You will have to ensure the application model implements an expiration method
160
+ application.expiration
161
+ end
162
+ # ...
163
+ end
164
+ ```
154
165
 
155
166
  - `protocol`
156
167
  - The protocol to use when generating URIs for the discovery endpoints.
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module OpenidConnect
5
+ module GrantTypesSupportedMixin
6
+ def grant_types_supported(doorkeeper)
7
+ grant_types_supported = doorkeeper.grant_flows.dup
8
+ grant_types_supported << 'refresh_token' if doorkeeper.refresh_token_enabled?
9
+ grant_types_supported
10
+ end
11
+ end
12
+ end
13
+ end
@@ -4,6 +4,7 @@ module Doorkeeper
4
4
  module OpenidConnect
5
5
  class DiscoveryController < ::Doorkeeper::ApplicationMetalController
6
6
  include Doorkeeper::Helpers::Controller
7
+ include GrantTypesSupportedMixin
7
8
 
8
9
  WEBFINGER_RELATION = 'http://openid.net/specs/connect/1.0/issuer'
9
10
 
@@ -34,6 +35,7 @@ module Doorkeeper
34
35
  userinfo_endpoint: oauth_userinfo_url(userinfo_url_options),
35
36
  jwks_uri: oauth_discovery_keys_url(jwks_url_options),
36
37
  end_session_endpoint: instance_exec(&openid_connect.end_session_endpoint),
38
+ registration_endpoint: openid_connect.dynamic_client_registration ? oauth_dynamic_client_registration_url(dynamic_client_registration_url_options) : nil,
37
39
 
38
40
  scopes_supported: doorkeeper.scopes,
39
41
 
@@ -45,7 +47,7 @@ module Doorkeeper
45
47
  # TODO: look into doorkeeper-jwt_assertion for these
46
48
  # 'client_secret_jwt',
47
49
  # 'private_key_jwt'
48
- token_endpoint_auth_methods_supported: %w[client_secret_basic client_secret_post],
50
+ token_endpoint_auth_methods_supported: token_endpoint_auth_methods_supported(doorkeeper),
49
51
 
50
52
  subject_types_supported: openid_connect.subject_types_supported,
51
53
 
@@ -73,20 +75,19 @@ module Doorkeeper
73
75
  }.compact
74
76
  end
75
77
 
76
- def grant_types_supported(doorkeeper)
77
- grant_types_supported = doorkeeper.grant_flows.dup
78
- grant_types_supported << 'refresh_token' if doorkeeper.refresh_token_enabled?
79
- grant_types_supported
80
- end
81
-
82
78
  def response_modes_supported(doorkeeper)
83
79
  doorkeeper.authorization_response_flows.flat_map(&:response_mode_matches).uniq
84
80
  end
85
81
 
82
+ def token_endpoint_auth_methods_supported(doorkeeper)
83
+ mapping = { from_basic: 'client_secret_basic', from_params: 'client_secret_post' }
84
+ doorkeeper.client_credentials_methods.filter_map { |method| mapping[method] }
85
+ end
86
+
86
87
  def code_challenge_methods_supported(doorkeeper)
87
88
  return unless doorkeeper.access_grant_model.pkce_supported?
88
89
 
89
- %w[plain S256]
90
+ doorkeeper.pkce_code_challenge_methods
90
91
  end
91
92
 
92
93
  def webfinger_response
@@ -136,7 +137,7 @@ module Doorkeeper
136
137
  end
137
138
  end
138
139
 
139
- %i[authorization token revocation introspection userinfo jwks webfinger].each do |endpoint|
140
+ %i[authorization token revocation introspection userinfo jwks webfinger dynamic_client_registration].each do |endpoint|
140
141
  define_method :"#{endpoint}_url_options" do
141
142
  discovery_url_default_options.merge(discovery_url_options[endpoint.to_sym] || {})
142
143
  end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module OpenidConnect
5
+ class DynamicClientRegistrationController < ::Doorkeeper::ApplicationMetalController
6
+ include GrantTypesSupportedMixin
7
+
8
+ def register
9
+ client = Doorkeeper::Application.create!(application_params)
10
+ render json: registration_response(client), status: :created
11
+ rescue ActiveRecord::RecordInvalid => e
12
+ render json: { error: "invalid_client_params", error_description: e.record.errors.full_messages.join(", ") },
13
+ status: :bad_request
14
+ end
15
+
16
+ private
17
+
18
+ def application_params
19
+ {
20
+ name: params.dig(:client_name),
21
+ redirect_uri: params.dig(:redirect_uris) || [],
22
+ scopes: params.dig(:scope),
23
+ confidential: false,
24
+ }
25
+ end
26
+
27
+ def registration_response(doorkeeper_application)
28
+ doorkeeper_config = ::Doorkeeper.configuration
29
+
30
+ {
31
+ client_secret: doorkeeper_application.plaintext_secret || doorkeeper_application.secret,
32
+ client_id: doorkeeper_application.uid,
33
+ client_id_issued_at: doorkeeper_application.created_at.to_i,
34
+ redirect_uris: doorkeeper_application.redirect_uri.split,
35
+ token_endpoint_auth_methods_supported: %w[client_secret_basic client_secret_post],
36
+ response_types: doorkeeper_config.authorization_response_types,
37
+ grant_types: grant_types_supported(doorkeeper_config),
38
+ scope: doorkeeper_application.scopes.to_s,
39
+ application_type: "web"
40
+ }
41
+ end
42
+ end
43
+ end
44
+ end
@@ -79,6 +79,18 @@ module Doorkeeper
79
79
  option :discovery_url_options, default: lambda { |*_|
80
80
  {}
81
81
  }
82
+
83
+ option :dynamic_client_registration, default: false
84
+
85
+ option :open_id_request_class, default: 'Doorkeeper::OpenidConnect::Request'
86
+
87
+ # Doorkeeper OpenID Request model class.
88
+ #
89
+ # @return [ActiveRecord::Base, Mongoid::Document, Sequel::Model]
90
+ #
91
+ def open_id_request_model
92
+ @open_id_request_model ||= open_id_request_class.to_s.constantize
93
+ end
82
94
  end
83
95
  end
84
96
  end
@@ -81,7 +81,10 @@ module Doorkeeper
81
81
  when 'login'
82
82
  reauthenticate_oidc_resource_owner(owner) if owner
83
83
  when 'consent'
84
- render :new if owner
84
+ if owner
85
+ clear_oidc_response
86
+ render :new
87
+ end
85
88
  when 'select_account'
86
89
  select_account_for_oidc_resource_owner(owner)
87
90
  when 'create'
@@ -118,7 +121,13 @@ module Doorkeeper
118
121
  return_to.to_s
119
122
  end
120
123
 
124
+ def clear_oidc_response
125
+ self.response_body = nil
126
+ @_response_body = nil
127
+ end
128
+
121
129
  def reauthenticate_oidc_resource_owner(owner)
130
+ clear_oidc_response
122
131
  return_to = return_without_oidc_prompt_param('login')
123
132
 
124
133
  instance_exec(
@@ -135,6 +144,7 @@ module Doorkeeper
135
144
  end
136
145
 
137
146
  def select_account_for_oidc_resource_owner(owner)
147
+ clear_oidc_response
138
148
  return_to = return_without_oidc_prompt_param('select_account')
139
149
 
140
150
  instance_exec(
@@ -57,8 +57,16 @@ module Doorkeeper
57
57
  @access_token.application.try(:uid)
58
58
  end
59
59
 
60
+ def expires_in
61
+ if @expires_in.respond_to?(:call)
62
+ @expires_in.call(@resource_owner, @access_token.application)
63
+ else
64
+ @expires_in
65
+ end
66
+ end
67
+
60
68
  def expiration
61
- (@issued_at.utc + @expires_in).to_i
69
+ (@issued_at.utc + expires_in).to_i
62
70
  end
63
71
 
64
72
  def issued_at
@@ -25,7 +25,7 @@ module Doorkeeper
25
25
  private
26
26
 
27
27
  def create_openid_request(access_grant)
28
- ::Doorkeeper::OpenidConnect::Request.create!(
28
+ ::Doorkeeper::OpenidConnect.configuration.open_id_request_model.create!(
29
29
  access_grant: access_grant,
30
30
  nonce: pre_auth.nonce
31
31
  )
@@ -6,7 +6,7 @@ module Doorkeeper
6
6
  def self.prepended(base)
7
7
  base.class_eval do
8
8
  has_one :openid_request,
9
- class_name: 'Doorkeeper::OpenidConnect::Request',
9
+ class_name: Doorkeeper::OpenidConnect.configuration.open_id_request_class,
10
10
  foreign_key: 'access_grant_id',
11
11
  inverse_of: :access_grant,
12
12
  dependent: :delete
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module OpenidConnect
5
+ module Orm
6
+ module ActiveRecord
7
+ module Mixins
8
+ module OpenidRequest
9
+ extend ::ActiveSupport::Concern
10
+
11
+ included do
12
+ self.table_name = "#{table_name_prefix}oauth_openid_requests#{table_name_suffix}".to_sym
13
+
14
+ validates :access_grant_id, :nonce, presence: true
15
+
16
+ if Gem.loaded_specs['doorkeeper'].version >= Gem::Version.create('5.5.0')
17
+ belongs_to :access_grant,
18
+ class_name: Doorkeeper.config.access_grant_class.to_s,
19
+ inverse_of: :openid_request
20
+ else
21
+ belongs_to :access_grant,
22
+ class_name: 'Doorkeeper::AccessGrant',
23
+ inverse_of: :openid_request
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -1,21 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'doorkeeper/openid_connect/orm/active_record/mixins/openid_request'
4
+
3
5
  module Doorkeeper
4
6
  module OpenidConnect
5
7
  class Request < ::ActiveRecord::Base
6
- self.table_name = "#{table_name_prefix}oauth_openid_requests#{table_name_suffix}".to_sym
7
-
8
- validates :access_grant_id, :nonce, presence: true
9
-
10
- if Gem.loaded_specs['doorkeeper'].version >= Gem::Version.create('5.5.0')
11
- belongs_to :access_grant,
12
- class_name: Doorkeeper.config.access_grant_class.to_s,
13
- inverse_of: :openid_request
14
- else
15
- belongs_to :access_grant,
16
- class_name: 'Doorkeeper::AccessGrant',
17
- inverse_of: :openid_request
18
- end
8
+ include Orm::ActiveRecord::Mixins::OpenidRequest
19
9
  end
20
10
  end
21
11
  end
@@ -9,6 +9,10 @@ module Doorkeeper
9
9
 
10
10
  module Orm
11
11
  module ActiveRecord
12
+ module Mixins
13
+ autoload :OpenidRequest, "doorkeeper/openid_connect/orm/active_record/mixins/openid_request"
14
+ end
15
+
12
16
  def run_hooks
13
17
  super
14
18
 
@@ -19,7 +23,7 @@ module Doorkeeper
19
23
  end
20
24
 
21
25
  if Doorkeeper.configuration.respond_to?(:active_record_options) && Doorkeeper.configuration.active_record_options[:establish_connection]
22
- [Doorkeeper::OpenidConnect::Request].each do |c|
26
+ [Doorkeeper::OpenidConnect.configuration.open_id_request_model].each do |c|
23
27
  c.send :establish_connection, Doorkeeper.configuration.active_record_options[:establish_connection]
24
28
  end
25
29
  end
@@ -38,7 +42,7 @@ module Doorkeeper
38
42
  end
39
43
 
40
44
  if Doorkeeper.configuration.active_record_options[:establish_connection]
41
- [Doorkeeper::OpenidConnect::Request].each do |c|
45
+ [Doorkeeper::OpenidConnect.configuration.open_id_request_model].each do |c|
42
46
  c.send :establish_connection, Doorkeeper.configuration.active_record_options[:establish_connection]
43
47
  end
44
48
  end
@@ -10,12 +10,14 @@ module Doorkeeper
10
10
  def initialize
11
11
  @controllers = {
12
12
  userinfo: 'doorkeeper/openid_connect/userinfo',
13
- discovery: 'doorkeeper/openid_connect/discovery'
13
+ discovery: 'doorkeeper/openid_connect/discovery',
14
+ dynamic_client_registration: 'doorkeeper/openid_connect/dynamic_client_registration'
14
15
  }
15
16
 
16
17
  @as = {
17
18
  userinfo: :userinfo,
18
- discovery: :discovery
19
+ discovery: :discovery,
20
+ dynamic_client_registration: :dynamic_client_registration
19
21
  }
20
22
 
21
23
  @skips = []
@@ -26,9 +26,15 @@ module Doorkeeper
26
26
 
27
27
  def generate_routes!(options)
28
28
  @mapping = Mapper.new.map(&@block)
29
+ openid_connect = ::Doorkeeper::OpenidConnect.configuration
30
+
29
31
  routes.scope options[:scope] || 'oauth', as: 'oauth' do
30
32
  map_route(:userinfo, :userinfo_routes)
31
33
  map_route(:discovery, :discovery_routes)
34
+
35
+ if openid_connect.dynamic_client_registration
36
+ map_route(:dynamic_client_registration, :dynamic_client_registration_routes)
37
+ end
32
38
  end
33
39
 
34
40
  routes.scope as: 'oauth' do
@@ -66,6 +72,10 @@ module Doorkeeper
66
72
  routes.get :webfinger
67
73
  end
68
74
  end
75
+
76
+ def dynamic_client_registration_routes
77
+ routes.post :register, path: 'registration', as: ''
78
+ end
69
79
  end
70
80
  end
71
81
  end
@@ -2,6 +2,12 @@
2
2
 
3
3
  module Doorkeeper
4
4
  module OpenidConnect
5
- VERSION = '1.8.11'
5
+ MAJOR = 1
6
+ MINOR = 9
7
+ TINY = 0
8
+ PRE = nil
9
+
10
+ # Full version number
11
+ VERSION = [MAJOR, MINOR, TINY, PRE].compact.join(".")
6
12
  end
7
13
  end
@@ -38,15 +38,26 @@ require 'doorkeeper/openid_connect/rails/routes'
38
38
  module Doorkeeper
39
39
  module OpenidConnect
40
40
  def self.signing_algorithm
41
- configuration.signing_algorithm.to_s.upcase.to_sym
41
+ algo = if configuration.signing_algorithm.respond_to?(:call)
42
+ configuration.signing_algorithm.call
43
+ else
44
+ configuration.signing_algorithm
45
+ end
46
+ algo.to_s.upcase.to_sym
42
47
  end
43
48
 
44
49
  def self.signing_key
50
+ key_value = if configuration.signing_key.respond_to?(:call)
51
+ configuration.signing_key.call
52
+ else
53
+ configuration.signing_key
54
+ end
55
+
45
56
  key =
46
57
  if %i[HS256 HS384 HS512].include?(signing_algorithm)
47
- configuration.signing_key
58
+ key_value
48
59
  else
49
- OpenSSL::PKey.read(configuration.signing_key)
60
+ OpenSSL::PKey.read(key_value)
50
61
  end
51
62
  ::JWT::JWK.new(key, { kid_generator: ::JWT::JWK::Thumbprint })
52
63
  end
@@ -30,12 +30,6 @@ Doorkeeper::OpenidConnect.configure do
30
30
  # redirect_to new_user_session_url
31
31
  end
32
32
 
33
- # Depending on your configuration, a DoubleRenderError could be raised
34
- # if render/redirect_to is called at some point before this callback is executed.
35
- # To avoid the DoubleRenderError, you could add these two lines at the beginning
36
- # of this callback: (Reference: https://github.com/rails/rails/issues/25106)
37
- # self.response_body = nil
38
- # @_response_body = nil
39
33
  select_account_for_resource_owner do |resource_owner, return_to|
40
34
  # Example implementation:
41
35
  # store_location_for resource_owner, return_to
@@ -59,6 +53,28 @@ Doorkeeper::OpenidConnect.configure do
59
53
  # Expiration time on or after which the ID Token MUST NOT be accepted for processing. (default 120 seconds).
60
54
  # expiration 600
61
55
 
56
+ # Enable dynamic client registration (default false)
57
+ # dynamic_client_registration true
58
+
59
+ # You can use your own model class if you need to extend (or even override) the default
60
+ # Doorkeeper::OpenidConnect::Request model (e.g. to use a different database connection).
61
+ #
62
+ # By default Doorkeeper OpenID Connect uses:
63
+ #
64
+ # open_id_request_class "Doorkeeper::OpenidConnect::Request"
65
+ #
66
+ # Don't forget to include the OpenID Connect ORM mixin into your custom model:
67
+ #
68
+ # * ::Doorkeeper::OpenidConnect::Orm::ActiveRecord::Mixins::OpenidRequest
69
+ #
70
+ # For example:
71
+ #
72
+ # open_id_request_class "MyOpenidRequest"
73
+ #
74
+ # class MyOpenidRequest < ApplicationRecord
75
+ # include ::Doorkeeper::OpenidConnect::Orm::ActiveRecord::Mixins::OpenidRequest
76
+ # end
77
+
62
78
  # Example claims:
63
79
  # claims do
64
80
  # normal_claim :_foo_ do |resource_owner|
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: doorkeeper-openid_connect
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.8.11
4
+ version: 1.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Dengler
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2025-02-10 00:00:00.000000000 Z
13
+ date: 2026-03-16 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: doorkeeper
@@ -21,7 +21,7 @@ dependencies:
21
21
  version: '5.5'
22
22
  - - "<"
23
23
  - !ruby/object:Gem::Version
24
- version: '5.9'
24
+ version: '6.0'
25
25
  type: :runtime
26
26
  prerelease: false
27
27
  version_requirements: !ruby/object:Gem::Requirement
@@ -31,7 +31,7 @@ dependencies:
31
31
  version: '5.5'
32
32
  - - "<"
33
33
  - !ruby/object:Gem::Version
34
- version: '5.9'
34
+ version: '6.0'
35
35
  - !ruby/object:Gem::Dependency
36
36
  name: ostruct
37
37
  requirement: !ruby/object:Gem::Requirement
@@ -185,7 +185,9 @@ files:
185
185
  - LICENSE.txt
186
186
  - README.md
187
187
  - app/controllers/concerns/doorkeeper/openid_connect/authorizations_extension.rb
188
+ - app/controllers/concerns/doorkeeper/openid_connect/grant_types_supported_mixin.rb
188
189
  - app/controllers/doorkeeper/openid_connect/discovery_controller.rb
190
+ - app/controllers/doorkeeper/openid_connect/dynamic_client_registration_controller.rb
189
191
  - app/controllers/doorkeeper/openid_connect/userinfo_controller.rb
190
192
  - config/locales/en.yml
191
193
  - lib/doorkeeper/oauth/id_token_request.rb
@@ -211,6 +213,7 @@ files:
211
213
  - lib/doorkeeper/openid_connect/oauth/token_response.rb
212
214
  - lib/doorkeeper/openid_connect/orm/active_record.rb
213
215
  - lib/doorkeeper/openid_connect/orm/active_record/access_grant.rb
216
+ - lib/doorkeeper/openid_connect/orm/active_record/mixins/openid_request.rb
214
217
  - lib/doorkeeper/openid_connect/orm/active_record/request.rb
215
218
  - lib/doorkeeper/openid_connect/rails/routes.rb
216
219
  - lib/doorkeeper/openid_connect/rails/routes/mapper.rb