rack-authenticate 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm use 1.9.2
@@ -0,0 +1,45 @@
1
+ module Rack
2
+ module Authenticate
3
+ class CORSMiddleware
4
+ ACCESS_CONTROL_MAX_AGE = 60 * 60 * 48 # 48 hours
5
+
6
+ def initialize(app)
7
+ @app = app
8
+ end
9
+
10
+ def call(env)
11
+ status, headers, body = if cors_preflight_request?(env)
12
+ cors_allowances(env)
13
+ else
14
+ @app.call(env)
15
+ end
16
+
17
+ headers['Access-Control-Allow-Origin'] = env['HTTP_ORIGIN'] if env.has_key?('HTTP_ORIGIN')
18
+
19
+ [status, headers, body]
20
+ end
21
+
22
+ def cors_preflight_request?(env)
23
+ env['REQUEST_METHOD'] == 'OPTIONS' &&
24
+ %w[ HTTP_ACCESS_CONTROL_REQUEST_METHOD HTTP_ORIGIN ].all? { |k| env.has_key?(k) }
25
+ end
26
+
27
+ def cors_allowances(env)
28
+ headers = {
29
+ 'Access-Control-Allow-Origin' => env['HTTP_ORIGIN'],
30
+ 'Access-Control-Allow-Methods' => env['HTTP_ACCESS_CONTROL_REQUEST_METHOD'],
31
+ 'Access-Control-Allow-Credentials' => 'true',
32
+ 'Access-Control-Max-Age' => ACCESS_CONTROL_MAX_AGE.to_s,
33
+ 'Content-Type' => 'text/plain'
34
+ }
35
+
36
+ if env.has_key?('HTTP_ACCESS_CONTROL_REQUEST_HEADERS')
37
+ headers['Access-Control-Allow-Headers'] = env['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']
38
+ end
39
+
40
+ [200, headers, []]
41
+ end
42
+ end
43
+ end
44
+ end
45
+
@@ -5,8 +5,6 @@ require 'time'
5
5
  module Rack
6
6
  module Authenticate
7
7
  class Middleware < ::Rack::Auth::Basic
8
- ACCESS_CONTROL_MAX_AGE = 60 * 60 * 24 # 24 hours
9
-
10
8
  class Configuration
11
9
  def initialize(*args)
12
10
  self.timestamp_minute_tolerance ||= 30
@@ -112,12 +110,6 @@ module Rack
112
110
  calculated_digest == given_digest
113
111
  end
114
112
 
115
- def supported_cors_preflight_request?
116
- @configuration.support_cross_origin_resource_sharing? &&
117
- request.request_method == 'OPTIONS' &&
118
- %w[ HTTP_ACCESS_CONTROL_REQUEST_METHOD HTTP_ORIGIN ].all? { |k| request.env.has_key?(k) }
119
- end
120
-
121
113
  private
122
114
 
123
115
  def date
@@ -135,47 +127,36 @@ module Rack
135
127
  def initialize(app)
136
128
  @configuration = Configuration.new
137
129
  yield @configuration
130
+
131
+ @middleware_stack = lambda do |env|
132
+ auth = Auth.new(env, @configuration)
133
+ _call(env, auth)
134
+ end
135
+
136
+ if @configuration.support_cross_origin_resource_sharing?
137
+ require 'rack/authenticate/cors_middleware'
138
+ @middleware_stack = ::Rack::Authenticate::CORSMiddleware.new(@middleware_stack)
139
+ end
140
+
138
141
  super(app, &@configuration.basic_auth_validation_block)
139
142
  end
140
143
 
144
+ alias basic_auth_call call
141
145
  def call(env)
142
- auth = Auth.new(env, @configuration)
143
- return cors_allowances(env) if auth.supported_cors_preflight_request?
144
-
145
- _call(env, auth) { super }.tap do |(status, headers, body)|
146
- if @configuration.support_cross_origin_resource_sharing? && env.has_key?('HTTP_ORIGIN')
147
- headers['Access-Control-Allow-Origin'] = env['HTTP_ORIGIN']
148
- end
149
- end
146
+ @middleware_stack.call(env)
150
147
  end
151
148
 
152
149
  private
153
150
 
154
151
  def _call(env, auth)
155
152
  return unauthorized unless auth.provided?
156
- return yield if auth.basic?
153
+ return basic_auth_call(env) if auth.basic?
157
154
  return bad_request unless auth.hmac?
158
155
  return bad_request unless auth.has_all_required_parts?
159
156
  return unauthorized unless auth.valid?
160
157
 
161
158
  @app.call(env)
162
159
  end
