rack-url_auth 0.0.0 → 0.2.1
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 +4 -4
- data/.gitignore +2 -0
- data/Gemfile.lock +25 -11
- data/README.md +77 -2
- data/lib/rack/url_auth/proxy.rb +10 -5
- data/lib/rack/url_auth/signer.rb +23 -19
- data/lib/rack/url_auth/version.rb +1 -1
- data/lib/rack/url_auth.rb +14 -5
- data/rack-signed_urls.gemspec +3 -0
- data/spec/middleware_spec.rb +69 -29
- data/spec/signer_spec.rb +35 -19
- metadata +39 -14
- data/spec/proxy_spec.rb +0 -40
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a72ca23ae12a4e7216c70321800a4381a265f92e
|
4
|
+
data.tar.gz: ff999de6188aeb84d739e7763402de8ce7984022
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 20b8935975cd8a6970b457be30728e909c9a7b25c9c56dc7daee0b9799530a37ed821833da72ec64be833b058380416a2ded57d95c01d5fcb45194201583e7b4
|
7
|
+
data.tar.gz: 5d06158fc1c9f29f45eef0efceb4a2f22bea0982885bb5f4b25a10ab20ea270576439e03ee561c0fde68af76abf60776bf3aadb2a683d9e88093de0e59cfcd2e
|
data/.gitignore
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,24 +1,35 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
rack-url_auth (0.
|
4
|
+
rack-url_auth (0.2.0)
|
5
|
+
addressable
|
6
|
+
ruby-hmac
|
5
7
|
|
6
8
|
GEM
|
7
9
|
remote: https://rubygems.org/
|
8
10
|
specs:
|
9
|
-
|
11
|
+
addressable (2.5.1)
|
12
|
+
public_suffix (~> 2.0, >= 2.0.2)
|
13
|
+
diff-lcs (1.3)
|
14
|
+
public_suffix (2.0.5)
|
10
15
|
rack (1.5.2)
|
11
16
|
rack-test (0.6.2)
|
12
17
|
rack (>= 1.0)
|
13
|
-
rake (
|
14
|
-
rspec (
|
15
|
-
rspec-core (~>
|
16
|
-
rspec-expectations (~>
|
17
|
-
rspec-mocks (~>
|
18
|
-
rspec-core (
|
19
|
-
|
20
|
-
|
21
|
-
|
18
|
+
rake (12.0.0)
|
19
|
+
rspec (3.6.0)
|
20
|
+
rspec-core (~> 3.6.0)
|
21
|
+
rspec-expectations (~> 3.6.0)
|
22
|
+
rspec-mocks (~> 3.6.0)
|
23
|
+
rspec-core (3.6.0)
|
24
|
+
rspec-support (~> 3.6.0)
|
25
|
+
rspec-expectations (3.6.0)
|
26
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
27
|
+
rspec-support (~> 3.6.0)
|
28
|
+
rspec-mocks (3.6.0)
|
29
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
30
|
+
rspec-support (~> 3.6.0)
|
31
|
+
rspec-support (3.6.0)
|
32
|
+
ruby-hmac (0.4.0)
|
22
33
|
|
23
34
|
PLATFORMS
|
24
35
|
ruby
|
@@ -30,3 +41,6 @@ DEPENDENCIES
|
|
30
41
|
rack-url_auth!
|
31
42
|
rake
|
32
43
|
rspec
|
44
|
+
|
45
|
+
BUNDLED WITH
|
46
|
+
1.14.6
|
data/README.md
CHANGED
@@ -1,6 +1,24 @@
|
|
1
1
|
# Rack::UrlAuth
|
2
2
|
|
3
|
-
|
3
|
+
Rack::UrlAuth is a Rack middleware for HMAC URL authentication.
|
4
|
+
|
5
|
+
The most obvious use case would be a service that allows its users to perform
|
6
|
+
an action by clicking on an email sent to them, such as activating an
|
7
|
+
account, claiming a discount coupon or reseting a password.
|
8
|
+
|
9
|
+
The user would receive an email with a link to an url such as:
|
10
|
+
`http://example.org/accounts/1/activate?expires=2013-12-12&signature=bf3a53...`
|
11
|
+
|
12
|
+
Because any tampering with the query string or any other url component
|
13
|
+
can be detected, the service can tell if the person is authorized to
|
14
|
+
perform that action.
|
15
|
+
|
16
|
+
Keep in mind that **all GET actions should be idempotent**, meaning that
|
17
|
+
accessing them every time yields the same result.
|
18
|
+
|
19
|
+
Amazon S3, Braintree and may other services use this same principle to
|
20
|
+
authenticate requests by either signing the request body or the url.
|
21
|
+
|
4
22
|
|
5
23
|
## Installation
|
6
24
|
|
@@ -16,9 +34,66 @@ Or install it yourself as:
|
|
16
34
|
|
17
35
|
$ gem install rack-url_auth
|
18
36
|
|
37
|
+
|
19
38
|
## Usage
|
20
39
|
|
21
|
-
|
40
|
+
### Rails example
|
41
|
+
|
42
|
+
|
43
|
+
```ruby
|
44
|
+
# config/application.rb
|
45
|
+
...
|
46
|
+
|
47
|
+
module MyApp
|
48
|
+
class Application < Rails::Application
|
49
|
+
config.middleware.use 'Rack::UrlAuth', secret: 'very-long-and-arbitrary-string'
|
50
|
+
...
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# controllers/application_controller.rb
|
55
|
+
class ApplicationController < ActionController::Base
|
56
|
+
...
|
57
|
+
protected
|
58
|
+
def authenticate_url!
|
59
|
+
unless env['rack.url_auth'].url_authorized?
|
60
|
+
render file: 'public/401', status: 401
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def sign_url(url)
|
65
|
+
env['rack.url_auth'].sign_url url
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# controllers/private_stuff_controller.rb
|
70
|
+
class PrivateThingsController < ApplicationController
|
71
|
+
before_filter :authenticate_url!, only: :view_private_thing
|
72
|
+
|
73
|
+
def send_authorization
|
74
|
+
signed_url = sign_url(view_private_thing_url(id: params[:id]))
|
75
|
+
ApplicationMailer.
|
76
|
+
private_thing_view_authorization(params[:email], signed_url).
|
77
|
+
deliver
|
78
|
+
...
|
79
|
+
end
|
80
|
+
|
81
|
+
def view_private_thing
|
82
|
+
# Not for you unless you are authorized ;)
|
83
|
+
@thing = PrivateThing.find(params[:id])
|
84
|
+
...
|
85
|
+
end
|
86
|
+
end
|
87
|
+
```
|
88
|
+
|
89
|
+
|
90
|
+
## Resources
|
91
|
+
|
92
|
+
|
93
|
+
* [Using HMAC to authenticate Web service requests](http://rc3.org/2011/12/02/using-hmac-to-authenticate-web-service-requests/)
|
94
|
+
* [Signed Idempotent Action Links](http://www.intridea.com/blog/2012/6/7/signed-idempotent-action-links)
|
95
|
+
* [Why you should never use hash functions for message authentication](http://blog.jcoglan.com/2012/06/09/why-you-should-never-use-hash-functions-for-message-authentication/)
|
96
|
+
|
22
97
|
|
23
98
|
## Contributing
|
24
99
|
|
data/lib/rack/url_auth/proxy.rb
CHANGED
@@ -8,13 +8,18 @@ module Rack
|
|
8
8
|
@signer = signer
|
9
9
|
end
|
10
10
|
|
11
|
-
def
|
12
|
-
|
13
|
-
|
11
|
+
def authorized?
|
12
|
+
method = request.request_method.downcase
|
13
|
+
signature_header = request.env["HTTP_X_SIGNATURE"]
|
14
14
|
|
15
|
-
|
16
|
-
|
15
|
+
if !signature_header && request.get? || request.head?
|
16
|
+
signer.verify_url(request.url, method)
|
17
|
+
else
|
18
|
+
body = request.body.read; request.body.rewind
|
19
|
+
signer.verify(method + request.url + body, signature_header)
|
20
|
+
end
|
17
21
|
end
|
18
22
|
end
|
23
|
+
|
19
24
|
end
|
20
25
|
end
|
data/lib/rack/url_auth/signer.rb
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
require 'hmac-sha2'
|
2
|
+
require 'addressable'
|
3
|
+
|
1
4
|
module Rack
|
2
5
|
class UrlAuth
|
3
6
|
class Signer
|
@@ -8,41 +11,42 @@ module Rack
|
|
8
11
|
end
|
9
12
|
|
10
13
|
def sign(message)
|
11
|
-
|
12
|
-
OpenSSL::HMAC.hexdigest sha1, secret, message
|
14
|
+
HMAC::SHA256.hexdigest(secret, message)
|
13
15
|
end
|
14
16
|
|
15
17
|
def verify(message, signature)
|
16
|
-
actual
|
18
|
+
actual = Digest::SHA1.hexdigest sign(message)
|
17
19
|
expected = Digest::SHA1.hexdigest signature
|
18
20
|
actual == expected
|
19
21
|
end
|
20
22
|
|
21
|
-
def sign_url(url)
|
22
|
-
purl
|
23
|
-
|
24
|
-
query
|
23
|
+
def sign_url(url, method)
|
24
|
+
purl, query = parse_and_extract_query(url)
|
25
|
+
normalized = purl.normalize.to_s
|
26
|
+
query['signature'] = sign(method.to_s.downcase + normalized)
|
25
27
|
|
26
|
-
build_url
|
28
|
+
build_url(purl, query)
|
27
29
|
end
|
28
30
|
|
29
|
-
def verify_url(url)
|
30
|
-
purl
|
31
|
-
|
32
|
-
|
31
|
+
def verify_url(url, method)
|
32
|
+
purl, query = parse_and_extract_query(url)
|
33
|
+
signature = query.delete('signature').to_s
|
34
|
+
message = method.to_s.downcase + build_url(purl, query)
|
33
35
|
|
34
|
-
verify
|
36
|
+
verify(message, signature)
|
35
37
|
end
|
36
38
|
|
37
39
|
private
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
40
|
+
|
41
|
+
def parse_and_extract_query(url)
|
42
|
+
purl = Addressable::URI.parse(url)
|
43
|
+
query = purl.query_values || {}
|
44
|
+
[purl, query]
|
43
45
|
end
|
44
46
|
|
45
|
-
|
47
|
+
def build_url(purl, query)
|
48
|
+
purl.query = Rack::Utils.build_query(query)
|
49
|
+
purl.normalize.to_s
|
46
50
|
end
|
47
51
|
end
|
48
52
|
end
|
data/lib/rack/url_auth.rb
CHANGED
@@ -4,16 +4,25 @@ require "rack/url_auth/proxy"
|
|
4
4
|
|
5
5
|
module Rack
|
6
6
|
class UrlAuth
|
7
|
-
attr_reader :app, :signer
|
7
|
+
attr_reader :app, :signer, :forward_auth
|
8
8
|
|
9
9
|
def initialize(app, opts = {})
|
10
|
-
secret = opts[:secret] or
|
11
|
-
|
10
|
+
secret = opts[:secret] or
|
11
|
+
raise(ArgumentError, 'Please provide `secret`')
|
12
|
+
|
13
|
+
@app = app
|
14
|
+
@signer = Signer.new(secret)
|
15
|
+
@forward_auth = !!opts[:forward_auth]
|
12
16
|
end
|
13
17
|
|
14
18
|
def call(env)
|
15
|
-
env['rack.
|
16
|
-
|
19
|
+
proxy = env['rack.signature_auth'] = Proxy.new(env, signer)
|
20
|
+
|
21
|
+
if !@forward_auth && !proxy.authorized?
|
22
|
+
[403, {}, ['Forbidden']]
|
23
|
+
else
|
24
|
+
@app.call(env)
|
25
|
+
end
|
17
26
|
end
|
18
27
|
end
|
19
28
|
end
|
data/rack-signed_urls.gemspec
CHANGED
@@ -18,6 +18,9 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
+
spec.add_dependency "ruby-hmac"
|
22
|
+
spec.add_dependency "addressable"
|
23
|
+
|
21
24
|
spec.add_development_dependency "bundler", "~> 1.3"
|
22
25
|
spec.add_development_dependency "rake"
|
23
26
|
end
|
data/spec/middleware_spec.rb
CHANGED
@@ -1,48 +1,88 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
|
3
|
+
describe Rack::UrlAuth do
|
4
|
+
include Rack::Test::Methods
|
4
5
|
|
5
|
-
|
6
|
-
let(:
|
7
|
-
let(:
|
6
|
+
let(:secret) { 'secretive-secret' }
|
7
|
+
let(:inner_app) { ->(env){ [200,{},['Hello, world.']] } }
|
8
|
+
let(:app) { Rack::UrlAuth.new(inner_app, secret: secret) }
|
8
9
|
|
9
|
-
|
10
|
+
describe 'instantiation' do
|
11
|
+
it 'requires a secret' do
|
12
|
+
expect { Rack::UrlAuth.new(app) }.to raise_error ArgumentError
|
13
|
+
end
|
14
|
+
end
|
10
15
|
|
11
|
-
describe '
|
12
|
-
let(:
|
16
|
+
describe 'request without body' do
|
17
|
+
let(:signature) {
|
18
|
+
'b645417491551a215286db40cd3fbdd97c7e2f146b2feb0ae5f32f03537ed343'
|
19
|
+
}
|
13
20
|
|
14
|
-
it '
|
15
|
-
|
16
|
-
|
21
|
+
it 'authorizes request' do
|
22
|
+
get "/index?signature=#{signature}"
|
23
|
+
expect( last_request.env['rack.signature_auth'] ).to be_authorized
|
17
24
|
end
|
18
25
|
|
19
|
-
it '
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
and_return(signer)
|
26
|
+
it 'forbids request if url is tampered' do
|
27
|
+
get "/forbid?signature=#{signature}"
|
28
|
+
expect( last_request.env['rack.signature_auth'] ).not_to be_authorized
|
29
|
+
end
|
24
30
|
|
25
|
-
|
26
|
-
|
31
|
+
it 'forbids request if method is incorrect' do
|
32
|
+
head "/index?signature=#{signature}"
|
33
|
+
expect( last_request.env['rack.signature_auth'] ).not_to be_authorized
|
27
34
|
end
|
28
35
|
end
|
29
36
|
|
30
|
-
describe 'calling' do
|
31
|
-
let(:app) { UrlAuth.new(inner_app, secret: secret) }
|
32
|
-
let(:env) { { path: '/'} }
|
33
|
-
let(:proxy) { mock('Proxy') }
|
34
37
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
+
describe 'request with body' do
|
39
|
+
let(:signature) {
|
40
|
+
'bab5dd78fce9f4fd85c5037466c5a5e22cf67ba14f25005f499ddc7820710475'
|
41
|
+
}
|
42
|
+
|
43
|
+
it 'autorizes request' do
|
44
|
+
header 'X-Signature', signature
|
45
|
+
post '/index', name: 'Macario'
|
46
|
+
expect( last_request.env['rack.signature_auth'] ).to be_authorized
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'forbids request if url is tampered' do
|
50
|
+
header 'X-Signature', signature
|
51
|
+
post '/forbid', name: 'Macario'
|
52
|
+
expect( last_request.env['rack.signature_auth'] ).not_to be_authorized
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'forbids request if body is tampered' do
|
56
|
+
header 'X-Signature', signature
|
57
|
+
post '/index', name: 'Juan'
|
58
|
+
expect( last_request.env['rack.signature_auth'] ).not_to be_authorized
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'forbids request if method is incorrect' do
|
62
|
+
header 'X-Signature', signature
|
63
|
+
put '/index', name: 'Macario'
|
64
|
+
expect( last_request.env['rack.signature_auth'] ).not_to be_authorized
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe 'handling authentication' do
|
69
|
+
context 'not forwarding auth to app' do
|
70
|
+
let(:app) { Rack::UrlAuth.new(inner_app, secret: secret) }
|
38
71
|
|
39
|
-
|
40
|
-
|
72
|
+
it 'returns forbidden status code' do
|
73
|
+
get "/forbid"
|
74
|
+
expect( last_response.status ).to eq 403
|
75
|
+
end
|
41
76
|
end
|
42
77
|
|
43
|
-
|
44
|
-
|
45
|
-
|
78
|
+
context 'forwarding auth to app' do
|
79
|
+
let(:app) { Rack::UrlAuth.new(inner_app,
|
80
|
+
forward_auth: true, secret: secret) }
|
81
|
+
|
82
|
+
it 'returns forbidden status code' do
|
83
|
+
get "/forbid"
|
84
|
+
expect( last_response.status ).to eq 200
|
85
|
+
end
|
46
86
|
end
|
47
87
|
end
|
48
88
|
end
|
data/spec/signer_spec.rb
CHANGED
@@ -6,48 +6,64 @@ describe UrlAuth::Signer do
|
|
6
6
|
let(:signer) { UrlAuth::Signer.new('my-secretive-secret') }
|
7
7
|
|
8
8
|
describe 'signing and validating messages' do
|
9
|
-
let(:message)
|
9
|
+
let(:message) { 'HMAC is fun!!' }
|
10
10
|
let(:tampered_message) { 'HMAC is fun!!!' }
|
11
|
+
let(:signature) { signer.sign message }
|
11
12
|
|
12
13
|
it 'signs a messages' do
|
13
|
-
signature
|
14
|
-
|
15
|
-
|
16
|
-
signer.verify(message, signature).should be true
|
17
|
-
signer.verify(tampered_message, signature).should be false
|
14
|
+
expect(signature.size).to eq(64)
|
15
|
+
expect(signer.verify(message, signature)).to be true
|
16
|
+
expect(signer.verify(tampered_message, signature)).to be false
|
18
17
|
end
|
19
18
|
end
|
20
19
|
|
21
20
|
describe 'signed urls' do
|
22
|
-
let(:url)
|
23
|
-
let(:signed_url) { signer.sign_url url }
|
21
|
+
let(:url) { 'http://example.com/path?token=1&query=sumething' }
|
22
|
+
let(:signed_url) { signer.sign_url url, 'get' }
|
24
23
|
|
25
24
|
it 'appends signature' do
|
26
|
-
signed_url.
|
25
|
+
expect(signed_url).to match %r{&signature=\w{64}}
|
27
26
|
end
|
28
27
|
|
29
28
|
it 'keeps params' do
|
30
|
-
signed_url.
|
29
|
+
expect(signed_url).to include '?token=1&query=sumething'
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'keeps host and path' do
|
33
|
+
expect(signed_url).to match %r{http://example\.com/path}
|
31
34
|
end
|
32
35
|
|
33
|
-
it 'keeps port' do
|
34
|
-
signed_url
|
36
|
+
it 'keeps port if different than 80' do
|
37
|
+
signed_url = signer.
|
38
|
+
sign_url 'http://example.com:3000/path?token=1&query=sumething', 'get'
|
39
|
+
expect(signed_url).to match %{^http://example.com:3000}
|
35
40
|
end
|
36
41
|
|
37
42
|
it 'verifies untampered url' do
|
38
|
-
signer.verify_url(signed_url).
|
43
|
+
expect( signer.verify_url(signed_url, 'get') ).to be true
|
39
44
|
end
|
40
45
|
|
41
46
|
it 'verifies false if url is tampered' do
|
42
|
-
signer.verify_url(signed_url.sub(/\.com/, '.me')).
|
43
|
-
|
44
|
-
signer.verify_url(signed_url.sub('
|
47
|
+
expect( signer.verify_url(signed_url.sub(/\.com/, '.me'), 'get') ).
|
48
|
+
to be false
|
49
|
+
expect( signer.verify_url(signed_url.sub('path', 'other-path'), 'get') ).
|
50
|
+
to be false
|
51
|
+
expect( signer.verify_url(signed_url.sub('1', '2'), 'get') ).
|
52
|
+
to be false
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'verifies that the method is correct' do
|
56
|
+
expect( signer.verify_url(signed_url, 'delete') ).to be false
|
45
57
|
end
|
46
58
|
|
47
59
|
it 'raises error when url is unsigned while verifying url' do
|
48
|
-
|
49
|
-
|
50
|
-
|
60
|
+
expect(signer.verify_url 'http://example.com', 'get').to be false
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'normalizes url' do
|
64
|
+
signed_url = signer.
|
65
|
+
sign_url 'http://example.com/path?token=點看&query=sumething:else', 'get'
|
66
|
+
expect( signer.verify_url(signed_url, 'get') ).to be true
|
51
67
|
end
|
52
68
|
end
|
53
69
|
end
|
metadata
CHANGED
@@ -1,41 +1,69 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rack-url_auth
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- macario
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-09-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: ruby-hmac
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: addressable
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
13
41
|
- !ruby/object:Gem::Dependency
|
14
42
|
name: bundler
|
15
43
|
requirement: !ruby/object:Gem::Requirement
|
16
44
|
requirements:
|
17
|
-
- - ~>
|
45
|
+
- - "~>"
|
18
46
|
- !ruby/object:Gem::Version
|
19
47
|
version: '1.3'
|
20
48
|
type: :development
|
21
49
|
prerelease: false
|
22
50
|
version_requirements: !ruby/object:Gem::Requirement
|
23
51
|
requirements:
|
24
|
-
- - ~>
|
52
|
+
- - "~>"
|
25
53
|
- !ruby/object:Gem::Version
|
26
54
|
version: '1.3'
|
27
55
|
- !ruby/object:Gem::Dependency
|
28
56
|
name: rake
|
29
57
|
requirement: !ruby/object:Gem::Requirement
|
30
58
|
requirements:
|
31
|
-
- -
|
59
|
+
- - ">="
|
32
60
|
- !ruby/object:Gem::Version
|
33
61
|
version: '0'
|
34
62
|
type: :development
|
35
63
|
prerelease: false
|
36
64
|
version_requirements: !ruby/object:Gem::Requirement
|
37
65
|
requirements:
|
38
|
-
- -
|
66
|
+
- - ">="
|
39
67
|
- !ruby/object:Gem::Version
|
40
68
|
version: '0'
|
41
69
|
description: Middleware for signing urls
|
@@ -45,8 +73,8 @@ executables: []
|
|
45
73
|
extensions: []
|
46
74
|
extra_rdoc_files: []
|
47
75
|
files:
|
48
|
-
- .gitignore
|
49
|
-
- .rspec
|
76
|
+
- ".gitignore"
|
77
|
+
- ".rspec"
|
50
78
|
- Gemfile
|
51
79
|
- Gemfile.lock
|
52
80
|
- LICENSE.txt
|
@@ -58,7 +86,6 @@ files:
|
|
58
86
|
- lib/rack/url_auth/version.rb
|
59
87
|
- rack-signed_urls.gemspec
|
60
88
|
- spec/middleware_spec.rb
|
61
|
-
- spec/proxy_spec.rb
|
62
89
|
- spec/signer_spec.rb
|
63
90
|
- spec/spec_helper.rb
|
64
91
|
homepage: http://github.com/maca/rack-url_auth
|
@@ -71,23 +98,21 @@ require_paths:
|
|
71
98
|
- lib
|
72
99
|
required_ruby_version: !ruby/object:Gem::Requirement
|
73
100
|
requirements:
|
74
|
-
- -
|
101
|
+
- - ">="
|
75
102
|
- !ruby/object:Gem::Version
|
76
103
|
version: '0'
|
77
104
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
78
105
|
requirements:
|
79
|
-
- -
|
106
|
+
- - ">="
|
80
107
|
- !ruby/object:Gem::Version
|
81
108
|
version: '0'
|
82
109
|
requirements: []
|
83
110
|
rubyforge_project:
|
84
|
-
rubygems_version: 2.
|
111
|
+
rubygems_version: 2.6.11
|
85
112
|
signing_key:
|
86
113
|
specification_version: 4
|
87
114
|
summary: Middleware authorizing signed urls, so they can't be tampered
|
88
115
|
test_files:
|
89
116
|
- spec/middleware_spec.rb
|
90
|
-
- spec/proxy_spec.rb
|
91
117
|
- spec/signer_spec.rb
|
92
118
|
- spec/spec_helper.rb
|
93
|
-
has_rdoc:
|
data/spec/proxy_spec.rb
DELETED
@@ -1,40 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
include Rack
|
4
|
-
|
5
|
-
describe UrlAuth::Proxy do
|
6
|
-
let(:env) { Rack::MockRequest.env_for('/home?signature=mock') }
|
7
|
-
let(:signer) { mock('Signer') }
|
8
|
-
let(:proxy) { UrlAuth::Proxy.new(env, signer) }
|
9
|
-
|
10
|
-
describe 'signing urls' do
|
11
|
-
it 'signs a url' do
|
12
|
-
signer.
|
13
|
-
should_receive(:sign_url).
|
14
|
-
and_return('/home?signature=mock')
|
15
|
-
|
16
|
-
proxy.sign_url('/home').
|
17
|
-
should eq '/home?signature=mock'
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
describe 'signer' do
|
22
|
-
it 'authorizes url' do
|
23
|
-
signer.
|
24
|
-
should_receive(:verify_url).
|
25
|
-
with('http://example.org/home?signature=mock').
|
26
|
-
and_return(true)
|
27
|
-
|
28
|
-
proxy.url_authorized?.should be true
|
29
|
-
end
|
30
|
-
|
31
|
-
it 'returns false for tampered url' do
|
32
|
-
signer.
|
33
|
-
should_receive(:verify_url).
|
34
|
-
with('http://example.org/home?signature=mock').
|
35
|
-
and_return(false)
|
36
|
-
|
37
|
-
proxy.url_authorized?.should be false
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|