doorkeeper 3.1.0 → 4.4.3
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.
- checksums.yaml +4 -4
- data/.coveralls.yml +1 -0
- data/.github/ISSUE_TEMPLATE.md +25 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +17 -0
- data/.gitignore +6 -1
- data/.hound.yml +2 -13
- data/.rubocop.yml +17 -0
- data/.travis.yml +26 -10
- data/Appraisals +18 -0
- data/CODE_OF_CONDUCT.md +46 -0
- data/CONTRIBUTING.md +2 -0
- data/Gemfile +5 -5
- data/NEWS.md +141 -2
- data/README.md +149 -66
- data/RELEASING.md +5 -12
- data/Rakefile +1 -1
- data/SECURITY.md +15 -0
- data/app/controllers/doorkeeper/application_controller.rb +4 -6
- data/app/controllers/doorkeeper/application_metal_controller.rb +3 -2
- data/app/controllers/doorkeeper/applications_controller.rb +18 -8
- data/app/controllers/doorkeeper/authorizations_controller.rb +1 -1
- data/app/controllers/doorkeeper/authorized_applications_controller.rb +1 -1
- data/app/controllers/doorkeeper/tokens_controller.rb +62 -15
- data/app/helpers/doorkeeper/dashboard_helper.rb +14 -10
- data/app/validators/redirect_uri_validator.rb +12 -2
- data/app/views/doorkeeper/applications/_delete_form.html.erb +1 -2
- data/app/views/doorkeeper/applications/_form.html.erb +13 -2
- data/app/views/doorkeeper/applications/index.html.erb +2 -0
- data/app/views/doorkeeper/applications/show.html.erb +4 -1
- data/app/views/doorkeeper/authorizations/new.html.erb +1 -1
- data/app/views/doorkeeper/authorized_applications/_delete_form.html.erb +1 -2
- data/app/views/doorkeeper/authorized_applications/index.html.erb +0 -1
- data/app/views/layouts/doorkeeper/admin.html.erb +1 -1
- data/config/locales/en.yml +12 -7
- data/doorkeeper.gemspec +16 -11
- data/gemfiles/rails_4_2.gemfile +13 -0
- data/gemfiles/rails_5_0.gemfile +12 -0
- data/gemfiles/rails_5_1.gemfile +12 -0
- data/gemfiles/rails_5_2.gemfile +12 -0
- data/gemfiles/rails_master.gemfile +14 -0
- data/lib/doorkeeper/config.rb +119 -46
- data/lib/doorkeeper/engine.rb +11 -7
- data/lib/doorkeeper/errors.rb +18 -0
- data/lib/doorkeeper/grape/helpers.rb +14 -8
- data/lib/doorkeeper/helpers/controller.rb +8 -19
- data/lib/doorkeeper/models/access_grant_mixin.rb +10 -21
- data/lib/doorkeeper/models/access_token_mixin.rb +147 -43
- data/lib/doorkeeper/models/application_mixin.rb +33 -35
- data/lib/doorkeeper/models/concerns/accessible.rb +4 -0
- data/lib/doorkeeper/models/concerns/expirable.rb +15 -5
- data/lib/doorkeeper/models/concerns/orderable.rb +13 -0
- data/lib/doorkeeper/models/concerns/ownership.rb +6 -1
- data/lib/doorkeeper/models/concerns/revocable.rb +37 -2
- data/lib/doorkeeper/oauth/authorization/token.rb +22 -18
- data/lib/doorkeeper/oauth/authorization/uri_builder.rb +20 -18
- data/lib/doorkeeper/oauth/authorization_code_request.rb +7 -5
- data/lib/doorkeeper/oauth/{request_concern.rb → base_request.rb} +9 -2
- data/lib/doorkeeper/oauth/base_response.rb +29 -0
- data/lib/doorkeeper/oauth/client/credentials.rb +21 -8
- data/lib/doorkeeper/oauth/client.rb +2 -3
- data/lib/doorkeeper/oauth/client_credentials/creator.rb +1 -1
- data/lib/doorkeeper/oauth/client_credentials/issuer.rb +3 -2
- data/lib/doorkeeper/oauth/client_credentials/validation.rb +1 -1
- data/lib/doorkeeper/oauth/client_credentials_request.rb +8 -8
- data/lib/doorkeeper/oauth/code_response.rb +16 -16
- data/lib/doorkeeper/oauth/error.rb +2 -2
- data/lib/doorkeeper/oauth/error_response.rb +10 -10
- data/lib/doorkeeper/oauth/forbidden_token_response.rb +1 -1
- data/lib/doorkeeper/oauth/helpers/scope_checker.rb +1 -1
- data/lib/doorkeeper/oauth/helpers/uri_checker.rb +17 -1
- data/lib/doorkeeper/oauth/invalid_token_response.rb +5 -4
- data/lib/doorkeeper/oauth/password_access_token_request.rb +8 -13
- data/lib/doorkeeper/oauth/pre_authorization.rb +5 -3
- data/lib/doorkeeper/oauth/refresh_token_request.rb +23 -14
- data/lib/doorkeeper/oauth/scopes.rb +18 -8
- data/lib/doorkeeper/oauth/token.rb +20 -21
- data/lib/doorkeeper/oauth/token_introspection.rb +128 -0
- data/lib/doorkeeper/oauth/token_request.rb +1 -2
- data/lib/doorkeeper/oauth/token_response.rb +1 -1
- data/lib/doorkeeper/orm/active_record/access_grant.rb +27 -0
- data/lib/doorkeeper/orm/active_record/access_token.rb +34 -8
- data/lib/doorkeeper/orm/active_record/application.rb +48 -11
- data/lib/doorkeeper/orm/active_record.rb +17 -22
- data/lib/doorkeeper/rails/helpers.rb +6 -9
- data/lib/doorkeeper/rails/routes/mapper.rb +4 -4
- data/lib/doorkeeper/rails/routes/mapping.rb +1 -1
- data/lib/doorkeeper/rails/routes.rb +17 -11
- data/lib/doorkeeper/request/authorization_code.rb +7 -1
- data/lib/doorkeeper/request/password.rb +2 -2
- data/lib/doorkeeper/request/refresh_token.rb +1 -1
- data/lib/doorkeeper/request.rb +7 -1
- data/lib/doorkeeper/server.rb +0 -8
- data/lib/doorkeeper/validations.rb +3 -2
- data/lib/doorkeeper/version.rb +34 -1
- data/lib/doorkeeper.rb +10 -2
- data/lib/generators/doorkeeper/add_client_confidentiality_generator.rb +31 -0
- data/lib/generators/doorkeeper/application_owner_generator.rb +11 -2
- data/lib/generators/doorkeeper/migration_generator.rb +13 -1
- data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +35 -0
- data/lib/generators/doorkeeper/templates/add_confidential_to_application_migration.rb.erb +11 -0
- data/{spec/dummy/db/migrate/20130902175349_add_owner_to_application.rb → lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb.erb} +1 -1
- data/lib/generators/doorkeeper/templates/add_previous_refresh_token_to_access_tokens.rb.erb +11 -0
- data/lib/generators/doorkeeper/templates/initializer.rb +38 -6
- data/lib/generators/doorkeeper/templates/migration.rb.erb +69 -0
- data/spec/controllers/application_metal_controller.rb +10 -0
- data/spec/controllers/applications_controller_spec.rb +15 -4
- data/spec/controllers/authorizations_controller_spec.rb +74 -27
- data/spec/controllers/protected_resources_controller_spec.rb +70 -32
- data/spec/controllers/token_info_controller_spec.rb +17 -13
- data/spec/controllers/tokens_controller_spec.rb +198 -12
- data/spec/dummy/app/controllers/full_protected_resources_controller.rb +4 -4
- data/spec/dummy/app/controllers/home_controller.rb +1 -1
- data/spec/dummy/app/controllers/metal_controller.rb +1 -1
- data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +3 -3
- data/spec/dummy/app/models/user.rb +0 -4
- data/spec/dummy/config/application.rb +2 -36
- data/spec/dummy/config/environment.rb +1 -1
- data/spec/dummy/config/environments/test.rb +4 -15
- data/spec/dummy/config/initializers/doorkeeper.rb +19 -3
- data/spec/dummy/config/initializers/new_framework_defaults.rb +6 -0
- data/spec/dummy/config/initializers/secret_token.rb +0 -1
- data/spec/dummy/db/migrate/20111122132257_create_users.rb +3 -1
- data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +3 -1
- data/{lib/generators/doorkeeper/templates/migration.rb → spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb} +16 -4
- data/{lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb → spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb} +4 -2
- data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +13 -0
- data/spec/dummy/db/migrate/20180210183654_add_confidential_to_application.rb +13 -0
- data/spec/dummy/db/schema.rb +24 -22
- data/spec/factories.rb +4 -2
- data/spec/generators/application_owner_generator_spec.rb +24 -5
- data/spec/generators/migration_generator_spec.rb +24 -3
- data/spec/generators/previous_refresh_token_generator_spec.rb +57 -0
- data/spec/grape/grape_integration_spec.rb +135 -0
- data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +1 -1
- data/spec/lib/config_spec.rb +159 -14
- data/spec/lib/doorkeeper_spec.rb +135 -13
- data/spec/lib/models/expirable_spec.rb +0 -1
- data/spec/lib/models/revocable_spec.rb +27 -4
- data/spec/lib/oauth/authorization/uri_builder_spec.rb +1 -2
- data/spec/lib/oauth/authorization_code_request_spec.rb +55 -12
- data/spec/lib/oauth/base_request_spec.rb +155 -0
- data/spec/lib/oauth/base_response_spec.rb +45 -0
- data/spec/lib/oauth/client/credentials_spec.rb +45 -2
- data/spec/lib/oauth/client_credentials/creator_spec.rb +1 -1
- data/spec/lib/oauth/client_credentials_integration_spec.rb +1 -1
- data/spec/lib/oauth/client_credentials_request_spec.rb +1 -0
- data/spec/lib/oauth/code_request_spec.rb +1 -3
- data/spec/lib/oauth/code_response_spec.rb +34 -0
- data/spec/lib/oauth/error_response_spec.rb +9 -9
- data/spec/lib/oauth/error_spec.rb +1 -1
- data/spec/lib/oauth/helpers/uri_checker_spec.rb +115 -1
- data/spec/lib/oauth/invalid_token_response_spec.rb +36 -8
- data/spec/lib/oauth/password_access_token_request_spec.rb +14 -8
- data/spec/lib/oauth/pre_authorization_spec.rb +12 -7
- data/spec/lib/oauth/refresh_token_request_spec.rb +52 -9
- data/spec/lib/oauth/scopes_spec.rb +28 -2
- data/spec/lib/oauth/token_request_spec.rb +6 -8
- data/spec/lib/oauth/token_spec.rb +12 -5
- data/spec/lib/server_spec.rb +10 -3
- data/spec/models/doorkeeper/access_grant_spec.rb +1 -1
- data/spec/models/doorkeeper/access_token_spec.rb +116 -48
- data/spec/models/doorkeeper/application_spec.rb +145 -29
- data/spec/requests/applications/applications_request_spec.rb +5 -5
- data/spec/requests/endpoints/authorization_spec.rb +5 -6
- data/spec/requests/endpoints/token_spec.rb +8 -1
- data/spec/requests/flows/authorization_code_errors_spec.rb +11 -1
- data/spec/requests/flows/authorization_code_spec.rb +6 -13
- data/spec/requests/flows/client_credentials_spec.rb +29 -1
- data/spec/requests/flows/implicit_grant_errors_spec.rb +2 -2
- data/spec/requests/flows/password_spec.rb +118 -15
- data/spec/requests/flows/refresh_token_spec.rb +89 -19
- data/spec/requests/flows/revoke_token_spec.rb +105 -91
- data/spec/requests/protected_resources/metal_spec.rb +1 -1
- data/spec/requests/protected_resources/private_api_spec.rb +1 -1
- data/spec/routing/custom_controller_routes_spec.rb +4 -0
- data/spec/routing/default_routes_spec.rb +5 -1
- data/spec/spec_helper.rb +2 -0
- data/spec/spec_helper_integration.rb +22 -4
- data/spec/support/dependencies/factory_girl.rb +2 -2
- data/spec/support/helpers/access_token_request_helper.rb +1 -1
- data/spec/support/helpers/model_helper.rb +34 -7
- data/spec/support/helpers/request_spec_helper.rb +17 -5
- data/spec/support/helpers/url_helper.rb +9 -8
- data/spec/support/http_method_shim.rb +38 -0
- data/spec/support/shared/controllers_shared_context.rb +15 -10
- data/spec/support/shared/models_shared_examples.rb +5 -5
- data/spec/validators/redirect_uri_validator_spec.rb +51 -6
- data/spec/version/version_spec.rb +15 -0
- metadata +128 -46
- data/lib/doorkeeper/oauth/client/methods.rb +0 -18
- data/lib/generators/doorkeeper/application_scopes_generator.rb +0 -34
- data/lib/generators/doorkeeper/templates/add_scopes_to_oauth_applications.rb +0 -5
- data/spec/dummy/db/migrate/20130902165751_create_doorkeeper_tables.rb +0 -41
- data/spec/dummy/db/migrate/20141209001746_add_scopes_to_oauth_applications.rb +0 -5
- data/spec/lib/oauth/client/methods_spec.rb +0 -54
@@ -1,12 +1,47 @@
|
|
1
1
|
module Doorkeeper
|
2
2
|
module Models
|
3
3
|
module Revocable
|
4
|
+
# Revokes the object (updates `:revoked_at` attribute setting its value
|
5
|
+
# to the specific time).
|
6
|
+
#
|
7
|
+
# @param clock [Time] time object
|
8
|
+
#
|
4
9
|
def revoke(clock = Time)
|
5
|
-
update_attribute :revoked_at, clock.now
|
10
|
+
update_attribute :revoked_at, clock.now.utc
|
6
11
|
end
|
7
12
|
|
13
|
+
# Indicates whether the object has been revoked.
|
14
|
+
#
|
15
|
+
# @return [Boolean] true if revoked, false in other case
|
16
|
+
#
|
8
17
|
def revoked?
|
9
|
-
!!(revoked_at && revoked_at <= Time.now)
|
18
|
+
!!(revoked_at && revoked_at <= Time.now.utc)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Revokes token with `:refresh_token` equal to `:previous_refresh_token`
|
22
|
+
# and clears `:previous_refresh_token` attribute.
|
23
|
+
#
|
24
|
+
def revoke_previous_refresh_token!
|
25
|
+
return unless refresh_token_revoked_on_use?
|
26
|
+
old_refresh_token.revoke if old_refresh_token
|
27
|
+
update_attribute :previous_refresh_token, ""
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
# Searches for Access Token record with `:refresh_token` equal to
|
33
|
+
# `:previous_refresh_token` value.
|
34
|
+
#
|
35
|
+
# @return [Doorkeeper::AccessToken, nil]
|
36
|
+
# Access Token record or nil if nothing found
|
37
|
+
#
|
38
|
+
def old_refresh_token
|
39
|
+
@old_refresh_token ||=
|
40
|
+
AccessToken.by_refresh_token(previous_refresh_token)
|
41
|
+
end
|
42
|
+
|
43
|
+
def refresh_token_revoked_on_use?
|
44
|
+
AccessToken.refresh_token_revoked_on_use?
|
10
45
|
end
|
11
46
|
end
|
12
47
|
end
|
@@ -4,19 +4,33 @@ module Doorkeeper
|
|
4
4
|
class Token
|
5
5
|
attr_accessor :pre_auth, :resource_owner, :token
|
6
6
|
|
7
|
+
class << self
|
8
|
+
def access_token_expires_in(server, pre_auth_or_oauth_client)
|
9
|
+
if (expiration = custom_expiration(server, pre_auth_or_oauth_client))
|
10
|
+
expiration
|
11
|
+
else
|
12
|
+
server.access_token_expires_in
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def custom_expiration(server, pre_auth_or_oauth_client)
|
19
|
+
oauth_client = if pre_auth_or_oauth_client.respond_to?(:client)
|
20
|
+
pre_auth_or_oauth_client.client
|
21
|
+
else
|
22
|
+
pre_auth_or_oauth_client
|
23
|
+
end
|
24
|
+
|
25
|
+
server.custom_access_token_expires_in.call(oauth_client)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
7
29
|
def initialize(pre_auth, resource_owner)
|
8
30
|
@pre_auth = pre_auth
|
9
31
|
@resource_owner = resource_owner
|
10
32
|
end
|
11
33
|
|
12
|
-
def self.access_token_expires_in(server, pre_auth_or_oauth_client)
|
13
|
-
if expiration = custom_expiration(server, pre_auth_or_oauth_client)
|
14
|
-
expiration
|
15
|
-
else
|
16
|
-
server.access_token_expires_in
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
34
|
def issue_token
|
21
35
|
@token ||= AccessToken.find_or_create_for(
|
22
36
|
pre_auth.client,
|
@@ -37,16 +51,6 @@ module Doorkeeper
|
|
37
51
|
|
38
52
|
private
|
39
53
|
|
40
|
-
def self.custom_expiration(server, pre_auth_or_oauth_client)
|
41
|
-
oauth_client = if pre_auth_or_oauth_client.respond_to?(:client)
|
42
|
-
pre_auth_or_oauth_client.client
|
43
|
-
else
|
44
|
-
pre_auth_or_oauth_client
|
45
|
-
end
|
46
|
-
|
47
|
-
server.custom_access_token_expires_in.call(oauth_client)
|
48
|
-
end
|
49
|
-
|
50
54
|
def configuration
|
51
55
|
Doorkeeper.configuration
|
52
56
|
end
|
@@ -1,27 +1,29 @@
|
|
1
|
+
require 'rack/utils'
|
2
|
+
|
1
3
|
module Doorkeeper
|
2
4
|
module OAuth
|
3
5
|
module Authorization
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
6
|
+
class URIBuilder
|
7
|
+
class << self
|
8
|
+
def uri_with_query(url, parameters = {})
|
9
|
+
uri = URI.parse(url)
|
10
|
+
original_query = Rack::Utils.parse_query(uri.query)
|
11
|
+
uri.query = build_query(original_query.merge(parameters))
|
12
|
+
uri.to_s
|
13
|
+
end
|
8
14
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
end
|
15
|
+
def uri_with_fragment(url, parameters = {})
|
16
|
+
uri = URI.parse(url)
|
17
|
+
uri.fragment = build_query(parameters)
|
18
|
+
uri.to_s
|
19
|
+
end
|
15
20
|
|
16
|
-
|
17
|
-
uri = URI.parse(url)
|
18
|
-
uri.fragment = build_query(parameters)
|
19
|
-
uri.to_s
|
20
|
-
end
|
21
|
+
private
|
21
22
|
|
22
|
-
|
23
|
-
|
24
|
-
|
23
|
+
def build_query(parameters = {})
|
24
|
+
parameters = parameters.reject { |_, v| v.blank? }
|
25
|
+
Rack::Utils.build_query parameters
|
26
|
+
end
|
25
27
|
end
|
26
28
|
end
|
27
29
|
end
|
@@ -1,12 +1,10 @@
|
|
1
1
|
module Doorkeeper
|
2
2
|
module OAuth
|
3
|
-
class AuthorizationCodeRequest
|
4
|
-
include Validations
|
5
|
-
include OAuth::RequestConcern
|
6
|
-
|
3
|
+
class AuthorizationCodeRequest < BaseRequest
|
7
4
|
validate :attributes, error: :invalid_request
|
8
5
|
validate :client, error: :invalid_client
|
9
6
|
validate :grant, error: :invalid_grant
|
7
|
+
# @see https://tools.ietf.org/html/rfc6749#section-5.2
|
10
8
|
validate :redirect_uri, error: :invalid_grant
|
11
9
|
|
12
10
|
attr_accessor :server, :grant, :client, :redirect_uri, :access_token
|
@@ -31,6 +29,7 @@ module Doorkeeper
|
|
31
29
|
grant.scopes,
|
32
30
|
server)
|
33
31
|
end
|
32
|
+
super
|
34
33
|
end
|
35
34
|
|
36
35
|
def validate_attributes
|
@@ -47,7 +46,10 @@ module Doorkeeper
|
|
47
46
|
end
|
48
47
|
|
49
48
|
def validate_redirect_uri
|
50
|
-
|
49
|
+
Helpers::URIChecker.valid_for_authorization?(
|
50
|
+
redirect_uri,
|
51
|
+
grant.redirect_uri
|
52
|
+
)
|
51
53
|
end
|
52
54
|
end
|
53
55
|
end
|
@@ -1,8 +1,11 @@
|
|
1
1
|
module Doorkeeper
|
2
2
|
module OAuth
|
3
|
-
|
3
|
+
class BaseRequest
|
4
|
+
include Validations
|
5
|
+
|
4
6
|
def authorize
|
5
7
|
validate
|
8
|
+
|
6
9
|
if valid?
|
7
10
|
before_successful_response
|
8
11
|
@response = TokenResponse.new(access_token)
|
@@ -35,13 +38,17 @@ module Doorkeeper
|
|
35
38
|
resource_owner_id,
|
36
39
|
scopes,
|
37
40
|
Authorization::Token.access_token_expires_in(server, client),
|
38
|
-
server.refresh_token_enabled?
|
41
|
+
server.refresh_token_enabled?
|
42
|
+
)
|
39
43
|
end
|
40
44
|
|
41
45
|
def before_successful_response
|
46
|
+
Doorkeeper.configuration.before_successful_strategy_response.call(self)
|
42
47
|
end
|
43
48
|
|
44
49
|
def after_successful_response
|
50
|
+
Doorkeeper.configuration.after_successful_strategy_response.
|
51
|
+
call(self, @response)
|
45
52
|
end
|
46
53
|
end
|
47
54
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Doorkeeper
|
2
|
+
module OAuth
|
3
|
+
class BaseResponse
|
4
|
+
def body
|
5
|
+
{}
|
6
|
+
end
|
7
|
+
|
8
|
+
def description
|
9
|
+
""
|
10
|
+
end
|
11
|
+
|
12
|
+
def headers
|
13
|
+
{}
|
14
|
+
end
|
15
|
+
|
16
|
+
def redirectable?
|
17
|
+
false
|
18
|
+
end
|
19
|
+
|
20
|
+
def redirect_uri
|
21
|
+
""
|
22
|
+
end
|
23
|
+
|
24
|
+
def status
|
25
|
+
:ok
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -1,19 +1,32 @@
|
|
1
1
|
module Doorkeeper
|
2
2
|
module OAuth
|
3
3
|
class Client
|
4
|
-
|
5
|
-
|
4
|
+
Credentials = Struct.new(:uid, :secret) do
|
5
|
+
class << self
|
6
|
+
def from_request(request, *credentials_methods)
|
7
|
+
credentials_methods.inject(nil) do |credentials, method|
|
8
|
+
method = self.method(method) if method.is_a?(Symbol)
|
9
|
+
credentials = Credentials.new(*method.call(request))
|
10
|
+
break credentials unless credentials.blank?
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def from_params(request)
|
15
|
+
request.parameters.values_at(:client_id, :client_secret)
|
16
|
+
end
|
6
17
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
18
|
+
def from_basic(request)
|
19
|
+
authorization = request.authorization
|
20
|
+
if authorization.present? && authorization =~ /^Basic (.*)/m
|
21
|
+
Base64.decode64(Regexp.last_match(1)).split(/:/, 2)
|
22
|
+
end
|
12
23
|
end
|
13
24
|
end
|
14
25
|
|
26
|
+
# Public clients may have their secret blank, but "credentials" are
|
27
|
+
# still present
|
15
28
|
def blank?
|
16
|
-
uid.blank?
|
29
|
+
uid.blank?
|
17
30
|
end
|
18
31
|
end
|
19
32
|
end
|
@@ -1,4 +1,3 @@
|
|
1
|
-
require 'doorkeeper/oauth/client/methods'
|
2
1
|
require 'doorkeeper/oauth/client/credentials'
|
3
2
|
|
4
3
|
module Doorkeeper
|
@@ -13,7 +12,7 @@ module Doorkeeper
|
|
13
12
|
end
|
14
13
|
|
15
14
|
def self.find(uid, method = Application.method(:by_uid))
|
16
|
-
if application = method.call(uid)
|
15
|
+
if (application = method.call(uid))
|
17
16
|
new(application)
|
18
17
|
end
|
19
18
|
end
|
@@ -21,7 +20,7 @@ module Doorkeeper
|
|
21
20
|
def self.authenticate(credentials, method = Application.method(:by_uid_and_secret))
|
22
21
|
return false if credentials.blank?
|
23
22
|
|
24
|
-
if application = method.call(credentials.uid, credentials.secret)
|
23
|
+
if (application = method.call(credentials.uid, credentials.secret))
|
25
24
|
new(application)
|
26
25
|
end
|
27
26
|
end
|
@@ -2,12 +2,13 @@ require 'doorkeeper/oauth/client_credentials/validation'
|
|
2
2
|
|
3
3
|
module Doorkeeper
|
4
4
|
module OAuth
|
5
|
-
class ClientCredentialsRequest
|
5
|
+
class ClientCredentialsRequest < BaseRequest
|
6
6
|
class Issuer
|
7
7
|
attr_accessor :token, :validation, :error
|
8
8
|
|
9
9
|
def initialize(server, validation)
|
10
|
-
@server
|
10
|
+
@server = server
|
11
|
+
@validation = validation
|
11
12
|
end
|
12
13
|
|
13
14
|
def create(client, scopes, creator = Creator.new)
|
@@ -4,13 +4,12 @@ require 'doorkeeper/oauth/client_credentials/validation'
|
|
4
4
|
|
5
5
|
module Doorkeeper
|
6
6
|
module OAuth
|
7
|
-
class ClientCredentialsRequest
|
8
|
-
|
9
|
-
include OAuth::RequestConcern
|
10
|
-
|
11
|
-
attr_accessor :issuer, :server, :client, :original_scopes
|
7
|
+
class ClientCredentialsRequest < BaseRequest
|
8
|
+
attr_accessor :server, :client, :original_scopes
|
12
9
|
attr_reader :response
|
13
|
-
|
10
|
+
attr_writer :issuer
|
11
|
+
|
12
|
+
alias_method :error_response, :response
|
14
13
|
|
15
14
|
delegate :error, to: :issuer
|
16
15
|
|
@@ -19,8 +18,9 @@ module Doorkeeper
|
|
19
18
|
end
|
20
19
|
|
21
20
|
def initialize(server, client, parameters = {})
|
22
|
-
@client
|
23
|
-
@
|
21
|
+
@client = client
|
22
|
+
@server = server
|
23
|
+
@response = nil
|
24
24
|
@original_scopes = parameters[:scope]
|
25
25
|
end
|
26
26
|
|
@@ -1,13 +1,13 @@
|
|
1
1
|
module Doorkeeper
|
2
2
|
module OAuth
|
3
|
-
class CodeResponse
|
4
|
-
include OAuth::Authorization::URIBuilder
|
3
|
+
class CodeResponse < BaseResponse
|
5
4
|
include OAuth::Helpers
|
6
5
|
|
7
6
|
attr_accessor :pre_auth, :auth, :response_on_fragment
|
8
7
|
|
9
8
|
def initialize(pre_auth, auth, options = {})
|
10
|
-
@pre_auth
|
9
|
+
@pre_auth = pre_auth
|
10
|
+
@auth = auth
|
11
11
|
@response_on_fragment = options[:response_on_fragment]
|
12
12
|
end
|
13
13
|
|
@@ -18,20 +18,20 @@ module Doorkeeper
|
|
18
18
|
def redirect_uri
|
19
19
|
if URIChecker.native_uri? pre_auth.redirect_uri
|
20
20
|
auth.native_redirect
|
21
|
+
elsif response_on_fragment
|
22
|
+
Authorization::URIBuilder.uri_with_fragment(
|
23
|
+
pre_auth.redirect_uri,
|
24
|
+
access_token: auth.token.token,
|
25
|
+
token_type: auth.token.token_type,
|
26
|
+
expires_in: auth.token.expires_in_seconds,
|
27
|
+
state: pre_auth.state
|
28
|
+
)
|
21
29
|
else
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
expires_in: auth.token.expires_in,
|
28
|
-
state: pre_auth.state
|
29
|
-
)
|
30
|
-
else
|
31
|
-
uri_with_query pre_auth.redirect_uri,
|
32
|
-
code: auth.token.token,
|
33
|
-
state: pre_auth.state
|
34
|
-
end
|
30
|
+
Authorization::URIBuilder.uri_with_query(
|
31
|
+
pre_auth.redirect_uri,
|
32
|
+
code: auth.token.token,
|
33
|
+
state: pre_auth.state
|
34
|
+
)
|
35
35
|
end
|
36
36
|
end
|
37
37
|
end
|
@@ -1,10 +1,10 @@
|
|
1
1
|
module Doorkeeper
|
2
2
|
module OAuth
|
3
|
-
|
3
|
+
Error = Struct.new(:name, :state) do
|
4
4
|
def description
|
5
5
|
I18n.translate(
|
6
6
|
name,
|
7
|
-
scope: [
|
7
|
+
scope: %i[doorkeeper errors messages],
|
8
8
|
default: :server_error
|
9
9
|
)
|
10
10
|
end
|
@@ -1,12 +1,10 @@
|
|
1
1
|
module Doorkeeper
|
2
2
|
module OAuth
|
3
|
-
class ErrorResponse
|
4
|
-
include OAuth::Authorization::URIBuilder
|
3
|
+
class ErrorResponse < BaseResponse
|
5
4
|
include OAuth::Helpers
|
6
5
|
|
7
6
|
def self.from_request(request, attributes = {})
|
8
|
-
|
9
|
-
new(attributes.merge(name: request.error, state: state))
|
7
|
+
new(attributes.merge(name: request.error, state: request.try(:state)))
|
10
8
|
end
|
11
9
|
|
12
10
|
delegate :name, :description, :state, to: :@error
|
@@ -36,16 +34,12 @@ module Doorkeeper
|
|
36
34
|
|
37
35
|
def redirect_uri
|
38
36
|
if @response_on_fragment
|
39
|
-
uri_with_fragment @redirect_uri, body
|
37
|
+
Authorization::URIBuilder.uri_with_fragment @redirect_uri, body
|
40
38
|
else
|
41
|
-
uri_with_query @redirect_uri, body
|
39
|
+
Authorization::URIBuilder.uri_with_query @redirect_uri, body
|
42
40
|
end
|
43
41
|
end
|
44
42
|
|
45
|
-
def authenticate_info
|
46
|
-
%(Bearer realm="#{realm}", error="#{name}", error_description="#{description}")
|
47
|
-
end
|
48
|
-
|
49
43
|
def headers
|
50
44
|
{ 'Cache-Control' => 'no-store',
|
51
45
|
'Pragma' => 'no-cache',
|
@@ -60,6 +54,12 @@ module Doorkeeper
|
|
60
54
|
def configuration
|
61
55
|
Doorkeeper.configuration
|
62
56
|
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def authenticate_info
|
61
|
+
%(Bearer realm="#{realm}", error="#{name}", error_description="#{description}")
|
62
|
+
end
|
63
63
|
end
|
64
64
|
end
|
65
65
|
end
|
@@ -3,6 +3,7 @@ module Doorkeeper
|
|
3
3
|
module Helpers
|
4
4
|
module URIChecker
|
5
5
|
def self.valid?(url)
|
6
|
+
return true if native_uri?(url)
|
6
7
|
uri = as_uri(url)
|
7
8
|
uri.fragment.nil? && !uri.host.nil? && !uri.scheme.nil?
|
8
9
|
rescue URI::InvalidURIError
|
@@ -10,7 +11,15 @@ module Doorkeeper
|
|
10
11
|
end
|
11
12
|
|
12
13
|
def self.matches?(url, client_url)
|
13
|
-
url
|
14
|
+
url = as_uri(url)
|
15
|
+
client_url = as_uri(client_url)
|
16
|
+
|
17
|
+
if client_url.query.present?
|
18
|
+
return false unless query_matches?(url.query, client_url.query)
|
19
|
+
# Clear out queries so rest of URI can be tested. This allows query
|
20
|
+
# params to be in the request but order not mattering.
|
21
|
+
client_url.query = nil
|
22
|
+
end
|
14
23
|
url.query = nil
|
15
24
|
url == client_url
|
16
25
|
end
|
@@ -23,6 +32,13 @@ module Doorkeeper
|
|
23
32
|
URI.parse(url)
|
24
33
|
end
|
25
34
|
|
35
|
+
def self.query_matches?(query, client_query)
|
36
|
+
return true if client_query.nil? && query.nil?
|
37
|
+
return false if client_query.nil? || query.nil?
|
38
|
+
# Will return true independent of query order
|
39
|
+
client_query.split('&').sort == query.split('&').sort
|
40
|
+
end
|
41
|
+
|
26
42
|
def self.native_uri?(url)
|
27
43
|
url == Doorkeeper.configuration.native_redirect_uri
|
28
44
|
end
|
@@ -1,11 +1,12 @@
|
|
1
1
|
module Doorkeeper
|
2
2
|
module OAuth
|
3
3
|
class InvalidTokenResponse < ErrorResponse
|
4
|
+
attr_reader :reason
|
5
|
+
|
4
6
|
def self.from_access_token(access_token, attributes = {})
|
5
|
-
reason =
|
6
|
-
when access_token.try(:revoked?)
|
7
|
+
reason = if access_token.try(:revoked?)
|
7
8
|
:revoked
|
8
|
-
|
9
|
+
elsif access_token.try(:expired?)
|
9
10
|
:expired
|
10
11
|
else
|
11
12
|
:unknown
|
@@ -20,7 +21,7 @@ module Doorkeeper
|
|
20
21
|
end
|
21
22
|
|
22
23
|
def description
|
23
|
-
scope = { scope: [
|
24
|
+
scope = { scope: %i[doorkeeper errors messages invalid_token] }
|
24
25
|
@description ||= I18n.translate @reason, scope
|
25
26
|
end
|
26
27
|
end
|
@@ -1,33 +1,28 @@
|
|
1
1
|
module Doorkeeper
|
2
2
|
module OAuth
|
3
|
-
class PasswordAccessTokenRequest
|
4
|
-
include Validations
|
5
|
-
include OAuth::RequestConcern
|
3
|
+
class PasswordAccessTokenRequest < BaseRequest
|
6
4
|
include OAuth::Helpers
|
7
5
|
|
8
6
|
validate :client, error: :invalid_client
|
9
7
|
validate :resource_owner, error: :invalid_grant
|
10
8
|
validate :scopes, error: :invalid_scope
|
11
9
|
|
12
|
-
attr_accessor :server, :
|
13
|
-
|
10
|
+
attr_accessor :server, :client, :resource_owner, :parameters,
|
11
|
+
:access_token
|
14
12
|
|
15
|
-
def initialize(server,
|
13
|
+
def initialize(server, client, resource_owner, parameters = {})
|
16
14
|
@server = server
|
17
15
|
@resource_owner = resource_owner
|
18
|
-
@
|
16
|
+
@client = client
|
17
|
+
@parameters = parameters
|
19
18
|
@original_scopes = parameters[:scope]
|
20
|
-
|
21
|
-
if credentials
|
22
|
-
@client = Application.by_uid_and_secret credentials.uid,
|
23
|
-
credentials.secret
|
24
|
-
end
|
25
19
|
end
|
26
20
|
|
27
21
|
private
|
28
22
|
|
29
23
|
def before_successful_response
|
30
24
|
find_or_create_access_token(client, resource_owner.id, scopes, server)
|
25
|
+
super
|
31
26
|
end
|
32
27
|
|
33
28
|
def validate_scopes
|
@@ -40,7 +35,7 @@ module Doorkeeper
|
|
40
35
|
end
|
41
36
|
|
42
37
|
def validate_client
|
43
|
-
!
|
38
|
+
!parameters[:client_id] || !!client
|
44
39
|
end
|
45
40
|
end
|
46
41
|
end
|
@@ -57,9 +57,11 @@ module Doorkeeper
|
|
57
57
|
|
58
58
|
# TODO: test uri should be matched against the client's one
|
59
59
|
def validate_redirect_uri
|
60
|
-
return false
|
61
|
-
|
62
|
-
|
60
|
+
return false if redirect_uri.blank?
|
61
|
+
|
62
|
+
Helpers::URIChecker.valid_for_authorization?(
|
63
|
+
redirect_uri, client.redirect_uri
|
64
|
+
)
|
63
65
|
end
|
64
66
|
end
|
65
67
|
end
|