163
-
164
- def cors_allowances(env)
165
- headers = {
166
- 'Access-Control-Allow-Origin' => env['HTTP_ORIGIN'],
167
- 'Access-Control-Allow-Methods' => env['HTTP_ACCESS_CONTROL_REQUEST_METHOD'],
168
- 'Access-Control-Allow-Credentials' => 'true',
169
- 'Access-Control-Max-Age' => ACCESS_CONTROL_MAX_AGE.to_s,
170
- 'Content-Type' => 'text/plain'
171
- }
172
-
173
- if env.has_key?('HTTP_ACCESS_CONTROL_REQUEST_HEADERS')
174
- headers['Access-Control-Allow-Headers'] = env['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']
175
- end
176
-
177
- [200, headers, []]
178
- end
179
160
  end
180
161
  end
181
162
  end
@@ -1,5 +1,5 @@
1
1
  module Rack
2
2
  module Authenticate
3
- VERSION = "0.3.0"
3
+ VERSION = "0.4.0"
4
4
  end
5
5
  end
@@ -0,0 +1,69 @@
1
+ require 'rack/authenticate/cors_middleware'
2
+ require 'rack/test'
3
+
4
+ RSpec.configure do |c|
5
+ c.treat_symbols_as_metadata_keys_with_true_values = true
6
+ c.filter_run :f
7
+ c.run_all_when_everything_filtered = true
8
+ end
9
+
10
+ module Rack
11
+ module Authenticate
12
+ describe CORSMiddleware do
13
+ include Rack::Test::Methods
14
+
15
+ let(:app) do
16
+ Rack::Builder.new do
17
+ use Rack::ContentLength
18
+ use Rack::Authenticate::CORSMiddleware
19
+ run lambda { |env| [200, {}, ['OK']] }
20
+ end
21
+ end
22
+
23
+ let(:headers) { 'X-Authorization-Date, Content-MD5, Authorization, Content-Type' }
24
+ let(:origin) { 'http://foo.example.com' }
25
+
26
+ let(:expected_response_headers) do {
27
+ 'Content-Type' => 'text/plain',
28
+ 'Access-Control-Allow-Origin' => origin,
29
+ 'Access-Control-Allow-Methods' => 'PUT',
30
+ 'Access-Control-Allow-Credentials' => 'true',
31
+ 'Access-Control-Max-Age' => CORSMiddleware::ACCESS_CONTROL_MAX_AGE.to_s
32
+ } end
33
+
34
+ it 'responds to a CORS OPTIONS request with all of the correct headers' do
35
+ header 'Origin', origin
36
+ header 'Access-Control-Request-Method', 'PUT'
37
+ options '/'
38
+
39
+ last_response.status.should eq(200)
40
+ last_response.headers.should include(expected_response_headers)
41
+ last_response.headers.should_not have_key('Access-Control-Allow-Headers')
42
+ end
43
+
44
+ it 'includes Access-Control-Allow-Headers when they the request asks about them' do
45
+ header 'Origin', origin
46
+ header 'Access-Control-Request-Method', 'PUT'
47
+ header 'Access-Control-Request-Headers', headers
48
+ options '/'
49
+
50
+ last_response.status.should eq(200)
51
+ last_response.headers.should include(expected_response_headers.merge(
52
+ 'Access-Control-Allow-Headers' => headers
53
+ ))
54
+ end
55
+
56
+ it 'appends the Access-Control-Allow-Origin header to every response to a request with an Origin header' do
57
+ header 'Origin', origin
58
+ get '/'
59
+ last_response.headers.should include('Access-Control-Allow-Origin' => origin)
60
+ end
61
+
62
+ it 'does not append a Access-Control-Allow-Origin header to a request without an Origin header' do
63
+ get '/'
64
+ last_response.headers.keys.should_not include('Access-Control-Allow-Origin')
65
+ end
66
+ end
67
+ end
68
+ end
69
+
@@ -370,7 +370,7 @@ module Rack
370
370
  'Access-Control-Allow-Origin' => origin,
371
371
  'Access-Control-Allow-Methods' => 'PUT',
372
372
  'Access-Control-Allow-Credentials' => 'true',
373
- 'Access-Control-Max-Age' => ACCESS_CONTROL_MAX_AGE.to_s
373
+ 'Access-Control-Max-Age' => CORSMiddleware::ACCESS_CONTROL_MAX_AGE.to_s
374
374
  } end
375
375
 
376
376
  it 'responds to a CORS OPTIONS request with all of the correct headers' do
@@ -382,29 +382,6 @@ module Rack
382
382
  last_response.headers.should include(expected_response_headers)
383
383
  last_response.headers.should_not have_key('Access-Control-Allow-Headers')
384
384
  end
