rack-oauth2 1.10.1 → 1.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e09ccf53817af77d1e714e25e20e9b76fd63de080fb1f3d9617fff3aef126a32
4
- data.tar.gz: '088a7815b796f5c05ac3445ee39cc997bcc20964a66c1d4fc7a5c3906e27eb36'
3
+ metadata.gz: de77a3afabd5ae9ec958c5799970a99a5576cb727b27c80020d1199c986f25f1
4
+ data.tar.gz: 6225a40427c3bb882890f5d6e54407b1a80bd56f5b74f4278122678a2206ae29
5
5
  SHA512:
6
- metadata.gz: b261cc8b398a4b02797b581d455307bc46f0f248990c4fef7b0286eb7eb2e191568ecb5c8c0b6123ef5cd43f5f517c0980bf405b9b3efd0874c29b8e97218696
7
- data.tar.gz: adf42215042112d7577d76b35437fa2b2b45f8a259a896c5621790a7603053e6ea1ada28ba2d27330e5338689061002cc870969a8895ba040349faea5ec7340b
6
+ metadata.gz: ce7ecffd6ee6aae2296c2d20a1353bfb96cdee665b1d06961859f2e3e1922822cb481e3791d7fefc6a53644ce6d150f7ec6eb63880b6112e66b0a9cd64f27fdf
7
+ data.tar.gz: 80c3816f4a0e1649c2f7f268fbde3583eb435c2978e155de963f9354cf6e2330778c22b80e15757a592042b800a5cf1fca9466557735aef3d90a59b77db2fd2b
data/.travis.yml CHANGED
@@ -2,6 +2,7 @@ before_install:
2
2
  - gem install bundler
3
3
 
4
4
  rvm:
5
- - 2.3.6
6
- - 2.4.3
7
- - 2.5.0
5
+ - 2.5.8
6
+ - 2.6.6
7
+ - 2.7.2
8
+ - 3.0.0
data/README.rdoc CHANGED
@@ -28,17 +28,11 @@ http://tools.ietf.org/html/draft-ietf-oauth-v2-http-mac-01
28
28
 
29
29
  === Bearer
30
30
 
31
- Running on Heroku
32
- https://rack-oauth2-sample.heroku.com
33
-
34
31
  Source on GitHub
35
32
  https://github.com/nov/rack-oauth2-sample
36
33
 
37
34
  === MAC
38
35
 
39
- Running on Heroku
40
- https://rack-oauth2-sample-mac.heroku.com
41
-
42
36
  Source on GitHub
43
37
  https://github.com/nov/rack-oauth2-sample-mac
44
38
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.10.1
1
+ 1.19.0
@@ -16,12 +16,12 @@ module Rack
16
16
  end
17
17
 
18
18
  def authorization_uri(params = {})
19
+ params[:redirect_uri] ||= self.redirect_uri
19
20
  params[:response_type] ||= :code
20
21
  params[:response_type] = Array(params[:response_type]).join(' ')
21
22
  params[:scope] = Array(params[:scope]).join(' ')
22
23
  Util.redirect_uri absolute_uri_for(authorization_endpoint), :query, params.merge(
23
- client_id: self.identifier,
24
- redirect_uri: self.redirect_uri
24
+ client_id: self.identifier
25
25
  )
26
26
  end
27
27
 
@@ -73,16 +73,24 @@ module Rack
73
73
  http_client = Rack::OAuth2.http_client
74
74
 
75
75
  # NOTE:
76
- # Using Array#estract_options! for backward compatibility.
76
+ # Using Array#extract_options! for backward compatibility.
77
77
  # Until v1.0.5, the first argument was 'client_auth_method' in scalar.
78
78
  options = args.extract_options!
79
- client_auth_method = args.first || options.delete(:client_auth_method) || :basic
79
+ client_auth_method = args.first || options.delete(:client_auth_method).try(:to_sym) || :basic
80
80
 
81
81
  params[:scope] = Array(options.delete(:scope)).join(' ') if options[:scope].present?
