doorkeeper 5.4.0 → 5.5.0.rc2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of doorkeeper might be problematic. Click here for more details.

Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +49 -9
  3. data/app/controllers/doorkeeper/authorizations_controller.rb +16 -5
  4. data/app/controllers/doorkeeper/tokens_controller.rb +34 -26
  5. data/app/views/doorkeeper/applications/show.html.erb +16 -12
  6. data/app/views/doorkeeper/authorizations/form_post.html.erb +11 -0
  7. data/config/locales/en.yml +3 -1
  8. data/lib/doorkeeper/config/option.rb +1 -3
  9. data/lib/doorkeeper/config/validations.rb +53 -0
  10. data/lib/doorkeeper/config.rb +87 -62
  11. data/lib/doorkeeper/grant_flow/fallback_flow.rb +15 -0
  12. data/lib/doorkeeper/grant_flow/flow.rb +44 -0
  13. data/lib/doorkeeper/grant_flow/registry.rb +50 -0
  14. data/lib/doorkeeper/grant_flow.rb +45 -0
  15. data/lib/doorkeeper/helpers/controller.rb +4 -0
  16. data/lib/doorkeeper/models/access_grant_mixin.rb +1 -2
  17. data/lib/doorkeeper/models/access_token_mixin.rb +3 -3
  18. data/lib/doorkeeper/models/concerns/revocable.rb +1 -1
  19. data/lib/doorkeeper/oauth/authorization/code.rb +4 -0
  20. data/lib/doorkeeper/oauth/authorization/context.rb +5 -5
  21. data/lib/doorkeeper/oauth/authorization/token.rb +10 -4
  22. data/lib/doorkeeper/oauth/authorization/uri_builder.rb +1 -1
  23. data/lib/doorkeeper/oauth/authorization_code_request.rb +10 -17
  24. data/lib/doorkeeper/oauth/base_request.rb +1 -1
  25. data/lib/doorkeeper/oauth/client_credentials/creator.rb +2 -1
  26. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +1 -0
  27. data/lib/doorkeeper/oauth/code_response.rb +17 -11
  28. data/lib/doorkeeper/oauth/error_response.rb +4 -3
  29. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +1 -3
  30. data/lib/doorkeeper/oauth/password_access_token_request.rb +20 -1
  31. data/lib/doorkeeper/oauth/pre_authorization.rb +33 -8
  32. data/lib/doorkeeper/oauth/refresh_token_request.rb +13 -0
  33. data/lib/doorkeeper/orm/active_record/mixins/application.rb +6 -3
  34. data/lib/doorkeeper/orm/active_record/redirect_uri_validator.rb +5 -0
  35. data/lib/doorkeeper/orm/active_record.rb +4 -5
  36. data/lib/doorkeeper/rails/routes.rb +1 -3
  37. data/lib/doorkeeper/request.rb +49 -12
  38. data/lib/doorkeeper/version.rb +2 -6
  39. data/lib/doorkeeper.rb +5 -0
  40. data/lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb.erb +1 -1
  41. data/lib/generators/doorkeeper/templates/initializer.rb +9 -7
  42. metadata +21 -8
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module GrantFlow
5
+ module Registry
6
+ mattr_accessor :flows
7
+ self.flows = {}
8
+
9
+ mattr_accessor :aliases
10
+ self.aliases = {}
11
+
12
+ # Allows to register custom OAuth grant flow so that Doorkeeper
13
+ # could recognize and process it.
14
+ #
15
+ def register(name_or_flow, **options)
16
+ unless name_or_flow.is_a?(Doorkeeper::GrantFlow::Flow)
17
+ name_or_flow = Flow.new(name_or_flow, **options)
18
+ end
19
+
20
+ flow_key = name_or_flow.name.to_sym
21
+
22
+ if flows.key?(flow_key)
23
+ ::Kernel.warn <<~WARNING
24
+ [DOORKEEPER] '#{flow_key}' grant flow already registered and will be overridden
25
+ in #{caller(1..1).first}
26
+ WARNING
27
+ end
28
+
29
+ flows[flow_key] = name_or_flow
30
+ end
31
+
32
+ # Allows to register aliases that could be used in `grant_flows`
33
+ # configuration option. It is possible to have aliases like 1:1 or
34
+ # 1:N, i.e. "implicit_oidc" => ['token', 'id_token', 'id_token token'].
35
+ #
36
+ def register_alias(alias_name, **options)
37
+ aliases[alias_name.to_sym] = Array.wrap(options.fetch(:as))
38
+ end
39
+
40
+ def expand_alias(alias_name)
41
+ aliases.fetch(alias_name.to_sym, [])
42
+ end
43
+
44
+ # [NOTE]: make it to use #fetch after removing fallbacks
45
+ def get(name)
46
+ flows[name.to_sym]
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "doorkeeper/grant_flow/flow"
4
+ require "doorkeeper/grant_flow/fallback_flow"
5
+ require "doorkeeper/grant_flow/registry"
6
+
7
+ module Doorkeeper
8
+ module GrantFlow
9
+ extend Registry
10
+
11
+ register(
12
+ :implicit,
13
+ response_type_matches: "token",
14
+ response_mode_matches: %w[fragment form_post],
15
+ response_type_strategy: Doorkeeper::Request::Token,
16
+ )
17
+
18
+ register(
19
+ :authorization_code,
20
+ response_type_matches: "code",
21
+ response_mode_matches: %w[query fragment form_post],
22
+ response_type_strategy: Doorkeeper::Request::Code,
23
+ grant_type_matches: "authorization_code",
24
+ grant_type_strategy: Doorkeeper::Request::AuthorizationCode,
25
+ )
26
+
27
+ register(
28
+ :client_credentials,
29
+ grant_type_matches: "client_credentials",
30
+ grant_type_strategy: Doorkeeper::Request::ClientCredentials,
31
+ )
32
+
33
+ register(
34
+ :password,
35
+ grant_type_matches: "password",
36
+ grant_type_strategy: Doorkeeper::Request::Password,
37
+ )
38
+
39
+ register(
40
+ :refresh_token,
41
+ grant_type_matches: "refresh_token",
42
+ grant_type_strategy: Doorkeeper::Request::RefreshToken,
43
+ )
44
+ end
45
+ end
@@ -16,6 +16,8 @@ module Doorkeeper
16
16
 
