rack-url_auth 0.0.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 +7 -0
- data/.gitignore +1 -0
- data/.rspec +1 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +32 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +1 -0
- data/lib/rack/url_auth/proxy.rb +20 -0
- data/lib/rack/url_auth/signer.rb +49 -0
- data/lib/rack/url_auth/version.rb +5 -0
- data/lib/rack/url_auth.rb +19 -0
- data/rack-signed_urls.gemspec +23 -0
- data/spec/middleware_spec.rb +48 -0
- data/spec/proxy_spec.rb +40 -0
- data/spec/signer_spec.rb +53 -0
- data/spec/spec_helper.rb +7 -0
- metadata +93 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 4d876d1b7162d8ca7a0b60d5d9682ba06b28cce3
|
4
|
+
data.tar.gz: b8a4579117bce3c2be5c0e3af3794119974169c8
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 455b084764c70bedc87efb4af97391cfd8d8d4d0a09758bcba711e16165497a51a25787e7dadfc4890b16bc74c1270df9e50e4d290f647134c84651f2dc6ebf3
|
7
|
+
data.tar.gz: 564f4788ce3a5f1be827f4e4e852727762b6572ab7a21b5776ed9b5f2b3e24d700bf7f61e9c4d8af6f0e4d75fb5c4354aab4d3cd09f14adc3894f6315e45001d
|
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
pkg
|
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
rack-url_auth (0.0.0)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
diff-lcs (1.2.4)
|
10
|
+
rack (1.5.2)
|
11
|
+
rack-test (0.6.2)
|
12
|
+
rack (>= 1.0)
|
13
|
+
rake (10.0.4)
|
14
|
+
rspec (2.13.0)
|
15
|
+
rspec-core (~> 2.13.0)
|
16
|
+
rspec-expectations (~> 2.13.0)
|
17
|
+
rspec-mocks (~> 2.13.0)
|
18
|
+
rspec-core (2.13.1)
|
19
|
+
rspec-expectations (2.13.0)
|
20
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
21
|
+
rspec-mocks (2.13.1)
|
22
|
+
|
23
|
+
PLATFORMS
|
24
|
+
ruby
|
25
|
+
|
26
|
+
DEPENDENCIES
|
27
|
+
bundler (~> 1.3)
|
28
|
+
rack (~> 1.5)
|
29
|
+
rack-test
|
30
|
+
rack-url_auth!
|
31
|
+
rake
|
32
|
+
rspec
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 macario
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# Rack::UrlAuth
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'rack-url_auth'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install rack-url_auth
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Rack
|
2
|
+
class UrlAuth
|
3
|
+
class Proxy
|
4
|
+
attr_reader :request, :signer
|
5
|
+
|
6
|
+
def initialize(env, signer)
|
7
|
+
@request = Rack::Request.new(env)
|
8
|
+
@signer = signer
|
9
|
+
end
|
10
|
+
|
11
|
+
def url_authorized?
|
12
|
+
signer.verify_url(request.url)
|
13
|
+
end
|
14
|
+
|
15
|
+
def sign_url(url)
|
16
|
+
signer.sign_url(url)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Rack
|
2
|
+
class UrlAuth
|
3
|
+
class Signer
|
4
|
+
attr_reader :secret
|
5
|
+
|
6
|
+
def initialize(secret)
|
7
|
+
@secret = secret
|
8
|
+
end
|
9
|
+
|
10
|
+
def sign(message)
|
11
|
+
sha1 = OpenSSL::Digest::Digest.new('sha1')
|
12
|
+
OpenSSL::HMAC.hexdigest sha1, secret, message
|
13
|
+
end
|
14
|
+
|
15
|
+
def verify(message, signature)
|
16
|
+
actual = Digest::SHA1.hexdigest sign(message)
|
17
|
+
expected = Digest::SHA1.hexdigest signature
|
18
|
+
actual == expected
|
19
|
+
end
|
20
|
+
|
21
|
+
def sign_url(url)
|
22
|
+
purl = URI.parse url
|
23
|
+
query = Rack::Utils.parse_query purl.query
|
24
|
+
query.merge! 'signature' => sign(url)
|
25
|
+
|
26
|
+
build_url purl, query
|
27
|
+
end
|
28
|
+
|
29
|
+
def verify_url(url)
|
30
|
+
purl = URI.parse url
|
31
|
+
query = Rack::Utils.parse_query(purl.query)
|
32
|
+
signature = query.delete('signature') or raise MissingSignature
|
33
|
+
|
34
|
+
verify build_url(purl, query), signature
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
def build_url(purl, query)
|
39
|
+
query = Rack::Utils.build_query(query)
|
40
|
+
url = "#{purl.scheme}://#{purl.host}#{':' + purl.port.to_s if purl.port}#{purl.path}"
|
41
|
+
url = "#{url}?#{query}" unless query.empty?
|
42
|
+
url
|
43
|
+
end
|
44
|
+
|
45
|
+
class MissingSignature < StandardError
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require "rack/url_auth/version"
|
2
|
+
require "rack/url_auth/signer"
|
3
|
+
require "rack/url_auth/proxy"
|
4
|
+
|
5
|
+
module Rack
|
6
|
+
class UrlAuth
|
7
|
+
attr_reader :app, :signer
|
8
|
+
|
9
|
+
def initialize(app, opts = {})
|
10
|
+
secret = opts[:secret] or raise(ArgumentError, 'Please provide `secret`')
|
11
|
+
@app, @signer = app, Signer.new(secret)
|
12
|
+
end
|
13
|
+
|
14
|
+
def call(env)
|
15
|
+
env['rack.url_auth'] = Proxy.new(env, signer)
|
16
|
+
@app.call(env)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'rack/url_auth/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "rack-url_auth"
|
8
|
+
spec.version = Rack::UrlAuth::VERSION
|
9
|
+
spec.authors = ["macario"]
|
10
|
+
spec.email = ["mail@makarius.me"]
|
11
|
+
spec.description = %q{Middleware for signing urls}
|
12
|
+
spec.summary = %q{Middleware authorizing signed urls, so they can't be tampered}
|
13
|
+
spec.homepage = "http://github.com/maca/rack-url_auth"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
include Rack
|
4
|
+
|
5
|
+
describe UrlAuth do
|
6
|
+
let(:secret) { 'my-secretive-secret' }
|
7
|
+
let(:inner_app) { mock('App', call: []) }
|
8
|
+
|
9
|
+
it { UrlAuth::VERSION.should eq '0.0.0' }
|
10
|
+
|
11
|
+
describe 'intantiation' do
|
12
|
+
let(:signer) { mock('Signer') }
|
13
|
+
|
14
|
+
it 'requires a secret' do
|
15
|
+
expect { UrlAuth.new(inner_app) }.
|
16
|
+
to raise_error(ArgumentError)
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'instantiates an signer' do
|
20
|
+
UrlAuth::Signer.
|
21
|
+
should_receive(:new).
|
22
|
+
with(secret).
|
23
|
+
and_return(signer)
|
24
|
+
|
25
|
+
app = UrlAuth.new(inner_app, secret: secret)
|
26
|
+
app.signer.should be signer
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe 'calling' do
|
31
|
+
let(:app) { UrlAuth.new(inner_app, secret: secret) }
|
32
|
+
let(:env) { { path: '/'} }
|
33
|
+
let(:proxy) { mock('Proxy') }
|
34
|
+
|
35
|
+
it 'sets proxy as env variable' do
|
36
|
+
UrlAuth::Proxy.should_receive(:new).
|
37
|
+
with(env, app.signer).and_return(proxy)
|
38
|
+
|
39
|
+
app.call(env)
|
40
|
+
env['rack.url_auth'].should be proxy
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'forwards to app' do
|
44
|
+
inner_app.should_receive(:call).with(env)
|
45
|
+
app.call(env)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/spec/proxy_spec.rb
ADDED
@@ -0,0 +1,40 @@
|
|
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
|
data/spec/signer_spec.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
include Rack
|
4
|
+
|
5
|
+
describe UrlAuth::Signer do
|
6
|
+
let(:signer) { UrlAuth::Signer.new('my-secretive-secret') }
|
7
|
+
|
8
|
+
describe 'signing and validating messages' do
|
9
|
+
let(:message) { 'HMAC is fun!!' }
|
10
|
+
let(:tampered_message) { 'HMAC is fun!!!' }
|
11
|
+
|
12
|
+
it 'signs a messages' do
|
13
|
+
signature = signer.sign message
|
14
|
+
signature.should have(40).characters
|
15
|
+
|
16
|
+
signer.verify(message, signature).should be true
|
17
|
+
signer.verify(tampered_message, signature).should be false
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe 'signed urls' do
|
22
|
+
let(:url) { 'http://example.com:3000/path?token=1&query=sumething' }
|
23
|
+
let(:signed_url) { signer.sign_url url }
|
24
|
+
|
25
|
+
it 'appends signature' do
|
26
|
+
signed_url.should match %r{&signature=\w{40}}
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'keeps params' do
|
30
|
+
signed_url.should include '?token=1&query=sumething'
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'keeps port' do
|
34
|
+
signed_url.should match %{^http://example.com:3000}
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'verifies untampered url' do
|
38
|
+
signer.verify_url(signed_url).should be true
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'verifies false if url is tampered' do
|
42
|
+
signer.verify_url(signed_url.sub(/\.com/, '.me')).should be false
|
43
|
+
signer.verify_url(signed_url.sub('path', 'other-path')).should be false
|
44
|
+
signer.verify_url(signed_url.sub('1', '2')).should be false
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'raises error when url is unsigned while verifying url' do
|
48
|
+
lambda do
|
49
|
+
signer.verify_url 'http://example.com'
|
50
|
+
end.should raise_error UrlAuth::Signer::MissingSignature
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rack-url_auth
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- macario
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-06-20 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description: Middleware for signing urls
|
42
|
+
email:
|
43
|
+
- mail@makarius.me
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- .gitignore
|
49
|
+
- .rspec
|
50
|
+
- Gemfile
|
51
|
+
- Gemfile.lock
|
52
|
+
- LICENSE.txt
|
53
|
+
- README.md
|
54
|
+
- Rakefile
|
55
|
+
- lib/rack/url_auth.rb
|
56
|
+
- lib/rack/url_auth/proxy.rb
|
57
|
+
- lib/rack/url_auth/signer.rb
|
58
|
+
- lib/rack/url_auth/version.rb
|
59
|
+
- rack-signed_urls.gemspec
|
60
|
+
- spec/middleware_spec.rb
|
61
|
+
- spec/proxy_spec.rb
|
62
|
+
- spec/signer_spec.rb
|
63
|
+
- spec/spec_helper.rb
|
64
|
+
homepage: http://github.com/maca/rack-url_auth
|
65
|
+
licenses:
|
66
|
+
- MIT
|
67
|
+
metadata: {}
|
68
|
+
post_install_message:
|
69
|
+
rdoc_options: []
|
70
|
+
require_paths:
|
71
|
+
- lib
|
72
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - '>='
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '0'
|
82
|
+
requirements: []
|
83
|
+
rubyforge_project:
|
84
|
+
rubygems_version: 2.0.0.rc.2
|
85
|
+
signing_key:
|
86
|
+
specification_version: 4
|
87
|
+
summary: Middleware authorizing signed urls, so they can't be tampered
|
88
|
+
test_files:
|
89
|
+
- spec/middleware_spec.rb
|
90
|
+
- spec/proxy_spec.rb
|
91
|
+
- spec/signer_spec.rb
|
92
|
+
- spec/spec_helper.rb
|
93
|
+
has_rdoc:
|