82
82
  params.merge! options
83
83
 
84
84
  case client_auth_method
85
85
  when :basic
86
+ cred = Base64.strict_encode64 [
87
+ Util.www_form_url_encode(identifier),
88
+ Util.www_form_url_encode(secret)
89
+ ].join(':')
90
+ headers.merge!(
91
+ 'Authorization' => "Basic #{cred}"
92
+ )
93
+ when :basic_without_www_form_urlencode
86
94
  cred = ["#{identifier}:#{secret}"].pack('m').tr("\n", '')
87
95
  headers.merge!(
88
96
  'Authorization' => "Basic #{cred}"
@@ -42,6 +42,7 @@ module Rack
42
42
 
43
43
  class Unauthorized < Error
44
44
  def initialize(error = :unauthorized, description = nil, options = {})
45
+ @skip_www_authenticate = options[:skip_www_authenticate]
45
46
  super 401, error, description, options
46
47
  end
47
48
  end
@@ -5,7 +5,7 @@ module Rack
5
5
  module ResponseExt
6
6
  def redirect?
7
7
  ensure_finish do
8
- @response.redirect?
8
+ super
9
9
  end
10
10
  end
11
11
 
@@ -17,7 +17,7 @@ module Rack
17
17
 
18
18
  def json
19
19
  ensure_finish do
20
- @response.body
20
+ @body
21
21
  end
22
22
  end
23
23
 
@@ -39,7 +39,7 @@ module Rack
39
39
  end
40
40
 
41
41
  def ensure_finish
42
- @status, @header, @response = finish unless finished?
42
+ @status, @header, @body = finish unless finished?
43
43
  yield
44
44
  end
45
45
  end
@@ -8,7 +8,9 @@ module Rack
8
8
  class Unauthorized < Abstract::Unauthorized
9
9
  def finish
10
10
  super do |response|
11
- response.header['WWW-Authenticate'] = 'Basic realm="OAuth2 Token Endpoint"'
11
+ unless @skip_www_authenticate
12
+ response.header['WWW-Authenticate'] = 'Basic realm="OAuth2 Token Endpoint"'
13
+ end
12
14
  end
13
15
  end
14
16
  end
@@ -44,16 +44,27 @@ module Rack
44
44
 
45
45
  class Request < Abstract::Request
46
46
  attr_required :grant_type
47
- attr_optional :client_secret
47
+ attr_optional :client_secret, :client_assertion, :client_assertion_type
48
48
 
49
49
  def initialize(env)
50
50
  auth = Rack::Auth::Basic::Request.new(env)
51
51
  if auth.provided? && auth.basic?
52
- @client_id, @client_secret = auth.credentials
52
+ @client_id, @client_secret = auth.credentials.map do |cred|
53
+ Util.www_form_url_decode cred
54
+ end
53
55
  super
54
56
  else
55
57
  super
56
58
  @client_secret = params['client_secret']
59
+ @client_assertion = params['client_assertion']
60
+ @client_assertion_type = params['client_assertion_type']
61
+ if client_assertion.present? && client_assertion_type == URN::ClientAssertionType::JWT_BEARER
62
+ require 'json/jwt'
63
+ @client_id = JSON::JWT.decode(
64
+ client_assertion,
65
+ :skip_verification
66
+ )[:sub] rescue nil
67
+ end
57
68
  end
58
69
  @grant_type = params['grant_type'].to_s
59
70
  end
@@ -3,14 +3,14 @@ module Rack
3
3
  module URN
4
4
  module TokenType
5
5
  JWT = 'urn:ietf:params:oauth:token-type:jwt' # RFC7519
6
- ACCESS_TOKEN = 'urn:ietf:params:oauth:token-type:access-token' # draft-ietf-oauth-token-exchange
7
- REFRESH_TOKEN = 'urn:ietf:params:oauth:token-type:refresh-token' # draft-ietf-oauth-token-exchange
6
+ ACCESS_TOKEN = 'urn:ietf:params:oauth:token-type:access_token' # RFC8693
7
+ REFRESH_TOKEN = 'urn:ietf:params:oauth:token-type:refresh_token' # RFC8693
8
8
  end
9
9
 
10
10
  module GrantType
11
11
  JWT_BEARER = 'urn:ietf:params:oauth:grant-type:jwt-bearer' # RFC7523
12
12
  SAML2_BEARER = 'urn:ietf:params:oauth:grant-type:saml2-bearer' # RFC7522
13
- TOKEN_EXCHANGE = 'urn:ietf:params:oauth:grant-type:token-exchange' # draft-ietf-oauth-token-exchange
13
+ TOKEN_EXCHANGE = 'urn:ietf:params:oauth:grant-type:token-exchange' # RFC8693
14
14
  end
15
15
 
16
16
  module ClientAssertionType
@@ -4,8 +4,12 @@ module Rack
4
4
  module OAuth2
5
5
  module Util
6
6
  class << self
7
- def rfc3986_encode(text)
8
- URI.encode(text, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
7
+ def www_form_url_encode(text)
8
+ URI.encode_www_form_component(text)
9
+ end
10
+
11
+ def www_form_url_decode(text)
12
+ URI.decode_www_form_component(text)
9
13
  end
10
14
 
11
15
  def base64_encode(text)
@@ -35,11 +39,12 @@ module Rack
35
39
 
36
40
  def redirect_uri(base_uri, location, params)
37
41
  redirect_uri = parse_uri base_uri
42
+ encoded_response_params = Util.compact_hash(params).to_query.gsub('+', '%20')
38
43
  case location
39
44
  when :query
40
- redirect_uri.query = [redirect_uri.query, Util.compact_hash(params).to_query].compact.join('&')
45
+ redirect_uri.query = [redirect_uri.query, encoded_response_params].compact.join('&')
41
46
  when :fragment
42
- redirect_uri.fragment = Util.compact_hash(params).to_query
47
+ redirect_uri.fragment = encoded_response_params
43
48
  end
44
49
  redirect_uri.to_s
45
50
  end
@@ -59,4 +64,4 @@ module Rack
59
64
  end
60
65
  end
61
66
  end
62
- end
67
+ end
data/lib/rack/oauth2.rb CHANGED
@@ -43,6 +43,11 @@ module Rack
43
43
  _http_client_ = HTTPClient.new(
44
44
  agent_name: agent_name
45
45
  )
46
+
47
+ # NOTE: httpclient gem seems stopped maintaining root certtificate set, use OS default.
48
+ _http_client_.ssl_config.clear_cert_store
49
+ _http_client_.ssl_config.cert_store.set_default_paths
50
+
46
51
  http_config.try(:call, _http_client_)
47
52
  local_http_config.try(:call, _http_client_) unless local_http_config.nil?
48
53
  _http_client_.request_filter << Debugger::RequestFilter.new if debugging?
data/rack-oauth2.gemspec CHANGED
@@ -13,7 +13,7 @@ Gem::Specification.new do |s|
13
13
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
14
14
  s.files = `git ls-files`.split("\n")
15
15
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
- s.add_runtime_dependency 'rack'
16
+ s.add_runtime_dependency 'rack', '>= 2.1.0'
17
17
  s.add_runtime_dependency 'httpclient'
18
18
  s.add_runtime_dependency 'activesupport'
19
19
  s.add_runtime_dependency 'attr_required'
@@ -1,10 +1,12 @@
1
1
  require 'spec_helper.rb'
2
2
 
3
3
  describe Rack::OAuth2::Client do
4
+ let(:client_id) { 'client_id' }
5
+ let(:client_secret) { 'client_secret' }
4
6
  let :client do
5
7
  Rack::OAuth2::Client.new(
6
- identifier: 'client_id',
7
- secret: 'client_secret',
8
+ identifier: client_id,
9
+ secret: client_secret,
8
10
  host: 'server.example.com',
9
11
  redirect_uri: 'https://client.example.com/callback'
10
12
  )
@@ -49,12 +51,12 @@ describe Rack::OAuth2::Client do
49
51
 
50
52
  context 'when response_type is an Array' do
51
53
  subject { client.authorization_uri(response_type: [:token, :code]) }
52
- it { should include 'response_type=token+code' }
54
+ it { should include 'response_type=token%20code' }
53
55
  end
54
56
 
55
57
  context 'when scope is given' do
56
58
  subject { client.authorization_uri(scope: [:scope1, :scope2]) }
57
- it { should include 'scope=scope1+scope2' }
59
+ it { should include 'scope=scope1%20scope2' }
58
60
  end
59
61
  end
60
62
 
@@ -97,6 +99,42 @@ describe Rack::OAuth2::Client do
97
99
  client.access_token!
98
100
  end
99
101
 
102
+ context 'when Basic auth method is used' do
103
+ context 'when client_id is a url' do
104
+ let(:client_id) { 'https://client.example.com'}
105
+
106
+ it 'should be encoded in "application/x-www-form-urlencoded"' do
107
+ mock_response(
108
+ :post,
109
+ 'https://server.example.com/oauth2/token',
110
+ 'tokens/bearer.json',
111
+ request_header: {
112
+ 'Authorization' => 'Basic aHR0cHMlM0ElMkYlMkZjbGllbnQuZXhhbXBsZS5jb206Y2xpZW50X3NlY3JldA=='
113
+ }
114
+ )
115
+ client.access_token!
116
+ end
117
+ end
118
+ end
119
+
120
+ context 'when basic_without_www_form_urlencode method is used' do
121
+ context 'when client_id is a url' do
122
+ let(:client_id) { 'https://client.example.com'}
123
+
124
+ it 'should be encoded in "application/x-www-form-urlencoded"' do
125
+ mock_response(
126
+ :post,
127
+ 'https://server.example.com/oauth2/token',
128
+ 'tokens/bearer.json',
129
+ request_header: {
130
+ 'Authorization' => 'Basic aHR0cHM6Ly9jbGllbnQuZXhhbXBsZS5jb206Y2xpZW50X3NlY3JldA=='
131
+ }
132
+ )
133
+ client.access_token! :basic_without_www_form_urlencode
134
+ end
135
+ end
136
+ end
137
+
100
138
  context 'when jwt_bearer auth method specified' do
101
139
  context 'when client_secret is given' do
102
140
  it 'should be JWT bearer client assertion w/ auto-generated HS256-signed JWT assertion' do
@@ -51,7 +51,7 @@ describe Rack::OAuth2::Server::Authorize::Code do
51
51
  error: :access_denied,
52
52
  error_description: Rack::OAuth2::Server::Authorize::ErrorMethods::DEFAULT_DESCRIPTION[:access_denied]
53
53
  }
54
- response.location.should == "#{redirect_uri}?#{error_message.to_query}&state=state"
54
+ response.location.should == "#{redirect_uri}?#{error_message.to_query.gsub('+', '%20')}&state=state"
55
55
  end
56
56
  end
57
57
  end
@@ -54,7 +54,7 @@ describe Rack::OAuth2::Server::Authorize::Extension::CodeAndToken do
54
54
  error: :access_denied,
55
55
  error_description: Rack::OAuth2::Server::Authorize::ErrorMethods::DEFAULT_DESCRIPTION[:access_denied]
56
56
  }
