doorkeeper 0.3.0 → 0.4.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.
- data/.gitignore +12 -0
- data/.rspec +1 -0
- data/.travis.yml +8 -0
- data/CHANGELOG.md +98 -0
- data/Gemfile +6 -0
- data/README.md +42 -6
- data/app/controllers/doorkeeper/application_controller.rb +4 -11
- data/app/controllers/doorkeeper/applications_controller.rb +7 -1
- data/app/controllers/doorkeeper/authorizations_controller.rb +11 -1
- data/app/controllers/doorkeeper/authorized_applications_controller.rb +3 -3
- data/app/controllers/doorkeeper/tokens_controller.rb +19 -5
- data/app/models/doorkeeper/access_grant.rb +28 -0
- data/app/models/doorkeeper/access_token.rb +65 -0
- data/app/models/doorkeeper/application.rb +54 -0
- data/app/views/doorkeeper/applications/index.html.erb +1 -1
- data/app/views/doorkeeper/authorizations/error.html.erb +1 -1
- data/app/views/doorkeeper/authorizations/new.html.erb +15 -15
- data/app/views/doorkeeper/authorized_applications/index.html.erb +1 -2
- data/config/locales/en.yml +3 -0
- data/doorkeeper.gemspec +28 -0
- data/gemfiles/gemfile.rails-3.1.x +7 -0
- data/gemfiles/gemfile.rails-3.2.x +7 -0
- data/lib/doorkeeper/config.rb +73 -12
- data/lib/doorkeeper/doorkeeper_for.rb +19 -15
- data/lib/doorkeeper/engine.rb +28 -0
- data/lib/doorkeeper/models/scopes.rb +13 -0
- data/lib/doorkeeper/oauth/access_token_request.rb +9 -20
- data/lib/doorkeeper/oauth/authorization/code.rb +1 -1
- data/lib/doorkeeper/oauth/authorization/token.rb +2 -2
- data/lib/doorkeeper/oauth/authorization_request.rb +18 -23
- data/lib/doorkeeper/oauth/client/credentials.rb +21 -0
- data/lib/doorkeeper/oauth/client/methods.rb +18 -0
- data/lib/doorkeeper/oauth/client.rb +27 -0
- data/lib/doorkeeper/oauth/client_credentials/creator.rb +29 -0
- data/lib/doorkeeper/oauth/client_credentials/issuer.rb +35 -0
- data/lib/doorkeeper/oauth/client_credentials/response.rb +42 -0
- data/lib/doorkeeper/oauth/client_credentials/validation.rb +33 -0
- data/lib/doorkeeper/oauth/client_credentials_request.rb +46 -0
- data/lib/doorkeeper/oauth/error.rb +9 -0
- data/lib/doorkeeper/oauth/error_response.rb +30 -0
- data/lib/doorkeeper/oauth/helpers/scope_checker.rb +2 -2
- data/lib/doorkeeper/oauth/password_access_token_request.rb +130 -0
- data/lib/doorkeeper/oauth/scopes.rb +60 -0
- data/lib/doorkeeper/version.rb +1 -1
- data/lib/doorkeeper.rb +23 -3
- data/lib/generators/doorkeeper/install_generator.rb +1 -0
- data/lib/generators/doorkeeper/templates/initializer.rb +12 -7
- data/lib/generators/doorkeeper/templates/migration.rb +1 -1
- data/lib/generators/doorkeeper/views_generator.rb +15 -0
- data/script/rails +6 -0
- data/script/run_all +11 -0
- data/spec/controllers/applications_controller_spec.rb +18 -0
- data/spec/controllers/authorizations_controller_spec.rb +131 -0
- data/spec/controllers/protected_resources_controller_spec.rb +308 -0
- data/spec/controllers/tokens_controller_spec.rb +34 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/assets/javascripts/application.js +9 -0
- data/spec/dummy/app/assets/stylesheets/application.css +7 -0
- data/spec/dummy/app/controllers/application_controller.rb +3 -0
- data/spec/dummy/app/controllers/full_protected_resources_controller.rb +12 -0
- data/spec/dummy/app/controllers/home_controller.rb +17 -0
- data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +11 -0
- data/spec/dummy/app/helpers/application_helper.rb +5 -0
- data/spec/dummy/app/models/user.rb +11 -0
- data/spec/dummy/app/views/home/index.html.erb +0 -0
- data/spec/dummy/app/views/layouts/application.html.erb +16 -0
- data/spec/dummy/config/application.rb +53 -0
- data/spec/dummy/config/boot.rb +10 -0
- data/spec/dummy/config/database.yml +15 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +30 -0
- data/spec/dummy/config/environments/production.rb +60 -0
- data/spec/dummy/config/environments/test.rb +39 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/doorkeeper.rb +41 -0
- data/spec/dummy/config/initializers/secret_token.rb +7 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/doorkeeper.en.yml +5 -0
- data/spec/dummy/config/routes.rb +8 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/db/migrate/20111122132257_create_users.rb +9 -0
- data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +5 -0
- data/spec/dummy/db/migrate/20120524202412_create_doorkeeper_tables.rb +42 -0
- data/spec/dummy/db/schema.rb +62 -0
- data/spec/dummy/public/404.html +26 -0
- data/spec/dummy/public/422.html +26 -0
- data/spec/dummy/public/500.html +26 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/factories/access_grant.rb +9 -0
- data/spec/factories/access_token.rb +7 -0
- data/spec/factories/application.rb +6 -0
- data/spec/generators/install_generator_spec.rb +35 -0
- data/spec/generators/templates/routes.rb +3 -0
- data/spec/generators/views_generator_spec.rb +27 -0
- data/spec/lib/config_spec.rb +87 -0
- data/spec/lib/models/expirable_spec.rb +49 -0
- data/spec/lib/models/revocable_spec.rb +31 -0
- data/spec/lib/models/scopes_spec.rb +32 -0
- data/spec/lib/oauth/access_token_request_spec.rb +240 -0
- data/spec/lib/oauth/authorization/uri_builder_spec.rb +37 -0
- data/spec/lib/oauth/authorization_request_spec.rb +286 -0
- data/spec/lib/oauth/client/credentials_spec.rb +47 -0
- data/spec/lib/oauth/client/methods_spec.rb +54 -0
- data/spec/lib/oauth/client_credentials/creator_spec.rb +47 -0
- data/spec/lib/oauth/client_credentials/issuer_spec.rb +57 -0
- data/spec/lib/oauth/client_credentials/response_spec.rb +58 -0
- data/spec/lib/oauth/client_credentials/validation_spec.rb +29 -0
- data/spec/lib/oauth/client_credentials_integration_spec.rb +27 -0
- data/spec/lib/oauth/client_credentials_request_spec.rb +60 -0
- data/spec/lib/oauth/client_spec.rb +42 -0
- data/spec/lib/oauth/error_response_spec.rb +40 -0
- data/spec/lib/oauth/error_spec.rb +19 -0
- data/spec/lib/oauth/helpers/scope_checker_spec.rb +74 -0
- data/spec/lib/oauth/helpers/unique_token_spec.rb +38 -0
- data/spec/lib/oauth/helpers/uri_checker_spec.rb +64 -0
- data/spec/lib/oauth/password_access_token_request_spec.rb +152 -0
- data/spec/lib/oauth/scopes_spec.rb +115 -0
- data/spec/models/doorkeeper/access_grant_spec.rb +36 -0
- data/spec/models/doorkeeper/access_token_spec.rb +113 -0
- data/spec/models/doorkeeper/application_spec.rb +129 -0
- data/spec/requests/applications/applications_request_spec.rb +92 -0
- data/spec/requests/applications/authorized_applications_spec.rb +30 -0
- data/spec/requests/endpoints/authorization_spec.rb +63 -0
- data/spec/requests/endpoints/token_spec.rb +29 -0
- data/spec/requests/flows/authorization_code_errors_spec.rb +111 -0
- data/spec/requests/flows/authorization_code_spec.rb +125 -0
- data/spec/requests/flows/client_credentials_spec.rb +56 -0
- data/spec/requests/flows/implicit_grant_errors_spec.rb +31 -0
- data/spec/requests/flows/implicit_grant_spec.rb +19 -0
- data/spec/requests/flows/password_spec.rb +52 -0
- data/spec/requests/flows/refresh_token_spec.rb +66 -0
- data/spec/requests/flows/skip_authorization_spec.rb +40 -0
- data/spec/requests/protected_resources/private_api_spec.rb +43 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/spec_helper_integration.rb +28 -0
- data/spec/support/dependencies/database_cleaner.rb +16 -0
- data/spec/support/dependencies/factory_girl.rb +5 -0
- data/spec/support/helpers/access_token_request_helper.rb +11 -0
- data/spec/support/helpers/authorization_request_helper.rb +32 -0
- data/spec/support/helpers/config_helper.rb +9 -0
- data/spec/support/helpers/model_helper.rb +45 -0
- data/spec/support/helpers/request_spec_helper.rb +72 -0
- data/spec/support/helpers/url_helper.rb +51 -0
- data/spec/support/shared/controllers_shared_context.rb +60 -0
- data/spec/support/shared/models_shared_examples.rb +44 -0
- metadata +163 -57
- data/app/controllers/doorkeeper/application_controller.rbc +0 -675
- data/app/controllers/doorkeeper/applications_controller.rbc +0 -954
- data/app/controllers/doorkeeper/authorizations_controller.rbc +0 -659
- data/app/controllers/doorkeeper/authorized_applications_controller.rbc +0 -393
- data/app/controllers/doorkeeper/tokens_controller.rbc +0 -423
- data/app/helpers/doorkeeper/application_helper.rbc +0 -127
- data/app/models/access_grant.rb +0 -31
- data/app/models/access_grant.rbc +0 -821
- data/app/models/access_token.rb +0 -70
- data/app/models/access_token.rbc +0 -979
- data/app/models/application.rb +0 -45
- data/app/models/application.rbc +0 -753
- data/config/initializers/form_errors.rbc +0 -272
- data/config/routes.rbc +0 -366
- data/lib/doorkeeper/config/scope.rb +0 -11
- data/lib/doorkeeper/config/scopes.rb +0 -61
- data/lib/doorkeeper/config/scopes_builder.rb +0 -18
- data/lib/doorkeeper/config.rbc +0 -1385
- data/lib/doorkeeper/doorkeeper_for.rbc +0 -1029
- data/lib/doorkeeper/engine.rbc +0 -318
- data/lib/doorkeeper/oauth/access_token_request.rbc +0 -2042
- data/lib/doorkeeper/oauth/authorization_request.rbc +0 -2272
- data/lib/doorkeeper/oauth/random_string.rbc +0 -437
- data/lib/doorkeeper/validations.rbc +0 -774
- data/lib/doorkeeper/version.rbc +0 -130
- data/lib/doorkeeper.rbc +0 -407
- data/lib/generators/doorkeeper/install_generator.rbc +0 -453
- data/lib/tasks/doorkeeper_tasks.rake.compiled.rbc +0 -40
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
require 'doorkeeper/validations'
|
|
2
|
+
require 'doorkeeper/oauth/scopes'
|
|
3
|
+
require 'doorkeeper/oauth/helpers/scope_checker'
|
|
4
|
+
|
|
5
|
+
module Doorkeeper
|
|
6
|
+
module OAuth
|
|
7
|
+
class ClientCredentialsRequest
|
|
8
|
+
class Validation
|
|
9
|
+
include Doorkeeper::Validations
|
|
10
|
+
include Doorkeeper::OAuth::Helpers
|
|
11
|
+
|
|
12
|
+
validate :client, :error => :invalid_client
|
|
13
|
+
validate :scopes, :error => :invalid_scope
|
|
14
|
+
|
|
15
|
+
def initialize(server, request)
|
|
16
|
+
@server, @request = server, request
|
|
17
|
+
validate
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
def validate_client
|
|
23
|
+
@request.client.present?
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def validate_scopes
|
|
27
|
+
return true unless @request.original_scopes.present?
|
|
28
|
+
ScopeChecker.valid?(@request.original_scopes, @server.scopes)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
require 'doorkeeper/oauth/error'
|
|
2
|
+
require 'doorkeeper/oauth/error_response'
|
|
3
|
+
require 'doorkeeper/oauth/scopes'
|
|
4
|
+
require 'doorkeeper/oauth/client_credentials/creator'
|
|
5
|
+
require 'doorkeeper/oauth/client_credentials/issuer'
|
|
6
|
+
require 'doorkeeper/oauth/client_credentials/response'
|
|
7
|
+
require 'doorkeeper/oauth/client_credentials/validation'
|
|
8
|
+
|
|
9
|
+
module Doorkeeper
|
|
10
|
+
module OAuth
|
|
11
|
+
class ClientCredentialsRequest
|
|
12
|
+
attr_accessor :issuer, :server, :client, :original_scopes, :scopes
|
|
13
|
+
attr_reader :response
|
|
14
|
+
alias :authorization :response # Remove this when API is consistent
|
|
15
|
+
alias :error_response :response
|
|
16
|
+
|
|
17
|
+
delegate :error, :to => :issuer
|
|
18
|
+
|
|
19
|
+
def issuer
|
|
20
|
+
@issuer ||= Issuer.new(server, Validation.new(server, self))
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def initialize(server, client, parameters = {})
|
|
24
|
+
@client, @server = client, server
|
|
25
|
+
@response = nil
|
|
26
|
+
@original_scopes = parameters[:scope]
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def authorize
|
|
30
|
+
@response = if issuer.create(client, scopes)
|
|
31
|
+
Response.new(issuer.token)
|
|
32
|
+
else
|
|
33
|
+
ErrorResponse.from_request(self)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def scopes
|
|
38
|
+
@scopes ||= if @original_scopes.present?
|
|
39
|
+
Doorkeeper::OAuth::Scopes.from_string(@original_scopes)
|
|
40
|
+
else
|
|
41
|
+
server.default_scopes
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module Doorkeeper
|
|
2
|
+
module OAuth
|
|
3
|
+
class ErrorResponse
|
|
4
|
+
include ActiveModel::Serializers::JSON
|
|
5
|
+
|
|
6
|
+
self.include_root_in_json = false
|
|
7
|
+
|
|
8
|
+
def self.from_request(request)
|
|
9
|
+
state = request.state if request.respond_to?(:state)
|
|
10
|
+
new(:name => request.error, :state => state)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
delegate :name, :description, :state, :to => :@error
|
|
14
|
+
alias :error :name
|
|
15
|
+
alias :error_description :description
|
|
16
|
+
|
|
17
|
+
def initialize(attributes = {})
|
|
18
|
+
@error = Doorkeeper::OAuth::Error.new(*attributes.values_at(:name, :state))
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def attributes
|
|
22
|
+
{ 'error' => name, 'error_description' => description, 'state' => state }.reject { |k, v| v.blank? }
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def status
|
|
26
|
+
:unauthorized
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -4,13 +4,13 @@ module Doorkeeper
|
|
|
4
4
|
module ScopeChecker
|
|
5
5
|
def self.matches?(current_scopes, scopes)
|
|
6
6
|
return false if current_scopes.nil? || scopes.nil?
|
|
7
|
-
current_scopes
|
|
7
|
+
current_scopes == scopes
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
def self.valid?(scope, server_scopes)
|
|
11
11
|
scope.present? &&
|
|
12
12
|
scope !~ /[\n|\r|\t]/ &&
|
|
13
|
-
server_scopes.
|
|
13
|
+
server_scopes.has_scopes?(Doorkeeper::OAuth::Scopes.from_string(scope))
|
|
14
14
|
end
|
|
15
15
|
end
|
|
16
16
|
end
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
|
|
3
|
+
# TODO: refactor to DRY up, this is very similar to AccessTokenRequest
|
|
4
|
+
module Doorkeeper::OAuth
|
|
5
|
+
class PasswordAccessTokenRequest
|
|
6
|
+
include Doorkeeper::Validations
|
|
7
|
+
|
|
8
|
+
ATTRIBUTES = [
|
|
9
|
+
:grant_type,
|
|
10
|
+
:username,
|
|
11
|
+
:password,
|
|
12
|
+
:scope,
|
|
13
|
+
:refresh_token
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
validate :attributes, :error => :invalid_request
|
|
17
|
+
validate :grant_type, :error => :unsupported_grant_type
|
|
18
|
+
validate :client, :error => :invalid_client
|
|
19
|
+
validate :resource_owner, :error => :invalid_resource_owner
|
|
20
|
+
validate :scope, :error => :invalid_scope
|
|
21
|
+
|
|
22
|
+
attr_accessor *ATTRIBUTES
|
|
23
|
+
attr_accessor :resource_owner, :client
|
|
24
|
+
|
|
25
|
+
def initialize(client, owner, attributes = {})
|
|
26
|
+
ATTRIBUTES.each { |attr| instance_variable_set("@#{attr}", attributes[attr]) }
|
|
27
|
+
@resource_owner = owner
|
|
28
|
+
@client = client
|
|
29
|
+
validate
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def authorize
|
|
33
|
+
if valid?
|
|
34
|
+
find_or_create_access_token
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def authorization
|
|
39
|
+
auth = {
|
|
40
|
+
'access_token' => access_token.token,
|
|
41
|
+
'token_type' => access_token.token_type,
|
|
42
|
+
'expires_in' => access_token.expires_in,
|
|
43
|
+
}
|
|
44
|
+
auth.merge!({'refresh_token' => access_token.refresh_token}) if refresh_token_enabled?
|
|
45
|
+
auth
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def valid?
|
|
49
|
+
self.error.nil?
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def access_token
|
|
53
|
+
@access_token
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def token_type
|
|
57
|
+
"bearer"
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def error_response
|
|
61
|
+
Doorkeeper::OAuth::ErrorResponse.from_request(self)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def scopes
|
|
65
|
+
@scopes ||= if scope.present?
|
|
66
|
+
Doorkeeper::OAuth::Scopes.from_string(scope)
|
|
67
|
+
else
|
|
68
|
+
Doorkeeper.configuration.default_scopes
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
private
|
|
73
|
+
|
|
74
|
+
def find_or_create_access_token
|
|
75
|
+
if access_token
|
|
76
|
+
access_token.expired? ? revoke_and_create_access_token : access_token
|
|
77
|
+
else
|
|
78
|
+
create_access_token
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def revoke_and_create_access_token
|
|
83
|
+
access_token.revoke
|
|
84
|
+
create_access_token
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def revoke_base_token
|
|
88
|
+
base_token.revoke
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def create_access_token
|
|
92
|
+
@access_token = Doorkeeper::AccessToken.create!({
|
|
93
|
+
:application_id => client.id,
|
|
94
|
+
:resource_owner_id => resource_owner.id,
|
|
95
|
+
:scopes => scopes.to_s,
|
|
96
|
+
:expires_in => configuration.access_token_expires_in,
|
|
97
|
+
:use_refresh_token => refresh_token_enabled?
|
|
98
|
+
})
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def validate_attributes
|
|
102
|
+
grant_type.present?
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def refresh_token_enabled?
|
|
106
|
+
configuration.refresh_token_enabled?
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def validate_client
|
|
110
|
+
!!client
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def validate_scope
|
|
114
|
+
return true unless scope.present?
|
|
115
|
+
ScopeChecker.valid?(scope, configuration.scopes)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def validate_grant_type
|
|
119
|
+
grant_type == 'password'
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def validate_resource_owner
|
|
123
|
+
!!resource_owner
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def configuration
|
|
127
|
+
Doorkeeper.configuration
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
module Doorkeeper
|
|
2
|
+
module OAuth
|
|
3
|
+
class Scopes
|
|
4
|
+
include Enumerable
|
|
5
|
+
include Comparable
|
|
6
|
+
|
|
7
|
+
def self.from_string(string)
|
|
8
|
+
string ||= ""
|
|
9
|
+
new.tap do |scope|
|
|
10
|
+
scope.add *string.split
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def self.from_array(array)
|
|
15
|
+
new.tap do |scope|
|
|
16
|
+
scope.add *array
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
delegate :each, :to => :@scopes
|
|
21
|
+
|
|
22
|
+
def initialize
|
|
23
|
+
@scopes = []
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def exists?(scope)
|
|
27
|
+
@scopes.include? scope.to_sym
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def add(*scopes)
|
|
31
|
+
@scopes.push *scopes.map(&:to_sym)
|
|
32
|
+
@scopes.uniq!
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def all
|
|
36
|
+
@scopes
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def to_s
|
|
40
|
+
@scopes.join(" ")
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def has_scopes?(scopes)
|
|
44
|
+
scopes.all? { |s| exists?(s) }
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def +(other)
|
|
48
|
+
if other.is_a? Scopes
|
|
49
|
+
self.class.from_array(self.all + other.all)
|
|
50
|
+
else
|
|
51
|
+
super(other)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def <=>(other)
|
|
56
|
+
self.map(&:to_s).sort <=> other.map(&:to_s).sort
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
data/lib/doorkeeper/version.rb
CHANGED
data/lib/doorkeeper.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
require "doorkeeper/version"
|
|
1
2
|
require "doorkeeper/engine"
|
|
2
3
|
require "doorkeeper/config"
|
|
3
4
|
require "doorkeeper/doorkeeper_for"
|
|
@@ -6,9 +7,15 @@ module Doorkeeper
|
|
|
6
7
|
autoload :Validations, "doorkeeper/validations"
|
|
7
8
|
|
|
8
9
|
module OAuth
|
|
9
|
-
autoload :
|
|
10
|
-
autoload :
|
|
11
|
-
autoload :
|
|
10
|
+
autoload :Scopes, "doorkeeper/oauth/scopes"
|
|
11
|
+
autoload :Error, "doorkeeper/oauth/error"
|
|
12
|
+
autoload :ErrorResponse, "doorkeeper/oauth/error_response"
|
|
13
|
+
autoload :AuthorizationRequest, "doorkeeper/oauth/authorization_request"
|
|
14
|
+
autoload :AccessTokenRequest, "doorkeeper/oauth/access_token_request"
|
|
15
|
+
autoload :PasswordAccessTokenRequest, "doorkeeper/oauth/password_access_token_request"
|
|
16
|
+
autoload :ClientCredentialsRequest, "doorkeeper/oauth/client_credentials_request"
|
|
17
|
+
autoload :Authorization, "doorkeeper/oauth/authorization"
|
|
18
|
+
autoload :Client, "doorkeeper/oauth/client"
|
|
12
19
|
|
|
13
20
|
module Helpers
|
|
14
21
|
autoload :ScopeChecker, "doorkeeper/oauth/helpers/scope_checker"
|
|
@@ -20,5 +27,18 @@ module Doorkeeper
|
|
|
20
27
|
module Models
|
|
21
28
|
autoload :Expirable, "doorkeeper/models/expirable"
|
|
22
29
|
autoload :Revocable, "doorkeeper/models/revocable"
|
|
30
|
+
autoload :Scopes, "doorkeeper/models/scopes"
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def self.configured?
|
|
34
|
+
@config.present?
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def self.database_installed?
|
|
38
|
+
[AccessToken, AccessGrant, Application].all? { |model| model.table_exists? }
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def self.installed?
|
|
42
|
+
configured? && database_installed?
|
|
23
43
|
end
|
|
24
44
|
end
|
|
@@ -3,6 +3,7 @@ require 'rails/generators/active_record'
|
|
|
3
3
|
class Doorkeeper::InstallGenerator < Rails::Generators::Base
|
|
4
4
|
include Rails::Generators::Migration
|
|
5
5
|
source_root File.expand_path('../templates', __FILE__)
|
|
6
|
+
desc "Installs Doorkeeper."
|
|
6
7
|
|
|
7
8
|
def install
|
|
8
9
|
migration_template 'migration.rb', 'db/migrate/create_doorkeeper_tables.rb'
|
|
@@ -7,7 +7,7 @@ Doorkeeper.configure do
|
|
|
7
7
|
# If you want to use named routes from your app you need
|
|
8
8
|
# to call them on routes object eg.
|
|
9
9
|
# routes.new_user_session_path
|
|
10
|
-
# e.g. User.find_by_id(session[:user_id]) || redirect_to
|
|
10
|
+
# e.g. User.find_by_id(session[:user_id]) || redirect_to(routes.new_user_session_url)
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
# If you want to restrict the access to the web interface for
|
|
@@ -18,10 +18,11 @@ Doorkeeper.configure do
|
|
|
18
18
|
# # If you want to use named routes from your app you need
|
|
19
19
|
# # to call them on routes object eg.
|
|
20
20
|
# # routes.new_admin_session_path
|
|
21
|
-
# Admin.find_by_id(session[:admin_id]) || redirect_to
|
|
21
|
+
# Admin.find_by_id(session[:admin_id]) || redirect_to(routes.new_admin_session_url)
|
|
22
22
|
# end
|
|
23
23
|
|
|
24
|
-
# Access token expiration time (default 2 hours)
|
|
24
|
+
# Access token expiration time (default 2 hours).
|
|
25
|
+
# If you want to disable expiration, set this to nil.
|
|
25
26
|
# access_token_expires_in 2.hours
|
|
26
27
|
|
|
27
28
|
# Issue access tokens with refresh token (disabled by default)
|
|
@@ -29,8 +30,12 @@ Doorkeeper.configure do
|
|
|
29
30
|
|
|
30
31
|
# Define access token scopes for your provider
|
|
31
32
|
# For more information go to https://github.com/applicake/doorkeeper/wiki/Using-Scopes
|
|
32
|
-
#
|
|
33
|
-
#
|
|
34
|
-
|
|
35
|
-
#
|
|
33
|
+
# default_scopes :public
|
|
34
|
+
# optional_scopes :write, :update
|
|
35
|
+
|
|
36
|
+
# Change the way client credentials are retrieved from the request object.
|
|
37
|
+
# By default it retrieves first from `HTTP_AUTHORIZATION` header and
|
|
38
|
+
# fallsback to `:client_id` and `:client_secret` from `params` object
|
|
39
|
+
# Check out the wiki for mor information on customization
|
|
40
|
+
# client_credentials :from_basic, :from_params
|
|
36
41
|
end
|
|
@@ -24,7 +24,7 @@ class CreateDoorkeeperTables < ActiveRecord::Migration
|
|
|
24
24
|
add_index :oauth_access_grants, :token, :unique => true
|
|
25
25
|
|
|
26
26
|
create_table :oauth_access_tokens do |t|
|
|
27
|
-
t.integer :resource_owner_id
|
|
27
|
+
t.integer :resource_owner_id
|
|
28
28
|
t.integer :application_id, :null => false
|
|
29
29
|
t.string :token, :null => false
|
|
30
30
|
t.string :refresh_token
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module Doorkeeper
|
|
2
|
+
module Generators
|
|
3
|
+
class ViewsGenerator < Rails::Generators::Base
|
|
4
|
+
source_root File.expand_path('../../../../app/views/doorkeeper', __FILE__)
|
|
5
|
+
|
|
6
|
+
desc "Copies default Doorkeeper views to your application."
|
|
7
|
+
|
|
8
|
+
def manifest
|
|
9
|
+
directory 'applications', 'app/views/doorkeeper/applications'
|
|
10
|
+
directory 'authorizations', 'app/views/doorkeeper/authorizations'
|
|
11
|
+
directory 'authorized_applications', 'app/views/doorkeeper/authorized_applications'
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
data/script/rails
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
#!/usr/bin/env ruby
|
|
3
|
+
# This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
|
|
4
|
+
|
|
5
|
+
ENGINE_PATH = File.expand_path('../..', __FILE__)
|
|
6
|
+
load File.expand_path('../../spec/dummy/script/rails', __FILE__)
|
data/script/run_all
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -e
|
|
3
|
+
|
|
4
|
+
RBENV_VERSION=1.8.7-p352 bundle install --quiet
|
|
5
|
+
RBENV_VERSION=1.8.7-p352 bundle exec rake
|
|
6
|
+
|
|
7
|
+
RBENV_VERSION=1.9.2-p290 bundle install --quiet
|
|
8
|
+
RBENV_VERSION=1.9.2-p290 bundle exec rake
|
|
9
|
+
|
|
10
|
+
RBENV_VERSION=1.9.3-p0 bundle install --quiet
|
|
11
|
+
RBENV_VERSION=1.9.3-p0 bundle exec rake
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
require 'spec_helper_integration'
|
|
2
|
+
|
|
3
|
+
module Doorkeeper
|
|
4
|
+
describe ApplicationsController do
|
|
5
|
+
context "when admin is not authenticated" do
|
|
6
|
+
before(:each) do
|
|
7
|
+
Doorkeeper.configuration.stub(:authenticate_admin => proc do
|
|
8
|
+
redirect_to main_app.root_url
|
|
9
|
+
end)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it "redirects as set in Doorkeeper.authenticate_admin" do
|
|
13
|
+
get :index, :use_route => :doorkeeper
|
|
14
|
+
response.should redirect_to(controller.main_app.root_url)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
require 'spec_helper_integration'
|
|
2
|
+
|
|
3
|
+
describe Doorkeeper::AuthorizationsController, "implicit grant flow" do
|
|
4
|
+
include AuthorizationRequestHelper
|
|
5
|
+
|
|
6
|
+
def fragments(param)
|
|
7
|
+
fragment = URI.parse(response.location).fragment
|
|
8
|
+
Rack::Utils.parse_query(fragment)[param]
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def translated_error_message(key)
|
|
12
|
+
I18n.translate key, :scope => [:doorkeeper, :errors, :messages]
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
let(:client) { FactoryGirl.create :application }
|
|
16
|
+
let(:user) { User.create!(:name => "Joe", :password => "sekret") }
|
|
17
|
+
|
|
18
|
+
before do
|
|
19
|
+
controller.stub :current_resource_owner => user
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
describe "POST #create" do
|
|
23
|
+
before do
|
|
24
|
+
post :create, :client_id => client.uid, :response_type => "token", :redirect_uri => client.redirect_uri, :use_route => :doorkeeper
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it "redirects after authorization" do
|
|
28
|
+
response.should be_redirect
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "redirects to client redirect uri" do
|
|
32
|
+
response.location.should =~ %r[^#{client.redirect_uri}]
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it "includes access token in fragment" do
|
|
36
|
+
fragments("access_token").should == Doorkeeper::AccessToken.first.token
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "includes token type in fragment" do
|
|
40
|
+
fragments("token_type").should == "bearer"
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it "includes token expiration in fragment" do
|
|
44
|
+
fragments("expires_in").to_i.should == 2.hours.to_i
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it "issues the token for the current client" do
|
|
48
|
+
Doorkeeper::AccessToken.first.application_id.should == client.id
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it "issues the token for the current resource owner" do
|
|
52
|
+
Doorkeeper::AccessToken.first.resource_owner_id.should == user.id
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
describe "POST #create with errors" do
|
|
57
|
+
before do
|
|
58
|
+
default_scopes_exist :public
|
|
59
|
+
post :create, :client_id => client.uid, :response_type => "token", :scope => "invalid", :redirect_uri => client.redirect_uri, :use_route => :doorkeeper
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it "redirects after authorization" do
|
|
63
|
+
response.should be_redirect
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it "redirects to client redirect uri" do
|
|
67
|
+
response.location.should =~ %r[^#{client.redirect_uri}]
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it "does not include access token in fragment" do
|
|
71
|
+
fragments("access_token").should be_nil
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
it "includes error in fragment" do
|
|
75
|
+
fragments("error").should == "invalid_scope"
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
it "includes error description in fragment" do
|
|
79
|
+
fragments("error_description").should == translated_error_message(:invalid_scope)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
it "does not issue any access token" do
|
|
83
|
+
Doorkeeper::AccessToken.all.should be_empty
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
describe "POST #create with application already authorized" do
|
|
88
|
+
it "returns the existing access token in a fragment"
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
describe "GET #new" do
|
|
92
|
+
before do
|
|
93
|
+
get :new, :client_id => client.uid, :response_type => "token", :redirect_uri => client.redirect_uri, :use_route => :doorkeeper
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
it 'renders new template' do
|
|
97
|
+
response.should render_template(:new)
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
describe "GET #new with errors" do
|
|
102
|
+
before do
|
|
103
|
+
default_scopes_exist :public
|
|
104
|
+
get :new, :client_id => client.uid, :response_type => "token", :scope => "invalid", :redirect_uri => client.redirect_uri, :use_route => :doorkeeper
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
it "redirects after authorization" do
|
|
108
|
+
response.should be_redirect
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
it "redirects to client redirect uri" do
|
|
112
|
+
response.location.should =~ %r[^#{client.redirect_uri}]
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
it "does not include access token in fragment" do
|
|
116
|
+
fragments("access_token").should be_nil
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
it "includes error in fragment" do
|
|
120
|
+
fragments("error").should == "invalid_scope"
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
it "includes error description in fragment" do
|
|
124
|
+
fragments("error_description").should == translated_error_message(:invalid_scope)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
it "does not issue any access token" do
|
|
128
|
+
Doorkeeper::AccessToken.all.should be_empty
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|