17
17
  # :doc:
18
18
  def current_resource_owner
19
+ return @current_resource_owner if defined?(@current_resource_owner)
20
+
19
21
  @current_resource_owner ||= begin
20
22
  instance_eval(&Doorkeeper.config.authenticate_resource_owner)
21
23
  end
@@ -36,6 +38,8 @@ module Doorkeeper
36
38
 
37
39
  # :doc:
38
40
  def doorkeeper_token
41
+ return @doorkeeper_token if defined?(@doorkeeper_token)
42
+
39
43
  @doorkeeper_token ||= OAuth::Token.authenticate(request, *config_methods)
40
44
  end
41
45
 
@@ -89,8 +89,7 @@ module Doorkeeper
89
89
  # suitable for PKCE validation
90
90
  #
91
91
  def generate_code_challenge(code_verifier)
92
- padded_result = Base64.urlsafe_encode64(Digest::SHA256.digest(code_verifier))
93
- padded_result.split("=")[0] # Remove any trailing '='
92
+ Base64.urlsafe_encode64(Digest::SHA256.digest(code_verifier), padding: false)
94
93
  end
95
94
 
96
95
  def pkce_supported?
@@ -94,8 +94,8 @@ module Doorkeeper
94
94
  # Interface to enumerate access token records in batches in order not
95
95
  # to bloat the memory. Could be overloaded in any ORM extension.
96
96
  #
97
- def find_access_token_in_batches(relation, *args, &block)
98
- relation.find_in_batches(*args, &block)
97
+ def find_access_token_in_batches(relation, **args, &block)
98
+ relation.find_in_batches(**args, &block)
99
99
  end