57
- response.location.should == "#{redirect_uri}##{error_message.to_query}"
57
+ response.location.should == "#{redirect_uri}##{error_message.to_query.gsub('+', '%20')}"
58
58
  end
59
59
  end
60
60
  end
@@ -67,7 +67,7 @@ describe Rack::OAuth2::Server::Authorize::Token do
67
67
  error: :access_denied,
68
68
  error_description: Rack::OAuth2::Server::Authorize::ErrorMethods::DEFAULT_DESCRIPTION[:access_denied]
69
69
  }
70
- response.location.should == "#{redirect_uri}##{error_message.to_query}&state=state"
70
+ response.location.should == "#{redirect_uri}##{error_message.to_query.gsub('+', '%20')}&state=state"
71
71
  end
72
72
  end
73
73
  end
@@ -10,7 +10,7 @@ describe Rack::OAuth2::Server::Resource::BadRequest do
10
10
  status, header, response = error.finish
11
11
  status.should == 400
12
12
  header['Content-Type'].should == 'application/json'
13
- response.body.should == ['{"error":"invalid_request"}']
13
+ response.should == ['{"error":"invalid_request"}']
14
14
  end
15
15
  end
16
16
  end
@@ -44,7 +44,7 @@ describe Rack::OAuth2::Server::Resource::Unauthorized do
44
44
  status.should == 401
