doorkeeper 3.0.1 → 3.1.0
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/.hound.yml +4 -0
- data/.travis.yml +5 -1
- data/NEWS.md +12 -0
- data/README.md +8 -11
- data/app/assets/stylesheets/doorkeeper/admin/application.css +1 -5
- data/app/views/layouts/doorkeeper/admin.html.erb +5 -2
- data/doorkeeper.gemspec +1 -1
- data/lib/doorkeeper/helpers/controller.rb +2 -0
- data/lib/doorkeeper/oauth/client_credentials/creator.rb +3 -4
- data/lib/doorkeeper/oauth/error.rb +5 -1
- data/lib/doorkeeper/orm/active_record.rb +4 -3
- data/lib/doorkeeper/rails/helpers.rb +12 -2
- data/lib/doorkeeper/request.rb +18 -8
- data/lib/doorkeeper/request/authorization_code.rb +10 -15
- data/lib/doorkeeper/request/client_credentials.rb +9 -15
- data/lib/doorkeeper/request/code.rb +7 -13
- data/lib/doorkeeper/request/password.rb +10 -15
- data/lib/doorkeeper/request/refresh_token.rb +11 -13
- data/lib/doorkeeper/request/strategy.rb +17 -0
- data/lib/doorkeeper/request/token.rb +7 -13
- data/lib/doorkeeper/server.rb +2 -2
- data/lib/doorkeeper/version.rb +1 -1
- data/spec/controllers/protected_resources_controller_spec.rb +95 -1
- data/spec/controllers/tokens_controller_spec.rb +30 -0
- data/spec/lib/oauth/client_credentials/creator_spec.rb +25 -1
- data/spec/lib/oauth/error_response_spec.rb +7 -7
- data/spec/lib/oauth/error_spec.rb +9 -5
- data/spec/lib/oauth/scopes_spec.rb +1 -1
- data/spec/lib/request/strategy_spec.rb +53 -0
- data/spec/lib/server_spec.rb +1 -1
- data/spec/models/doorkeeper/access_grant_spec.rb +5 -5
- data/spec/models/doorkeeper/access_token_spec.rb +2 -2
- metadata +8 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 03417189314de7b84fcfa05699c35a0346a55035
|
4
|
+
data.tar.gz: e4026de8e9ed39d2bb270abc9efc4e1ccca20775
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bbe0a1693809bfc8802a66c50df30a128a527a3f239114ffdc69d46e948ac0516594fe3872f3624157632e91078a0ad64aa1f98932b26bdf389228b22bed246b
|
7
|
+
data.tar.gz: 6d434e7dc34b65d1022914f8fd348c9d1c8e6ef41bb30761411eb0c693531ccb12c87c237c1e54fbcbee11a8dd0bf68c82768a6801f273dab2bcaf1fe96afea6
|
data/.hound.yml
CHANGED
data/.travis.yml
CHANGED
data/NEWS.md
CHANGED
@@ -4,6 +4,18 @@ User-visible changes worth mentioning.
|
|
4
4
|
|
5
5
|
---
|
6
6
|
|
7
|
+
## 3.1.0
|
8
|
+
|
9
|
+
- [#736] Existing valid tokens are now reused in client_credentials flow
|
10
|
+
- [#749] Allow user to raise authorization error with custom messages.
|
11
|
+
Under `resource_owner_authenticator` block a user can
|
12
|
+
`raise Doorkeeper::Errors::DoorkeeperError.new('custom_message')`
|
13
|
+
- [#762] Check doesn’t abort the actual migration, so it runs
|
14
|
+
- [#722] `doorkeeper_forbidden_render_options` now supports returning a 404 by
|
15
|
+
specifying `respond_not_found_when_forbidden: true` in the
|
16
|
+
`doorkeeper_forbidden_render_options` method.
|
17
|
+
- [#734] Simplify and remove duplication in request strategy classes
|
18
|
+
|
7
19
|
## 3.0.1
|
8
20
|
|
9
21
|
- [#712] Wrap exchange of grant token for access token and access token refresh
|
data/README.md
CHANGED
@@ -14,10 +14,12 @@ functionality to your Rails or Grape application.
|
|
14
14
|
## Documentation valid for `master` branch
|
15
15
|
|
16
16
|
Please check the documentation for the version of doorkeeper you are using in:
|
17
|
-
https://github.com/doorkeeper-gem/doorkeeper/releases
|
17
|
+
https://github.com/doorkeeper-gem/doorkeeper/releases
|
18
18
|
|
19
19
|
## Table of Contents
|
20
20
|
|
21
|
+
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
22
|
+
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
21
23
|
- [Useful links](#useful-links)
|
22
24
|
- [Installation](#installation)
|
23
25
|
- [Configuration](#configuration)
|
@@ -39,12 +41,12 @@ https://github.com/doorkeeper-gem/doorkeeper/releases.
|
|
39
41
|
- [Contributing](#contributing)
|
40
42
|
- [Other resources](#other-resources)
|
41
43
|
- [Wiki](#wiki)
|
42
|
-
- [Live demo](#live-demo)
|
43
44
|
- [Screencast](#screencast)
|
44
45
|
- [Client applications](#client-applications)
|
45
46
|
- [Contributors](#contributors)
|
46
47
|
- [IETF Standards](#ietf-standards)
|
47
48
|
- [License](#license)
|
49
|
+
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
48
50
|
|
49
51
|
|
50
52
|
## Useful links
|
@@ -259,7 +261,7 @@ have both `:admin` and `:write` scopes.
|
|
259
261
|
|
260
262
|
### Custom Access Token Generator
|
261
263
|
|
262
|
-
By default a
|
264
|
+
By default a 128 bit access token will be generated. If you require a custom
|
263
265
|
token, such as [JWT](http://jwt.io), specify an object that responds to
|
264
266
|
`.generate(options = {})` and returns a string to be used as the token.
|
265
267
|
|
@@ -333,6 +335,8 @@ notes](https://github.com/doorkeeper-gem/doorkeeper/wiki/Migration-from-old-vers
|
|
333
335
|
and take a look at the
|
334
336
|
[changelog](https://github.com/doorkeeper-gem/doorkeeper/blob/master/NEWS.md).
|
335
337
|
|
338
|
+
Doorkeeper follows [semantic versioning](http://semver.org/).
|
339
|
+
|
336
340
|
## Development
|
337
341
|
|
338
342
|
To run the local engine server:
|
@@ -369,12 +373,6 @@ page](https://github.com/doorkeeper-gem/doorkeeper/wiki/Contributing).
|
|
369
373
|
You can find everything about doorkeeper in our [wiki
|
370
374
|
here](https://github.com/doorkeeper-gem/doorkeeper/wiki).
|
371
375
|
|
372
|
-
### Live demo
|
373
|
-
|
374
|
-
Check out this [live demo](http://doorkeeper-provider.herokuapp.com) hosted on
|
375
|
-
heroku. For more demos check out [the
|
376
|
-
wiki](https://github.com/doorkeeper-gem/doorkeeper/wiki/Example-Applications).
|
377
|
-
|
378
376
|
### Screencast
|
379
377
|
|
380
378
|
Check out this screencast from [railscasts.com](http://railscasts.com/): [#353
|
@@ -392,7 +390,7 @@ here](https://github.com/doorkeeper-gem/doorkeeper/wiki/Testing-your-provider-wi
|
|
392
390
|
### Contributors
|
393
391
|
|
394
392
|
Thanks to all our [awesome
|
395
|
-
contributors](https://github.com/doorkeeper-gem/doorkeeper/contributors)!
|
393
|
+
contributors](https://github.com/doorkeeper-gem/doorkeeper/graphs/contributors)!
|
396
394
|
|
397
395
|
|
398
396
|
### IETF Standards
|
@@ -404,4 +402,3 @@ contributors](https://github.com/doorkeeper-gem/doorkeeper/contributors)!
|
|
404
402
|
### License
|
405
403
|
|
406
404
|
MIT License. Copyright 2011 Applicake.
|
407
|
-
[http://applicake.com](http://applicake.com)
|
@@ -9,8 +9,8 @@
|
|
9
9
|
<%= csrf_meta_tags %>
|
10
10
|
</head>
|
11
11
|
<body>
|
12
|
-
<div class="navbar navbar-inverse navbar-
|
13
|
-
<div class="container">
|
12
|
+
<div class="navbar navbar-inverse navbar-static-top" role="navigation">
|
13
|
+
<div class="container-fluid">
|
14
14
|
<div class="navbar-header">
|
15
15
|
<%= link_to t('doorkeeper.layouts.admin.nav.oauth2_provider'), oauth_applications_path, class: 'navbar-brand' %>
|
16
16
|
</div>
|
@@ -18,6 +18,9 @@
|
|
18
18
|
<%= content_tag :li, class: "#{'active' if request.path == oauth_applications_path}" do %>
|
19
19
|
<%= link_to t('doorkeeper.layouts.admin.nav.applications'), oauth_applications_path %>
|
20
20
|
<% end %>
|
21
|
+
<%= content_tag :li do %>
|
22
|
+
<%= link_to 'Home', root_path %>
|
23
|
+
<% end %>
|
21
24
|
</ul>
|
22
25
|
</div>
|
23
26
|
</div>
|
data/doorkeeper.gemspec
CHANGED
@@ -18,7 +18,7 @@ Gem::Specification.new do |s|
|
|
18
18
|
|
19
19
|
s.add_dependency "railties", ">= 3.2"
|
20
20
|
|
21
|
-
s.add_development_dependency "rspec-rails", "~> 3.
|
21
|
+
s.add_development_dependency "rspec-rails", "~> 3.4.0"
|
22
22
|
s.add_development_dependency "capybara", "~> 2.3.0"
|
23
23
|
s.add_development_dependency "generator_spec", "~> 0.9.0"
|
24
24
|
s.add_development_dependency "factory_girl", "~> 4.5.0"
|
@@ -3,10 +3,9 @@ module Doorkeeper
|
|
3
3
|
class ClientCredentialsRequest
|
4
4
|
class Creator
|
5
5
|
def call(client, scopes, attributes = {})
|
6
|
-
AccessToken.
|
7
|
-
|
8
|
-
|
9
|
-
))
|
6
|
+
AccessToken.find_or_create_for(
|
7
|
+
client, nil, scopes, attributes[:expires_in],
|
8
|
+
attributes[:use_refresh_token])
|
10
9
|
end
|
11
10
|
end
|
12
11
|
end
|
@@ -2,7 +2,11 @@ module Doorkeeper
|
|
2
2
|
module OAuth
|
3
3
|
class Error < Struct.new(:name, :state)
|
4
4
|
def description
|
5
|
-
I18n.translate
|
5
|
+
I18n.translate(
|
6
|
+
name,
|
7
|
+
scope: [:doorkeeper, :errors, :messages],
|
8
|
+
default: :server_error
|
9
|
+
)
|
6
10
|
end
|
7
11
|
end
|
8
12
|
end
|
@@ -25,11 +25,12 @@ module Doorkeeper
|
|
25
25
|
Doorkeeper::Application.table_name
|
26
26
|
)
|
27
27
|
unless Doorkeeper::Application.new.attributes.include?("scopes")
|
28
|
-
|
28
|
+
migration_path = '../../../generators/doorkeeper/templates/add_scopes_to_oauth_applications.rb'
|
29
|
+
puts <<-MSG.squish
|
29
30
|
[doorkeeper] Missing column: `oauth_applications.scopes`.
|
30
|
-
|
31
|
-
&& rake db:migrate` to add it.
|
31
|
+
Create the following migration and run `rake db:migrate`.
|
32
32
|
MSG
|
33
|
+
puts File.read(File.expand_path(migration_path, __FILE__))
|
33
34
|
end
|
34
35
|
end
|
35
36
|
end
|
@@ -31,10 +31,12 @@ module Doorkeeper
|
|
31
31
|
|
32
32
|
def doorkeeper_render_error_with(error)
|
33
33
|
options = doorkeeper_render_options(error) || {}
|
34
|
+
status = doorkeeper_status_for_error(
|
35
|
+
error, options.delete(:respond_not_found_when_forbidden))
|
34
36
|
if options.blank?
|
35
|
-
head
|
37
|
+
head status
|
36
38
|
else
|
37
|
-
options[:status] =
|
39
|
+
options[:status] = status
|
38
40
|
options[:layout] = false if options[:layout].nil?
|
39
41
|
render options
|
40
42
|
end
|
@@ -56,6 +58,14 @@ module Doorkeeper
|
|
56
58
|
end
|
57
59
|
end
|
58
60
|
|
61
|
+
def doorkeeper_status_for_error(error, respond_not_found_when_forbidden)
|
62
|
+
if respond_not_found_when_forbidden && error.status == :forbidden
|
63
|
+
:not_found
|
64
|
+
else
|
65
|
+
error.status
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
59
69
|
def doorkeeper_invalid_token_response?
|
60
70
|
!doorkeeper_token || !doorkeeper_token.accessible?
|
61
71
|
end
|
data/lib/doorkeeper/request.rb
CHANGED
@@ -9,22 +9,32 @@ module Doorkeeper
|
|
9
9
|
module Request
|
10
10
|
module_function
|
11
11
|
|
12
|
-
def authorization_strategy(
|
13
|
-
get_strategy
|
12
|
+
def authorization_strategy(response_type)
|
13
|
+
get_strategy response_type, authorization_response_types
|
14
14
|
rescue NameError
|
15
15
|
raise Errors::InvalidAuthorizationStrategy
|
16
16
|
end
|
17
17
|
|
18
|
-
def token_strategy(
|
19
|
-
get_strategy
|
18
|
+
def token_strategy(grant_type)
|
19
|
+
get_strategy grant_type, token_grant_types
|
20
20
|
rescue NameError
|
21
21
|
raise Errors::InvalidTokenStrategy
|
22
22
|
end
|
23
23
|
|
24
|
-
def get_strategy(
|
25
|
-
fail Errors::MissingRequestStrategy unless
|
26
|
-
fail NameError unless available.include?(
|
27
|
-
"Doorkeeper::Request::#{
|
24
|
+
def get_strategy(grant_or_request_type, available)
|
25
|
+
fail Errors::MissingRequestStrategy unless grant_or_request_type.present?
|
26
|
+
fail NameError unless available.include?(grant_or_request_type.to_s)
|
27
|
+
"Doorkeeper::Request::#{grant_or_request_type.to_s.camelize}".constantize
|
28
28
|
end
|
29
|
+
|
30
|
+
def authorization_response_types
|
31
|
+
Doorkeeper.configuration.authorization_response_types
|
32
|
+
end
|
33
|
+
private_class_method :authorization_response_types
|
34
|
+
|
35
|
+
def token_grant_types
|
36
|
+
Doorkeeper.configuration.token_grant_types
|
37
|
+
end
|
38
|
+
private_class_method :token_grant_types
|
29
39
|
end
|
30
40
|
end
|
@@ -1,22 +1,17 @@
|
|
1
|
+
require 'doorkeeper/request/strategy'
|
2
|
+
|
1
3
|
module Doorkeeper
|
2
4
|
module Request
|
3
|
-
class AuthorizationCode
|
4
|
-
|
5
|
-
new(server.grant, server.client, server)
|
6
|
-
end
|
7
|
-
|
8
|
-
attr_accessor :grant, :client, :server
|
9
|
-
|
10
|
-
def initialize(grant, client, server)
|
11
|
-
@grant, @client, @server = grant, client, server
|
12
|
-
end
|
5
|
+
class AuthorizationCode < Strategy
|
6
|
+
delegate :grant, :client, :parameters, to: :server
|
13
7
|
|
14
8
|
def request
|
15
|
-
@request ||= OAuth::AuthorizationCodeRequest.new(
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
9
|
+
@request ||= OAuth::AuthorizationCodeRequest.new(
|
10
|
+
Doorkeeper.configuration,
|
11
|
+
grant,
|
12
|
+
client,
|
13
|
+
parameters
|
14
|
+
)
|
20
15
|
end
|
21
16
|
end
|
22
17
|
end
|
@@ -1,22 +1,16 @@
|
|
1
|
+
require 'doorkeeper/request/strategy'
|
2
|
+
|
1
3
|
module Doorkeeper
|
2
4
|
module Request
|
3
|
-
class ClientCredentials
|
4
|
-
|
5
|
-
new(server.client, server)
|
6
|
-
end
|
7
|
-
|
8
|
-
attr_accessor :client, :server
|
9
|
-
|
10
|
-
def initialize(client, server)
|
11
|
-
@client, @server = client, server
|
12
|
-
end
|
5
|
+
class ClientCredentials < Strategy
|
6
|
+
delegate :client, :parameters, to: :server
|
13
7
|
|
14
8
|
def request
|
15
|
-
@request ||= OAuth::ClientCredentialsRequest.new(
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
9
|
+
@request ||= OAuth::ClientCredentialsRequest.new(
|
10
|
+
Doorkeeper.configuration,
|
11
|
+
client,
|
12
|
+
parameters
|
13
|
+
)
|
20
14
|
end
|
21
15
|
end
|
22
16
|
end
|
@@ -1,22 +1,16 @@
|
|
1
|
+
require 'doorkeeper/request/strategy'
|
2
|
+
|
1
3
|
module Doorkeeper
|
2
4
|
module Request
|
3
|
-
class Code
|
4
|
-
|
5
|
-
new(server.context.send(:pre_auth), server)
|
6
|
-
end
|
7
|
-
|
8
|
-
attr_accessor :pre_auth, :server
|
5
|
+
class Code < Strategy
|
6
|
+
delegate :current_resource_owner, to: :server
|
9
7
|
|
10
|
-
def
|
11
|
-
|
8
|
+
def pre_auth
|
9
|
+
server.context.send(:pre_auth)
|
12
10
|
end
|
13
11
|
|
14
12
|
def request
|
15
|
-
@request ||= OAuth::CodeRequest.new(pre_auth,
|
16
|
-
end
|
17
|
-
|
18
|
-
def authorize
|
19
|
-
request.authorize
|
13
|
+
@request ||= OAuth::CodeRequest.new(pre_auth, current_resource_owner)
|
20
14
|
end
|
21
15
|
end
|
22
16
|
end
|
@@ -1,22 +1,17 @@
|
|
1
|
+
require 'doorkeeper/request/strategy'
|
2
|
+
|
1
3
|
module Doorkeeper
|
2
4
|
module Request
|
3
|
-
class Password
|
4
|
-
|
5
|
-
new(server.credentials, server.resource_owner, server)
|
6
|
-
end
|
7
|
-
|
8
|
-
attr_accessor :credentials, :resource_owner, :server
|
9
|
-
|
10
|
-
def initialize(credentials, resource_owner, server)
|
11
|
-
@credentials, @resource_owner, @server = credentials, resource_owner, server
|
12
|
-
end
|
5
|
+
class Password < Strategy
|
6
|
+
delegate :credentials, :resource_owner, :parameters, to: :server
|
13
7
|
|
14
8
|
def request
|
15
|
-
@request ||= OAuth::PasswordAccessTokenRequest.new(
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
9
|
+
@request ||= OAuth::PasswordAccessTokenRequest.new(
|
10
|
+
Doorkeeper.configuration,
|
11
|
+
credentials,
|
12
|
+
resource_owner,
|
13
|
+
parameters
|
14
|
+
)
|
20
15
|
end
|
21
16
|
end
|
22
17
|
end
|
@@ -1,22 +1,20 @@
|
|
1
|
+
require 'doorkeeper/request/strategy'
|
2
|
+
|
1
3
|
module Doorkeeper
|
2
4
|
module Request
|
3
|
-
class RefreshToken
|
4
|
-
|
5
|
-
new(server.current_refresh_token, server.credentials, server)
|
6
|
-
end
|
7
|
-
|
8
|
-
attr_accessor :refresh_token, :credentials, :server
|
5
|
+
class RefreshToken < Strategy
|
6
|
+
delegate :credentials, :parameters, to: :server
|
9
7
|
|
10
|
-
def
|
11
|
-
|
8
|
+
def refresh_token
|
9
|
+
server.current_refresh_token
|
12
10
|
end
|
13
11
|
|
14
12
|
def request
|
15
|
-
@request ||= OAuth::RefreshTokenRequest.new(
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
13
|
+
@request ||= OAuth::RefreshTokenRequest.new(
|
14
|
+
Doorkeeper.configuration,
|
15
|
+
refresh_token, credentials,
|
16
|
+
parameters
|
17
|
+
)
|
20
18
|
end
|
21
19
|
end
|
22
20
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Doorkeeper
|
2
|
+
module Request
|
3
|
+
class Strategy
|
4
|
+
attr_accessor :server
|
5
|
+
|
6
|
+
delegate :authorize, to: :request
|
7
|
+
|
8
|
+
def initialize(server)
|
9
|
+
self.server = server
|
10
|
+
end
|
11
|
+
|
12
|
+
def request
|
13
|
+
raise NotImplementedError, "request strategies must define #request"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -1,22 +1,16 @@
|
|
1
|
+
require 'doorkeeper/request/strategy'
|
2
|
+
|
1
3
|
module Doorkeeper
|
2
4
|
module Request
|
3
|
-
class Token
|
4
|
-
|
5
|
-
new(server.context.send(:pre_auth), server)
|
6
|
-
end
|
7
|
-
|
8
|
-
attr_accessor :pre_auth, :server
|
5
|
+
class Token < Strategy
|
6
|
+
delegate :current_resource_owner, to: :server
|
9
7
|
|
10
|
-
def
|
11
|
-
|
8
|
+
def pre_auth
|
9
|
+
server.context.send(:pre_auth)
|
12
10
|
end
|
13
11
|
|
14
12
|
def request
|
15
|
-
@request ||= OAuth::TokenRequest.new(pre_auth,
|
16
|
-
end
|
17
|
-
|
18
|
-
def authorize
|
19
|
-
request.authorize
|
13
|
+
@request ||= OAuth::TokenRequest.new(pre_auth, current_resource_owner)
|
20
14
|
end
|
21
15
|
end
|
22
16
|
end
|
data/lib/doorkeeper/server.rb
CHANGED
@@ -8,12 +8,12 @@ module Doorkeeper
|
|
8
8
|
|
9
9
|
def authorization_request(strategy)
|
10
10
|
klass = Request.authorization_strategy strategy
|
11
|
-
klass.
|
11
|
+
klass.new self
|
12
12
|
end
|
13
13
|
|
14
14
|
def token_request(strategy)
|
15
15
|
klass = Request.token_strategy strategy
|
16
|
-
klass.
|
16
|
+
klass.new self
|
17
17
|
end
|
18
18
|
|
19
19
|
# TODO: context should be the request
|
data/lib/doorkeeper/version.rb
CHANGED
@@ -165,7 +165,7 @@ describe 'doorkeeper authorize filter' do
|
|
165
165
|
end
|
166
166
|
end
|
167
167
|
|
168
|
-
it 'it renders a custom
|
168
|
+
it 'it renders a custom text response', token: :invalid do
|
169
169
|
get :index, access_token: token_string
|
170
170
|
expect(response.status).to eq 401
|
171
171
|
expect(response.content_type).to eq('text/html')
|
@@ -174,4 +174,98 @@ describe 'doorkeeper authorize filter' do
|
|
174
174
|
end
|
175
175
|
end
|
176
176
|
end
|
177
|
+
|
178
|
+
context 'when custom forbidden render options are configured' do
|
179
|
+
before do
|
180
|
+
expect(Doorkeeper::AccessToken).to receive(:by_token).with(token_string).and_return(token)
|
181
|
+
expect(token).to receive(:acceptable?).with([:write]).and_return(false)
|
182
|
+
end
|
183
|
+
|
184
|
+
after do
|
185
|
+
module ControllerActions
|
186
|
+
def doorkeeper_forbidden_render_options(*)
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
controller do
|
192
|
+
before_filter -> { doorkeeper_authorize! :write }
|
193
|
+
|
194
|
+
include ControllerActions
|
195
|
+
end
|
196
|
+
|
197
|
+
let(:token) do
|
198
|
+
double(Doorkeeper::AccessToken,
|
199
|
+
accessible?: true, scopes: ['public'], revoked?: false, expired?: false)
|
200
|
+
end
|
201
|
+
let(:token_string) { '1A2DUWE' }
|
202
|
+
|
203
|
+
context 'with a JSON custom render' do
|
204
|
+
before do
|
205
|
+
module ControllerActions
|
206
|
+
def doorkeeper_forbidden_render_options(*)
|
207
|
+
{ json: { error_message: 'Forbidden' } }
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
it 'renders a custom JSON response' do
|
213
|
+
get :index, access_token: token_string
|
214
|
+
expect(response.header).to_not include('WWW-Authenticate')
|
215
|
+
expect(response.content_type).to eq('application/json')
|
216
|
+
expect(response.status).to eq 403
|
217
|
+
parsed_body = JSON.parse(response.body)
|
218
|
+
expect(parsed_body).not_to be_nil
|
219
|
+
expect(parsed_body['error_message']).to match('Forbidden')
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
context 'with a status and JSON custom render' do
|
224
|
+
before do
|
225
|
+
module ControllerActions
|
226
|
+
def doorkeeper_forbidden_render_options(*)
|
227
|
+
{ json: { error_message: 'Not Found' },
|
228
|
+
respond_not_found_when_forbidden: true }
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
it 'overrides the default status code' do
|
234
|
+
get :index, access_token: token_string
|
235
|
+
expect(response.status).to eq 404
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
context 'with a text custom render' do
|
240
|
+
before do
|
241
|
+
module ControllerActions
|
242
|
+
def doorkeeper_forbidden_render_options(*)
|
243
|
+
{ text: 'Forbidden' }
|
244
|
+
end
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
it 'renders a custom status code and text response' do
|
249
|
+
get :index, access_token: token_string
|
250
|
+
expect(response.header).to_not include('WWW-Authenticate')
|
251
|
+
expect(response.status).to eq 403
|
252
|
+
expect(response.body).to eq('Forbidden')
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
context 'with a status and text custom render' do
|
257
|
+
before do
|
258
|
+
module ControllerActions
|
259
|
+
def doorkeeper_forbidden_render_options(*)
|
260
|
+
{ respond_not_found_when_forbidden: true, text: 'Not Found' }
|
261
|
+
end
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
it 'overrides the default status code' do
|
266
|
+
get :index, access_token: token_string
|
267
|
+
expect(response.status).to eq 404
|
268
|
+
end
|
269
|
+
end
|
270
|
+
end
|
177
271
|
end
|
@@ -31,6 +31,36 @@ describe Doorkeeper::TokensController do
|
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
+
describe 'when there is a failure due to a custom error' do
|
35
|
+
it 'returns the error response with a custom message' do
|
36
|
+
# I18n looks for `doorkeeper.errors.messages.custom_message` in locale files
|
37
|
+
custom_message = "my_message"
|
38
|
+
allow(I18n).to receive(:translate).
|
39
|
+
with(
|
40
|
+
custom_message,
|
41
|
+
hash_including(scope: [:doorkeeper, :errors, :messages]),
|
42
|
+
).
|
43
|
+
and_return('Authorization custom message')
|
44
|
+
|
45
|
+
doorkeeper_error = Doorkeeper::Errors::DoorkeeperError.new(custom_message)
|
46
|
+
|
47
|
+
strategy = double(:strategy)
|
48
|
+
request = double(token_request: strategy)
|
49
|
+
allow(strategy).to receive(:authorize).and_raise(doorkeeper_error)
|
50
|
+
allow(controller).to receive(:server).and_return(request)
|
51
|
+
|
52
|
+
post :create
|
53
|
+
|
54
|
+
expected_response_body = {
|
55
|
+
"error" => custom_message,
|
56
|
+
"error_description" => "Authorization custom message"
|
57
|
+
}
|
58
|
+
expect(response.status).to eq 401
|
59
|
+
expect(response.headers['WWW-Authenticate']).to match(/Bearer/)
|
60
|
+
expect(JSON.load(response.body)).to eq expected_response_body
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
34
64
|
describe 'when revoke authorization has failed' do
|
35
65
|
# http://tools.ietf.org/html/rfc7009#section-2.2
|
36
66
|
it 'returns no error response' do
|
@@ -11,8 +11,32 @@ class Doorkeeper::OAuth::ClientCredentialsRequest
|
|
11
11
|
end.to change { Doorkeeper::AccessToken.count }.by(1)
|
12
12
|
end
|
13
13
|
|
14
|
+
context "when reuse_access_token is true" do
|
15
|
+
it "returns the existing valid token" do
|
16
|
+
allow(Doorkeeper.configuration).to receive(:reuse_access_token).and_return(true)
|
17
|
+
existing_token = subject.call(client, scopes)
|
18
|
+
|
19
|
+
result = subject.call(client, scopes)
|
20
|
+
|
21
|
+
expect(Doorkeeper::AccessToken.count).to eq(1)
|
22
|
+
expect(result).to eq(existing_token)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context "when reuse_access_token is false" do
|
27
|
+
it "returns a new token" do
|
28
|
+
allow(Doorkeeper.configuration).to receive(:reuse_access_token).and_return(false)
|
29
|
+
existing_token = subject.call(client, scopes)
|
30
|
+
|
31
|
+
result = subject.call(client, scopes)
|
32
|
+
|
33
|
+
expect(Doorkeeper::AccessToken.count).to eq(2)
|
34
|
+
expect(result).not_to eq(existing_token)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
14
38
|
it 'returns false if creation fails' do
|
15
|
-
expect(Doorkeeper::AccessToken).to receive(:
|
39
|
+
expect(Doorkeeper::AccessToken).to receive(:find_or_create_for).and_return(false)
|
16
40
|
created = subject.call(client, scopes)
|
17
41
|
expect(created).to be_falsey
|
18
42
|
end
|
@@ -37,9 +37,9 @@ module Doorkeeper::OAuth
|
|
37
37
|
subject { ErrorResponse.new(name: :some_error, state: :some_state).body }
|
38
38
|
|
39
39
|
describe '#body' do
|
40
|
-
it {
|
41
|
-
it {
|
42
|
-
it {
|
40
|
+
it { expect(subject).to have_key(:error) }
|
41
|
+
it { expect(subject).to have_key(:error_description) }
|
42
|
+
it { expect(subject).to have_key(:state) }
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
@@ -47,15 +47,15 @@ module Doorkeeper::OAuth
|
|
47
47
|
let(:error_response) { ErrorResponse.new(name: :some_error, state: :some_state) }
|
48
48
|
subject { error_response.authenticate_info }
|
49
49
|
|
50
|
-
it {
|
51
|
-
it {
|
52
|
-
it {
|
50
|
+
it { expect(subject).to include("realm=\"#{error_response.realm}\"") }
|
51
|
+
it { expect(subject).to include("error=\"#{error_response.name}\"") }
|
52
|
+
it { expect(subject).to include("error_description=\"#{error_response.description}\"") }
|
53
53
|
end
|
54
54
|
|
55
55
|
describe '.headers' do
|
56
56
|
subject { ErrorResponse.new(name: :some_error, state: :some_state).headers }
|
57
57
|
|
58
|
-
it {
|
58
|
+
it { expect(subject).to include 'WWW-Authenticate' }
|
59
59
|
end
|
60
60
|
end
|
61
61
|
end
|
@@ -4,15 +4,19 @@ require 'doorkeeper/oauth/error'
|
|
4
4
|
|
5
5
|
module Doorkeeper::OAuth
|
6
6
|
describe Error do
|
7
|
-
subject { Error.new(:some_error, :some_state) }
|
7
|
+
subject(:error) { Error.new(:some_error, :some_state) }
|
8
8
|
|
9
|
-
it {
|
10
|
-
it {
|
9
|
+
it { expect(subject).to respond_to(:name) }
|
10
|
+
it { expect(subject).to respond_to(:state) }
|
11
11
|
|
12
12
|
describe :description do
|
13
13
|
it 'is translated from translation messages' do
|
14
|
-
expect(I18n).to receive(:translate).with(
|
15
|
-
|
14
|
+
expect(I18n).to receive(:translate).with(
|
15
|
+
:some_error,
|
16
|
+
scope: [:doorkeeper, :errors, :messages],
|
17
|
+
default: :server_error
|
18
|
+
)
|
19
|
+
error.description
|
16
20
|
end
|
17
21
|
end
|
18
22
|
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'doorkeeper/request/strategy'
|
3
|
+
|
4
|
+
module Doorkeeper
|
5
|
+
module Request
|
6
|
+
describe Strategy do
|
7
|
+
let(:server) { double }
|
8
|
+
subject(:strategy) { Strategy.new(server) }
|
9
|
+
|
10
|
+
describe :initialize do
|
11
|
+
it "sets the server attribute" do
|
12
|
+
expect(strategy.server).to eq server
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe :request do
|
17
|
+
it "requires an implementation" do
|
18
|
+
expect { strategy.request }.to raise_exception NotImplementedError
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "a sample Strategy subclass" do
|
23
|
+
let(:fake_request) { double }
|
24
|
+
|
25
|
+
let(:strategy_class) do
|
26
|
+
subclass = Class.new(Strategy) do
|
27
|
+
class << self
|
28
|
+
attr_accessor :fake_request
|
29
|
+
end
|
30
|
+
|
31
|
+
def request
|
32
|
+
self.class.fake_request
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
subclass.fake_request = fake_request
|
37
|
+
subclass
|
38
|
+
end
|
39
|
+
|
40
|
+
subject(:strategy) { strategy_class.new(server) }
|
41
|
+
|
42
|
+
it "provides a request implementation" do
|
43
|
+
expect(strategy.request).to eq fake_request
|
44
|
+
end
|
45
|
+
|
46
|
+
it "authorizes the request" do
|
47
|
+
expect(fake_request).to receive :authorize
|
48
|
+
strategy.authorize
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/spec/lib/server_spec.rb
CHANGED
@@ -45,7 +45,7 @@ describe Doorkeeper::Server do
|
|
45
45
|
|
46
46
|
it 'builds the request with selected strategy' do
|
47
47
|
stub_const 'Doorkeeper::Request::Code', fake_class
|
48
|
-
expect(fake_class).to receive(:
|
48
|
+
expect(fake_class).to receive(:new).with(subject)
|
49
49
|
subject.authorization_request :code
|
50
50
|
end
|
51
51
|
end
|
@@ -3,7 +3,7 @@ require 'spec_helper_integration'
|
|
3
3
|
describe Doorkeeper::AccessGrant do
|
4
4
|
subject { FactoryGirl.build(:access_grant) }
|
5
5
|
|
6
|
-
it {
|
6
|
+
it { expect(subject).to be_valid }
|
7
7
|
|
8
8
|
it_behaves_like 'an accessible token'
|
9
9
|
it_behaves_like 'a revocable token'
|
@@ -14,23 +14,23 @@ describe Doorkeeper::AccessGrant do
|
|
14
14
|
describe 'validations' do
|
15
15
|
it 'is invalid without resource_owner_id' do
|
16
16
|
subject.resource_owner_id = nil
|
17
|
-
|
17
|
+
expect(subject).not_to be_valid
|
18
18
|
end
|
19
19
|
|
20
20
|
it 'is invalid without application_id' do
|
21
21
|
subject.application_id = nil
|
22
|
-
|
22
|
+
expect(subject).not_to be_valid
|
23
23
|
end
|
24
24
|
|
25
25
|
it 'is invalid without token' do
|
26
26
|
subject.save
|
27
27
|
subject.token = nil
|
28
|
-
|
28
|
+
expect(subject).not_to be_valid
|
29
29
|
end
|
30
30
|
|
31
31
|
it 'is invalid without expires_in' do
|
32
32
|
subject.expires_in = nil
|
33
|
-
|
33
|
+
expect(subject).not_to be_valid
|
34
34
|
end
|
35
35
|
end
|
36
36
|
end
|
@@ -4,7 +4,7 @@ module Doorkeeper
|
|
4
4
|
describe AccessToken do
|
5
5
|
subject { FactoryGirl.build(:access_token) }
|
6
6
|
|
7
|
-
it {
|
7
|
+
it { expect(subject).to be_valid }
|
8
8
|
|
9
9
|
it_behaves_like 'an accessible token'
|
10
10
|
it_behaves_like 'a revocable token'
|
@@ -141,7 +141,7 @@ module Doorkeeper
|
|
141
141
|
it 'is valid without resource_owner_id' do
|
142
142
|
# For client credentials flow
|
143
143
|
subject.resource_owner_id = nil
|
144
|
-
|
144
|
+
expect(subject).to be_valid
|
145
145
|
end
|
146
146
|
end
|
147
147
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: doorkeeper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.0
|
4
|
+
version: 3.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Felipe Elias Philipp
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2015-
|
12
|
+
date: 2015-12-23 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: railties
|
@@ -31,14 +31,14 @@ dependencies:
|
|
31
31
|
requirements:
|
32
32
|
- - "~>"
|
33
33
|
- !ruby/object:Gem::Version
|
34
|
-
version: 3.
|
34
|
+
version: 3.4.0
|
35
35
|
type: :development
|
36
36
|
prerelease: false
|
37
37
|
version_requirements: !ruby/object:Gem::Requirement
|
38
38
|
requirements:
|
39
39
|
- - "~>"
|
40
40
|
- !ruby/object:Gem::Version
|
41
|
-
version: 3.
|
41
|
+
version: 3.4.0
|
42
42
|
- !ruby/object:Gem::Dependency
|
43
43
|
name: capybara
|
44
44
|
requirement: !ruby/object:Gem::Requirement
|
@@ -210,6 +210,7 @@ files:
|
|
210
210
|
- lib/doorkeeper/request/code.rb
|
211
211
|
- lib/doorkeeper/request/password.rb
|
212
212
|
- lib/doorkeeper/request/refresh_token.rb
|
213
|
+
- lib/doorkeeper/request/strategy.rb
|
213
214
|
- lib/doorkeeper/request/token.rb
|
214
215
|
- lib/doorkeeper/server.rb
|
215
216
|
- lib/doorkeeper/validations.rb
|
@@ -303,6 +304,7 @@ files:
|
|
303
304
|
- spec/lib/oauth/token_request_spec.rb
|
304
305
|
- spec/lib/oauth/token_response_spec.rb
|
305
306
|
- spec/lib/oauth/token_spec.rb
|
307
|
+
- spec/lib/request/strategy_spec.rb
|
306
308
|
- spec/lib/server_spec.rb
|
307
309
|
- spec/models/doorkeeper/access_grant_spec.rb
|
308
310
|
- spec/models/doorkeeper/access_token_spec.rb
|
@@ -359,7 +361,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
359
361
|
version: '0'
|
360
362
|
requirements: []
|
361
363
|
rubyforge_project:
|
362
|
-
rubygems_version: 2.
|
364
|
+
rubygems_version: 2.5.1
|
363
365
|
signing_key:
|
364
366
|
specification_version: 4
|
365
367
|
summary: OAuth 2 provider for Rails and Grape
|
@@ -443,6 +445,7 @@ test_files:
|
|
443
445
|
- spec/lib/oauth/token_request_spec.rb
|
444
446
|
- spec/lib/oauth/token_response_spec.rb
|
445
447
|
- spec/lib/oauth/token_spec.rb
|
448
|
+
- spec/lib/request/strategy_spec.rb
|
446
449
|
- spec/lib/server_spec.rb
|
447
450
|
- spec/models/doorkeeper/access_grant_spec.rb
|
448
451
|
- spec/models/doorkeeper/access_token_spec.rb
|