100
100
 
101
101
  # Enumerates AccessToken records in batches to find a matching token.
@@ -377,7 +377,7 @@ module Doorkeeper
377
377
  return unless self.class.refresh_token_revoked_on_use?
378
378
 
379
379
  old_refresh_token&.revoke
380
- update_column(:previous_refresh_token, "")
380
+ update_attribute(:previous_refresh_token, "") if previous_refresh_token.present?
381
381
  end
382
382
 
383
383
  private
@@ -9,7 +9,7 @@ module Doorkeeper
9
9
  # @param clock [Time] time object
10
10
  #
11
11
  def revoke(clock = Time)
12
- update_column(:revoked_at, clock.now.utc)
12
+ update_attribute(:revoked_at, clock.now.utc)
13
13
  end
14
14
 
15
15
  # Indicates whether the object has been revoked.
@@ -21,6 +21,10 @@ module Doorkeeper
21
21
  { action: :show, code: token.plaintext_token }
22
22
  end
23
23
 
24
+ def access_grant?
25
+ true
26
+ end
27
+
24
28
  private
25
29
 
26
30
  def authorization_code_expires_in
@@ -4,12 +4,12 @@ module Doorkeeper
4
4
  module OAuth
5
5
  module Authorization
6
6
  class Context
7
- attr_reader :client, :grant_type, :scopes
7
+ attr_reader :client, :grant_type, :resource_owner, :scopes
8
8
 
9
- def initialize(client, grant_type, scopes)
10
- @client = client
11
- @grant_type = grant_type
12
- @scopes = scopes
9
+ def initialize(**attributes)
10
+ attributes.each do |name, value|
11
+ instance_variable_set(:"@#{name}", value) if respond_to?(name)
12
+ end
13
13
  end
14
14
  end
15
15
  end
@@ -7,7 +7,7 @@ module Doorkeeper
7
7
  attr_reader :pre_auth, :resource_owner, :token
8
8
 
9
9
  class << self
10
- def build_context(pre_auth_or_oauth_client, grant_type, scopes)
10
+ def build_context(pre_auth_or_oauth_client, grant_type, scopes, resource_owner)
11
11
  oauth_client = if pre_auth_or_oauth_client.respond_to?(:application)
12
12
  pre_auth_or_oauth_client.application
13
13
  elsif pre_auth_or_oauth_client.respond_to?(:client)
@@ -17,9 +17,10 @@ module Doorkeeper
17
17
  end
18
18
 
19
19
  Doorkeeper::OAuth::Authorization::Context.new(
20
- oauth_client,
21
- grant_type,
22
- scopes,
20
+ client: oauth_client,
21
+ grant_type: grant_type,
22
+ scopes: scopes,
23
+ resource_owner: resource_owner,
23
24
  )
24
25
  end
25
26
 
@@ -55,6 +56,7 @@ module Doorkeeper
55
56
  pre_auth.client,
56
57
  Doorkeeper::OAuth::IMPLICIT,
57
58
  pre_auth.scopes,
59
+ resource_owner,
58
60
  )
59
61
 
60
62
  @token = Doorkeeper.config.access_token_model.find_or_create_for(
@@ -74,6 +76,10 @@ module Doorkeeper
74
76
  }
75
77
  end
76
78
 
79
+ def access_token?
80
+ true
81
+ end
82
+
77
83
  private
78
84
 
79
85
  def controller
@@ -23,7 +23,7 @@ module Doorkeeper
23
23
  private
24
24
 
25
25
  def build_query(parameters = {})
26
- parameters = parameters.reject { |_, value| value.blank? }
26
+ parameters.reject! { |_, value| value.blank? }
27
27
  Rack::Utils.build_query(parameters)
28
28
  end
29
29
  end
@@ -3,7 +3,6 @@
3
3
  module Doorkeeper
4
4
  module OAuth
5
5
  class AuthorizationCodeRequest < BaseRequest
6
- validate :pkce_support, error: :invalid_request
7
6
  validate :params, error: :invalid_request