45
45
  header['Content-Type'].should == 'application/json'
46
46
  header['WWW-Authenticate'].should == "Scheme realm=\"#{realm}\", error=\"invalid_token\""
47
- response.body.should == ['{"error":"invalid_token"}']
47
+ response.should == ['{"error":"invalid_token"}']
48
48
  end
49
49
 
50
50
  context 'when error_code is not invalid_token' do
@@ -53,7 +53,7 @@ describe Rack::OAuth2::Server::Resource::Unauthorized do
53
53
  it 'should have error_code in body but not in WWW-Authenticate header' do
54
54
  status, header, response = error_with_scheme.finish
55
55
  header['WWW-Authenticate'].should == "Scheme realm=\"#{realm}\""
56
- response.body.first.should include '"error":"something"'
56
+ response.first.should include '"error":"something"'
57
57
  end
58
58
  end
59
59
 
@@ -63,7 +63,7 @@ describe Rack::OAuth2::Server::Resource::Unauthorized do
63
63
  it 'should have error_code in body but not in WWW-Authenticate header' do
64
64
  status, header, response = error_with_scheme.finish
65
65
  header['WWW-Authenticate'].should == "Scheme realm=\"#{realm}\""
66
- response.body.first.should == '{"error":"unauthorized"}'
66
+ response.first.should == '{"error":"unauthorized"}'
67
67
  end