385
-
386
- it 'includes Access-Control-Allow-Headers when they the request asks about them' do
387
- header 'Origin', origin
388
- header 'Access-Control-Request-Method', 'PUT'
389
- header 'Access-Control-Request-Headers', headers
390
- options '/'
391
-
392
- last_response.status.should eq(200)
393
- last_response.headers.should include(expected_response_headers.merge(
394
- 'Access-Control-Allow-Headers' => headers
395
- ))
396
- end
397
-
398
- it 'appends the Access-Control-Allow-Origin header to every response to a request with an Origin header' do
399
- header 'Origin', origin
400
- get '/'
401
- last_response.headers.should include('Access-Control-Allow-Origin' => origin)
402
- end
403
-
404
- it 'does not append a Access-Control-Allow-Origin header to a request without an Origin header' do
405
- get '/'
406
- last_response.headers.keys.should_not include('Access-Control-Allow-Origin')
407
- end
408
385
  end
409
386
 
410
387
  context 'when cross origin resource sharing is not supported' do
@@ -418,12 +395,6 @@ module Rack
418
395
  last_response.status.should eq(401)
419
396
  last_response.headers.keys.select { |k| k.include?('Access-Control') }.should eq([])
420
397
  end
421
-
422
- it 'does not append the Access-Control-Allow-Origin header to every response' do
423
- header 'Origin', 'http://foo.example.com'
424
- get '/'
425
- last_response.headers.keys.should_not include('Access-Control-Allow-Origin')
426
- end
427
398
  end
428
399
  end
429
400
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-authenticate
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-12-19 00:00:00.000000000Z
12
+ date: 2012-02-14 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: ruby-hmac
16
- requirement: &2156269640 !ruby/object:Gem::Requirement
16
+ requirement: &2152601180 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 0.4.0
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *2156269640
24
+ version_requirements: *2152601180
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rspec
27
- requirement: &2156267980 !ruby/object:Gem::Requirement
27
+ requirement: &2152600560 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 2.8.0.rc1
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *2156267980
35
+ version_requirements: *2152600560
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rack-test
38
- requirement: &2156267060 !ruby/object:Gem::Requirement
38
+ requirement: &2152599640 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 0.6.1
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *2156267060
46
+ version_requirements: *2152599640
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: timecop
49
- requirement: &2156266080 !ruby/object:Gem::Requirement
49
+ requirement: &2152588140 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ~>
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: 0.3.5
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *2156266080
57
+ version_requirements: *2152588140
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: rake
60
- requirement: &2156265000 !ruby/object:Gem::Requirement
60
+ requirement: &2152586640 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ~>
@@ -65,7 +65,7 @@ dependencies:
65
65
  version: 0.9.2.2
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *2156265000
68
+ version_requirements: *2152586640
69
69
  description: A rack middleware that authenticates requests either using basic auth
70
70
  or via signed HMAC.
71
71
  email:
@@ -76,6 +76,7 @@ extra_rdoc_files: []
76
76
  files:
77
77
  - .gitignore
78
78
  - .rspec
79
+ - .rvmrc
79
80
  - .travis.yml
80
81
  - Appraisals
81
82
  - Gemfile
@@ -90,10 +91,12 @@ files:
90
91
  - lib/rack-authenticate.rb
91
92
  - lib/rack/authenticate.rb
92
93
  - lib/rack/authenticate/client.rb
94
+ - lib/rack/authenticate/cors_middleware.rb
93
95
  - lib/rack/authenticate/middleware.rb
94
96
  - lib/rack/authenticate/version.rb
95
97
  - rack-authenticate.gemspec
96
98
  - spec/rack/authenticate/client_spec.rb
99
+ - spec/rack/authenticate/cors_middleware_spec.rb
97
100
  - spec/rack/authenticate/middleware_spec.rb
98
101
  - spec/rack/authenticate_spec.rb
99
102
  homepage: ''
@@ -110,7 +113,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
110
113
  version: '0'
111
114
  segments:
112
115
  - 0
113
- hash: 496392540953768214
116
+ hash: -359603919774236080
114
117
  required_rubygems_version: !ruby/object:Gem::Requirement
115
118
  none: false
116
119
  requirements:
@@ -119,7 +122,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
119
122
  version: '0'
120
123
  segments:
121
124
  - 0
122
- hash: 496392540953768214
125
+ hash: -359603919774236080
123
126
  requirements: []
124
127
  rubyforge_project: rack-authenticate
125
128
  rubygems_version: 1.8.6
@@ -129,5 +132,6 @@ summary: A rack middleware that authenticates requests either using basic auth o
129
132
  via signed HMAC.
130
133
  test_files:
131
134
  - spec/rack/authenticate/client_spec.rb
135
+ - spec/rack/authenticate/cors_middleware_spec.rb
132
136
  - spec/rack/authenticate/middleware_spec.rb
133
137
  - spec/rack/authenticate_spec.rb