8
7
  validate :client, error: :invalid_client
9
8
  validate :grant, error: :invalid_grant
@@ -32,12 +31,6 @@ module Doorkeeper
32
31
 
33
32
  grant.revoke
34
33
 
35
- resource_owner = if Doorkeeper.config.polymorphic_resource_owner?
36
- grant.resource_owner
37
- else
38
- grant.resource_owner_id
39
- end
40
-
41
34
  find_or_create_access_token(
42
35
  grant.application,
43
36
  resource_owner,
@@ -49,16 +42,16 @@ module Doorkeeper
49
42
  super
50
43
  end
51
44
 
52
- def pkce_supported?
53
- Doorkeeper.config.access_grant_model.pkce_supported?
45
+ def resource_owner
46
+ if Doorkeeper.config.polymorphic_resource_owner?
47
+ grant.resource_owner
48
+ else
49
+ grant.resource_owner_id
50
+ end
54
51
  end
55
52
 
56
- def validate_pkce_support
57
- @invalid_request_reason = :not_support_pkce if grant &&
58
- !pkce_supported? &&
59
- code_verifier.present?
60
-
61
- @invalid_request_reason.nil?
53
+ def pkce_supported?
54
+ Doorkeeper.config.access_grant_model.pkce_supported?
62
55
  end
63
56
 
64
57
  def validate_params
@@ -91,8 +84,8 @@ module Doorkeeper
91
84
  # if either side (server or client) request PKCE, check the verifier
92
85
  # against the DB - if PKCE is supported
93
86
  def validate_code_verifier
94
- return true unless grant.uses_pkce? || code_verifier
95
- return false unless pkce_supported?
87
+ return true unless pkce_supported?
88
+ return grant.code_challenge.blank? if code_verifier.blank?
96
89
 
97
90
  if grant.code_challenge_method == "S256"
98
91
  grant.code_challenge == generate_code_challenge(code_verifier)
@@ -27,7 +27,7 @@ module Doorkeeper
27
27
  end
28
28
 
29
29
  def find_or_create_access_token(client, resource_owner, scopes, server)
30
- context = Authorization::Token.build_context(client, grant_type, scopes)
30
+ context = Authorization::Token.build_context(client, grant_type, scopes, resource_owner)
31
31
  @access_token = server_config.access_token_model.find_or_create_for(
32
32
  application: client,
33
33
  resource_owner: resource_owner,
@@ -39,7 +39,8 @@ module Doorkeeper
39
39
  end
40
40
 
41
41
  def lookup_existing_token?
42
- server_config.reuse_access_token || server_config.revoke_previous_client_credentials_token?
42
+ server_config.reuse_access_token ||
43
+ server_config.revoke_previous_client_credentials_token?
43
44
  end
44
45
 
45
46
  def find_existing_token_for(client, scopes)
@@ -30,6 +30,7 @@ module Doorkeeper
30
30
  client,
31
31
  Doorkeeper::OAuth::CLIENT_CREDENTIALS,
32
32
  scopes,
33
+ nil,
33
34
  )
34
35
  ttl = Authorization::Token.access_token_expires_in(@server, context)
35
36
 
@@ -21,23 +21,29 @@ module Doorkeeper
21
21
  auth.token
22
22
  end
23
23
 
24
- def redirect_uri
25
- if URIChecker.oob_uri?(pre_auth.redirect_uri)
26
- auth.oob_redirect
27
- elsif response_on_fragment
28
- Authorization::URIBuilder.uri_with_fragment(
29
- pre_auth.redirect_uri,
24
+ def body
25
+ if auth.try(:access_token?)
26
+ {
30
27
  access_token: auth.token.plaintext_token,
31
28
  token_type: auth.token.token_type,
32
29
  expires_in: auth.token.expires_in_seconds,
33
30
  state: pre_auth.state,
34
- )
35
- else
36
- Authorization::URIBuilder.uri_with_query(
37
- pre_auth.redirect_uri,
31
+ }
32
+ elsif auth.try(:access_grant?)
33
+ {
38
34
  code: auth.token.plaintext_token,
39
35
  state: pre_auth.state,
40
- )
36
+ }
37
+ end
38
+ end
39
+
40
+ def redirect_uri
41
+ if URIChecker.oob_uri?(pre_auth.redirect_uri)
42
+ auth.oob_redirect
43
+ elsif response_on_fragment
44
+ Authorization::URIBuilder.uri_with_fragment(pre_auth.redirect_uri, body)
45
+ else
46
+ Authorization::URIBuilder.uri_with_query(pre_auth.redirect_uri, body)
41
47
  end
42
48
  end
43
49
  end
@@ -5,6 +5,8 @@ module Doorkeeper
5
5
  class ErrorResponse < BaseResponse
6
6
  include OAuth::Helpers
7
7
 
8
+ NON_REDIRECTABLE_STATES = %i[invalid_redirect_uri invalid_client unauthorized_client].freeze
9
+
8
10
  def self.from_request(request, attributes = {})
9
11
  new(
10
12
  attributes.merge(
@@ -32,7 +34,7 @@ module Doorkeeper
32
34
  end
33
35
 
34
36
  def status
35
- if name == :invalid_client
37
+ if name == :invalid_client || name == :unauthorized_client
36
38
  :unauthorized
37
39
  else
38
40
  :bad_request
@@ -40,8 +42,7 @@ module Doorkeeper
40
42
  end
41
43
 
42
44
  def redirectable?
43
- name != :invalid_redirect_uri && name != :invalid_client &&
44
- !URIChecker.oob_uri?(@redirect_uri)
45
+ !NON_REDIRECTABLE_STATES.include?(name) && !URIChecker.oob_uri?(@redirect_uri)
45
46
  end
46
47
 
47
48
  def redirect_uri
@@ -12,9 +12,7 @@ module Doorkeeper
12
12
  @scope_str = scope_str
13
13
  @valid_scopes = valid_scopes(server_scopes, app_scopes)
14
14
 
15
- if grant_type
16
- @scopes_by_grant_type = Doorkeeper.config.scopes_by_grant_type[grant_type.to_sym]
17
- end
15
+ @scopes_by_grant_type = Doorkeeper.config.scopes_by_grant_type[grant_type.to_sym] if grant_type
18
16
  end
19
17
 
20
18
  def valid?
@@ -43,8 +43,27 @@ module Doorkeeper
43
43
  resource_owner.present?
44
44
  end
45
45
 
46
+ # Section 4.3.2. Access Token Request for Resource Owner Password Credentials Grant:
47
+ #
48
+ # If the client type is confidential or the client was issued client credentials (or assigned
49
+ # other authentication requirements), the client MUST authenticate with the authorization
50
+ # server as described in Section 3.2.1.
51
+ #
52
+ # The authorization server MUST:
53
+ #
54
+ # o require client authentication for confidential clients or for any client that was
55
+ # issued client credentials (or with other authentication requirements)
56
+ #
57
+ # o authenticate the client if client authentication is included,
58
+ #
59
+ # @see https://tools.ietf.org/html/rfc6749#section-4.3
60
+ #
46
61
  def validate_client
47
- !parameters[:client_id] || client.present?
62
+ if Doorkeeper.config.skip_client_authentication_for_password_grant
63
+ !parameters[:client_id] || client.present?
64
+ else
65
+ client.present?
66
+ end
48
67
  end
49
68
 
50
69
  def validate_client_supports_grant_flow
@@ -12,16 +12,19 @@ module Doorkeeper
12
12
  validate :redirect_uri, error: :invalid_redirect_uri
13
13
  validate :params, error: :invalid_request
14
14
  validate :response_type, error: :unsupported_response_type
15
+ validate :response_mode, error: :unsupported_response_mode
15
16
  validate :scopes, error: :invalid_scope
16
17
  validate :code_challenge_method, error: :invalid_code_challenge_method
17
18
 
18
19
  attr_reader :client, :code_challenge, :code_challenge_method, :missing_param,
19
- :redirect_uri, :resource_owner, :response_type, :state
20
+ :redirect_uri, :resource_owner, :response_type, :state,
21
+ :authorization_response_flow, :response_mode
20
22
 
21
23
  def initialize(server, parameters = {}, resource_owner = nil)
22
24
  @server = server
23
25
  @client_id = parameters[:client_id]
24
26
  @response_type = parameters[:response_type]
27
+ @response_mode = parameters[:response_mode]
25
28
  @redirect_uri = parameters[:redirect_uri]
26
29
  @scope = parameters[:scope]
27
30
  @state = parameters[:state]
@@ -57,6 +60,10 @@ module Doorkeeper
57
60
  pre_auth_hash
58
61
  end
59
62
 
63
+ def form_post_response?
64
+ response_mode == "form_post"
65
+ end
66
+
60
67
  private
61
68
 
62
69
  attr_reader :client_id, :server
@@ -84,6 +91,11 @@ module Doorkeeper
84
91
  Doorkeeper.config.allow_grant_flow_for_client?(grant_type, client.application)
85
92
  end
86
93
 
94
+ def validate_resource_owner_authorize_for_client
95
+ # The `authorize_resource_owner_for_client` config option is used for this validation
96
+ client.application.authorized_for_resource_owner?(@resource_owner)
97
+ end
98
+
87
99
  def validate_redirect_uri
88
100
  return false if redirect_uri.blank?
89
101
 
@@ -104,7 +116,21 @@ module Doorkeeper
104
116
  end
105
117
 
106
118
  def validate_response_type
107
- server.authorization_response_types.include?(response_type)
119
+ server.authorization_response_flows.any? do |flow|
120
+ if flow.matches_response_type?(response_type)
121
+ @authorization_response_flow = flow
122
+ true
123
+ end
124
+ end
125
+ end
126
+
127
+ def validate_response_mode
128
+ if response_mode.blank?
129
+ @response_mode = authorization_response_flow.default_response_mode
130
+ return true
131
+ end
132
+
133
+ authorization_response_flow.matches_response_mode?(response_mode)
108
134
  end
109
135
 
110
136
  def validate_scopes
@@ -117,17 +143,16 @@ module Doorkeeper
117
143
  end
118
144
 
119
145
  def validate_code_challenge_method
146
+ return true unless Doorkeeper.config.access_grant_model.pkce_supported?
147
+
120
148
  code_challenge.blank? ||
121
149
  (code_challenge_method.present? && code_challenge_method =~ /^plain$|^S256$/)
122
150
  end
123
151
 
124
- def validate_resource_owner_authorize_for_client
125
- # The `authorize_resource_owner_for_client` config option is used for this validation
126
- client.application.authorized_for_resource_owner?(@resource_owner)
127
- end
128
-
129
152
  def response_on_fragment?
130
- response_type == "token"
153
+ return response_type == "token" if response_mode.nil?
154
+
155
+ response_mode == "fragment"
131
156
  end
132
157
 
133
158
  def grant_type
@@ -62,6 +62,19 @@ module Doorkeeper
62
62
  attributes[:previous_refresh_token] = refresh_token.refresh_token
63
63
  end
64
64
 
65
+ # RFC6749
66
+ # 1.5. Refresh Token
67
+ #
68
+ # Refresh tokens are issued to the client by the authorization server and are
69
+ # used to obtain a new access token when the current access token
70
+ # becomes invalid or expires, or to obtain additional access tokens
71
+ # with identical or narrower scope (access tokens may have a shorter
72
+ # lifetime and fewer permissions than authorized by the resource
73
+ # owner).
74
+ #
75
+ # Here we assume that TTL of the token received after refreshing should be
76
+ # the same as that of the original token.
77
+ #
65
78
  @access_token = server_config.access_token_model.create_for(
66
79
  application: refresh_token.application,
67
80
  resource_owner: resource_owner,
@@ -137,9 +137,9 @@ module Doorkeeper::Orm::ActiveRecord::Mixins
137
137
  only = Array.wrap(opts[:only]).map(&:to_s)
138
138
 
139
139
  only = if only.blank?
140
- serializable_attributes
140
+ client_serializable_attributes
141
141
  else
142
- only & serializable_attributes
142
+ only & client_serializable_attributes
143
143
  end
144
144
 
145
145
  only -= Array.wrap(opts[:except]).map(&:to_s) if opts.key?(:except)
@@ -150,7 +150,10 @@ module Doorkeeper::Orm::ActiveRecord::Mixins
150
150
  # Override this method if you need additional attributes to be serialized.
151
151
  #
152
152
  # @return [Array<String>] collection of serializable attributes
153
- def serializable_attributes
153
+ #
154
+ # NOTE: `serializable_attributes` method already taken by Rails >= 6
155
+ #
156
+ def client_serializable_attributes
154
157
  attributes = %w[id name created_at]
155
158
  attributes << "uid" unless confidential?
156
159
  attributes
@@ -21,6 +21,7 @@ module Doorkeeper
21
21
  record.errors.add(attribute, :unspecified_scheme) if unspecified_scheme?(uri)
22
22
  record.errors.add(attribute, :relative_uri) if relative_uri?(uri)
23
23
  record.errors.add(attribute, :secured_uri) if invalid_ssl_uri?(uri)
24
+ record.errors.add(attribute, :invalid_uri) if unspecified_host?(uri)
24
25
  end
25
26
  end
26
27
  rescue URI::InvalidURIError
@@ -43,6 +44,10 @@ module Doorkeeper
43
44
  %w[localhost].include?(uri.try(:scheme))
44
45
  end
45
46
 
47
+ def unspecified_host?(uri)
48
+ uri.is_a?(URI::HTTP) && uri.host.nil?
49
+ end
50
+
46
51
  def relative_uri?(uri)
47
52
  uri.scheme.nil? && uri.host.nil?
48
53
  end
@@ -20,9 +20,8 @@ module Doorkeeper
20
20
  require "doorkeeper/orm/active_record/access_token"
21
21
  require "doorkeeper/orm/active_record/application"
22
22
 
23
- if Doorkeeper.config.active_record_options[:establish_connection]
23
+ if (options = Doorkeeper.config.active_record_options[:establish_connection])
24
24
  Doorkeeper::Orm::ActiveRecord.models.each do |model|
25
- options = Doorkeeper.config.active_record_options[:establish_connection]
26
25
  model.establish_connection(options)
27
26
  end
28
27
  end
@@ -51,9 +50,9 @@ module Doorkeeper
51
50
 
52
51
  def self.models
53
52
  [
54
- Doorkeeper::AccessGrant,
55
- Doorkeeper::AccessToken,
56
- Doorkeeper::Application,
53
+ Doorkeeper.config.access_grant_model,
54
+ Doorkeeper.config.access_token_model,
55
+ Doorkeeper.config.application_model,
57
56
  ]
58
57
  end
59
58
  end
@@ -29,8 +29,6 @@ module Doorkeeper
29
29
 
30
30
  def initialize(routes, mapper = Mapper.new, &block)
31
31
  super
32
-
33
- @mapping.skips.push(:applications, :authorized_applications) if Doorkeeper.config.api_only
34
32
  end
35
33
 
36
34
  def generate_routes!(options)
@@ -38,7 +36,7 @@ module Doorkeeper
38
36
  map_route(:authorizations, :authorization_routes)
39
37
  map_route(:tokens, :token_routes)
40
38
  map_route(:tokens, :revoke_routes)
41
- map_route(:tokens, :introspect_routes)
39
+ map_route(:tokens, :introspect_routes) unless Doorkeeper.config.allow_token_introspection.is_a?(FalseClass)
42
40
  map_route(:applications, :application_routes)
43
41
  map_route(:authorized_applications, :authorized_applications_routes)
44
42
  map_route(:token_info, :token_info_routes)