68
68
  end
69
69
 
@@ -74,7 +74,7 @@ describe Rack::OAuth2::Server::Resource::Unauthorized do
74
74
  it 'should use given realm' do
75
75
  status, header, response = error_with_scheme.finish
76
76
  header['WWW-Authenticate'].should == "Scheme realm=\"#{realm}\""
77
- response.body.first.should include '"error":"something"'
77
+ response.first.should include '"error":"something"'
78
78
  end
79
79
  end
80
80
  end
@@ -91,7 +91,7 @@ describe Rack::OAuth2::Server::Resource::Forbidden do
91
91
  status, header, response = error.finish
92
92
  status.should == 403
93
93
  header['Content-Type'].should == 'application/json'
94
- response.body.should == ['{"error":"insufficient_scope"}']
94
+ response.should == ['{"error":"insufficient_scope"}']
95
95
  end
96
96
  end
97
97
 
@@ -100,7 +100,7 @@ describe Rack::OAuth2::Server::Resource::Forbidden do
100
100
 
101
101
  it 'should have blank WWW-Authenticate header' do
102
102
  status, header, response = error.finish
103
- response.body.first.should include '"scope":"scope1 scope2"'
103
+ response.first.should include '"scope":"scope1 scope2"'
104
104
  end
105
105
  end
106
106
  end
@@ -4,14 +4,19 @@ describe Rack::OAuth2::Server::Token::ClientCredentials do
4
4
  let(:request) { Rack::MockRequest.new app }
5
5
  let(:app) do
6
6
  Rack::OAuth2::Server::Token.new do |request, response|
7
+ unless request.client_id == client_id && request.client_secret == client_secret
8
+ request.invalid_client!
9
+ end
7
10
  response.access_token = Rack::OAuth2::AccessToken::Bearer.new(access_token: 'access_token')
8
11
  end
9
12
  end
13
+ let(:client_id) { 'client_id '}
14
+ let(:client_secret) { 'client_secret' }
10
15
  let(:params) do
11
16
  {
12
17
  grant_type: 'client_credentials',
13
- client_id: 'client_id',
14
- client_secret: 'client_secret'
18
+ client_id: client_id,
19
+ client_secret: client_secret
15
20
  }
16
21
  end
17
22
  subject { request.post('/', params: params) }
@@ -20,4 +25,29 @@ describe Rack::OAuth2::Server::Token::ClientCredentials do
20
25
  its(:content_type) { should == 'application/json' }
21
26
  its(:body) { should include '"access_token":"access_token"' }
22
27
  its(:body) { should include '"token_type":"bearer"' }
28
+
29
+ context 'basic auth' do
30
+ let(:params) do
31
+ { grant_type: 'client_credentials' }
32
+ end
33
+ let(:encoded_creds) do
34
+ Base64.strict_encode64([
35
+ Rack::OAuth2::Util.www_form_url_encode(client_id),
36
+ Rack::OAuth2::Util.www_form_url_encode(client_secret)
37
+ ].join(':'))
38
+ end
39
+ subject do
40
+ request.post('/',
41
+ {params: params, 'HTTP_AUTHORIZATION' => "Basic #{encoded_creds}"})
42
+ end
43
+
44
+ its(:status) { should == 200 }
45
+
46
+ context 'compliance with RFC6749 sec 2.3.1' do
47
+ let(:client_id) { 'client: yes/please!' }
48
+ let(:client_secret) { 'terrible:secret:of:space' }
49
+
50
+ its(:status) { should == 200 }
51
+ end
52
+ end
23
53
  end
@@ -10,7 +10,7 @@ describe Rack::OAuth2::Server::Token::BadRequest do
10
10
  status, header, response = error.finish
11
11
  status.should == 400
12
12
  header['Content-Type'].should == 'application/json'
13
- response.body.should == ['{"error":"invalid_request"}']
13
+ response.should == ['{"error":"invalid_request"}']
14
14
  end
15
15
  end
16
16
  end
@@ -26,7 +26,7 @@ describe Rack::OAuth2::Server::Token::Unauthorized do
26
26
  status.should == 401
27
27
  header['Content-Type'].should == 'application/json'
28
28
  header['WWW-Authenticate'].should == 'Basic realm="OAuth2 Token Endpoint"'
29
- response.body.should == ['{"error":"invalid_request"}']
29
+ response.should == ['{"error":"invalid_request"}']
30
30
  end
31
31
  end
32
32
  end
@@ -74,4 +74,4 @@ describe Rack::OAuth2::Server::Token::ErrorMethods do
74
74
  end
75
75
  end
76
76
  end
77
- end
77
+ end
@@ -30,7 +30,7 @@ describe Rack::OAuth2::Server::Token do
30
30
  it 'should fail with unsupported_grant_type' do
31
31
  status, header, response = app.call(env)
32
32
  status.should == 400
33
- response.body.first.should include '"error":"invalid_request"'
33
+ response.first.should include '"error":"invalid_request"'
34
34
  end
35
35
  end
36
36
 
@@ -71,6 +71,60 @@ describe Rack::OAuth2::Server::Token do
71
71
  end
72
72
  end
73
73
 
74
+ context 'when client_id is given via JWT client assertion' do
75
+ before do
76
+ require 'json/jwt'
77
+ params[:client_assertion] = JSON::JWT.new(
78
+ sub: params[:client_id]
79
+ # NOTE: actual client_assertion should have more claims.
80
+ ).sign('client_secret').to_s
81
+ params[:client_assertion_type] = Rack::OAuth2::URN::ClientAssertionType::JWT_BEARER
82
+ params.delete(:client_id)
83
+ end
84
+
85
+ context 'when client_assertion is invalid JWT' do
86
+ before do
87
+ params[:client_assertion] = 'invalid-jwt'
88
+ end
89
+ its(:status) { should == 400 }
90
+ its(:content_type) { should == 'application/json' }
91
+ its(:body) { should include '"error":"invalid_request"' }
92
+ end
93
+
94
+ context 'when client_assertion_type is missing' do
95
+ before do
96
+ params.delete(:client_assertion_type)
97
+ end
98
+ its(:status) { should == 400 }
99
+ its(:content_type) { should == 'application/json' }
100
+ its(:body) { should include '"error":"invalid_request"' }
101
+ end
102
+
103
+ context 'when client_assertion_type is unknown' do
104
+ before do
105
+ params[:client_assertion_type] = 'unknown'
106
+ end
107
+ its(:status) { should == 400 }
108
+ its(:content_type) { should == 'application/json' }
109
+ its(:body) { should include '"error":"invalid_request"' }
110
+ end
111
+
112
+ context 'when client_assertion issuer is different from client_id' do
113
+ before do
114
+ params[:client_id] = 'another_client_id'
115
+ end
116
+ its(:status) { should == 400 }
117
+ its(:content_type) { should == 'application/json' }
118
+ its(:body) { should include '"error":"invalid_request"' }
119
+ end
120
+
121
+ context 'otherwise' do
122
+ its(:status) { should == 200 }
123
+ its(:content_type) { should == 'application/json' }
124
+ its(:body) { should include '"access_token":"access_token"' }
125
+ end
126
+ end
127
+
74
128
  Rack::OAuth2::Server::Token::ErrorMethods::DEFAULT_DESCRIPTION.each do |error, default_message|
75
129
  status = if error == :invalid_client
76
130
  401
@@ -87,7 +141,22 @@ describe Rack::OAuth2::Server::Token do
87
141
  its(:content_type) { should == 'application/json' }
88
142
  its(:body) { should include "\"error\":\"#{error}\"" }
89
143
  its(:body) { should include "\"error_description\":\"#{default_message}\"" }
144
+ if error == :invalid_client
145
+ its(:headers) { should include 'WWW-Authenticate' }
146
+ end
147
+ end
148
+ end
149
+
150
+ context 'when skip_www_authenticate option is specified on invalid_client' do
151
+ let(:app) do
152
+ Rack::OAuth2::Server::Token.new do |request, response|
153
+ request.invalid_client!(
154
+ Rack::OAuth2::Server::Token::ErrorMethods::DEFAULT_DESCRIPTION[:invalid_client],
155
+ skip_www_authenticate: true
156
+ )
157
+ end
90
158
  end
159
+ its(:headers) { should_not include 'WWW-Authenticate' }
91
160
  end
92
161
 
93
162
  context 'when responding' do
@@ -9,9 +9,14 @@ describe Rack::OAuth2::Util do
9
9
  'http://client.example.com/callback'
10
10
  end
11
11
 
12
- describe '.rfc3986_encode' do
13
- subject { util.rfc3986_encode '=+ .-/' }
14
- it { should == '%3D%2B%20.-%2F' }
12
+ describe '.www_form_url_encode' do
13
+ subject { util.www_form_url_encode '=+ .-/' }
14
+ it { should == '%3D%2B+.-%2F' }
15
+ end
16
+
17
+ describe '.www_form_urldecode' do
18
+ subject { util.www_form_url_decode '%3D%2B+.-%2F' }
19
+ it { should == '=+ .-/' }
15
20
  end
16
21
 
17
22
  describe '.base64_encode' do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-oauth2
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.10.1
4
+ version: 1.19.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - nov matake
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-11-15 00:00:00.000000000 Z
11
+ date: 2021-10-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
19
+ version: 2.1.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '0'
26
+ version: 2.1.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: httpclient
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -301,7 +301,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
301
301
  - !ruby/object:Gem::Version
302
302
  version: '0'
303
303
  requirements: []
304
- rubygems_version: 3.0.3
304
+ rubygems_version: 3.1.4
305
305
  signing_key:
306
306
  specification_version: 4
307
307
  summary: OAuth 2.0 Server & Client Library - Both Bearer and MAC token type are supported