url_authenticator 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +21 -0
- data/README.md +36 -0
- data/Rakefile +15 -0
- data/lib/url_authenticator.rb +60 -0
- data/test/signer_test.rb +16 -0
- data/test/test_helper.rb +2 -0
- data/test/url_authenticator_test.rb +16 -0
- data/test/verifier_test.rb +41 -0
- data/url_authenticator.gemspec +11 -0
- metadata +58 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT LICENSE
|
2
|
+
|
3
|
+
Copyright (c) 2010 Tomasz Werbicki <tomasz@werbicki.net>
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
UrlAuthenticator
|
2
|
+
================
|
3
|
+
|
4
|
+
A library to sign and verify signed URLs.
|
5
|
+
|
6
|
+
Usage
|
7
|
+
-----
|
8
|
+
|
9
|
+
require "url_authenticator"
|
10
|
+
|
11
|
+
url = "http://example.com"
|
12
|
+
signed_url = UrlAuthenticator.sign(url, "your_secret")
|
13
|
+
# => "http://example.com?expires=1323787739&signature=c064a2cbda335ed784387ad69abd1880"
|
14
|
+
|
15
|
+
UrlAuthenticator.verify(signed_url, "your_secret") # => true
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
# If you want to extend expire period (20 minutes default):
|
20
|
+
expires_at = Time.now + 40 * 60
|
21
|
+
signed_url = UrlAuthenticator.sign(url, "your_secret", expires_at)
|
22
|
+
# => "http://example.com?expires=1323789137&signature=813b0e16bd5bc3618dd84d2274e9c212"
|
23
|
+
|
24
|
+
|
25
|
+
# If you want to use different time for expiration verification (default Time.now):
|
26
|
+
now = Time.new(2000, 7, 7, 12, 30)
|
27
|
+
UrlAuthenticator.verify(signed_url, "your_secret", now) # => true
|
28
|
+
|
29
|
+
### Settings
|
30
|
+
|
31
|
+
UrlAuthenticator.default_secre = "your_secret"
|
32
|
+
|
33
|
+
License
|
34
|
+
-------
|
35
|
+
|
36
|
+
[MIT License](https://github.com/neaf/url_authenticator/blob/master/MIT-LICENSE)
|
data/Rakefile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
require 'rake/testtask'
|
3
|
+
|
4
|
+
dir = File.dirname(__FILE__)
|
5
|
+
|
6
|
+
task :default => :test
|
7
|
+
|
8
|
+
Rake::TestTask.new do |t|
|
9
|
+
t.libs << "test"
|
10
|
+
t.test_files = Dir.glob("#{dir}/test/*_test.rb").sort
|
11
|
+
t.warning = true
|
12
|
+
end
|
13
|
+
|
14
|
+
desc "Run gem tests by default"
|
15
|
+
task :default => :test
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require "uri"
|
2
|
+
require "cgi"
|
3
|
+
require "openssl"
|
4
|
+
|
5
|
+
module UrlAuthenticator
|
6
|
+
class << self
|
7
|
+
attr_accessor :default_secret
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.sign(url, secret = nil, expires = nil)
|
11
|
+
secret ||= default_secret
|
12
|
+
raise ArgumentError.new("Pass secret explicitly or set default_secret for UrlAuthenticator") unless secret
|
13
|
+
Signer.new(secret, expires).sign(url)
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.verify(url, secret = nil, now = nil)
|
17
|
+
secret ||= default_secret
|
18
|
+
raise ArgumentError.new("Pass secret explicitly or set default_secret for UrlAuthenticator") unless secret
|
19
|
+
Verifier.new(secret, now).verify(url)
|
20
|
+
end
|
21
|
+
|
22
|
+
class Verifier
|
23
|
+
def initialize(secret, now = nil)
|
24
|
+
@secret = secret
|
25
|
+
@now = (now || Time.now).utc.to_i
|
26
|
+
end
|
27
|
+
|
28
|
+
def verify(url)
|
29
|
+
uri = URI.parse(url)
|
30
|
+
params = CGI.parse(uri.query || "")
|
31
|
+
expires = params["expires"].first.to_i
|
32
|
+
signature = params["signature"].first
|
33
|
+
signature_valid(url, signature) && @now <= expires
|
34
|
+
end
|
35
|
+
|
36
|
+
def signature_valid(url, signature)
|
37
|
+
unsigned = url.sub(/(\?|&)signature=#{signature}/, "")
|
38
|
+
OpenSSL::HMAC.hexdigest("md5", @secret, unsigned) == signature
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
class Signer
|
43
|
+
def initialize(secret, expires = nil)
|
44
|
+
@secret = secret
|
45
|
+
@expires = (expires || Time.now + 20 * 60).utc.to_i
|
46
|
+
end
|
47
|
+
|
48
|
+
def sign(url)
|
49
|
+
url = append_param(url, "expires", @expires)
|
50
|
+
signature = OpenSSL::HMAC.hexdigest("md5", @secret, url)
|
51
|
+
append_param(url, "signature", signature)
|
52
|
+
end
|
53
|
+
|
54
|
+
def append_param(url, name, value)
|
55
|
+
parameter = [name, value].join('=')
|
56
|
+
separator = url.include?('?') ? '&' : '?'
|
57
|
+
[url, parameter].join(separator)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/test/signer_test.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper.rb'
|
2
|
+
|
3
|
+
class SignerTest < Test::Unit::TestCase
|
4
|
+
EXPIRES_TIME = Time.utc(2011, 12, 12, 12, 30)
|
5
|
+
SECRET = "password"
|
6
|
+
VALID_URL = "http://themes.cardflick.co/themes?expires=1323693000&signature=adeb9e4c42661f04121f51bb53ddb10a"
|
7
|
+
BASE_URL = "http://themes.cardflick.co/themes"
|
8
|
+
|
9
|
+
def signer(time=EXPIRES_TIME)
|
10
|
+
UrlAuthenticator::Signer.new(SECRET, time)
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_sign_returns_signed_url
|
14
|
+
assert_equal VALID_URL, signer.sign(BASE_URL)
|
15
|
+
end
|
16
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper.rb'
|
2
|
+
|
3
|
+
class UrlAuthenticatorTest < Test::Unit::TestCase
|
4
|
+
SECRET = "password"
|
5
|
+
BASE_URL = "http://themes.cardflick.co/themes"
|
6
|
+
|
7
|
+
def test_api_cohesion
|
8
|
+
signed = UrlAuthenticator.sign(BASE_URL, SECRET)
|
9
|
+
assert UrlAuthenticator.verify(signed, SECRET)
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_api_correctnes
|
13
|
+
signed = UrlAuthenticator.sign(BASE_URL, "first")
|
14
|
+
assert !UrlAuthenticator.verify(signed, "second")
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper.rb'
|
2
|
+
|
3
|
+
class VerifierTest < Test::Unit::TestCase
|
4
|
+
GENERATION_TIME = Time.utc(2011, 12, 12, 12, 0)
|
5
|
+
EXPIRES_TIME = Time.utc(2011, 12, 12, 12, 30)
|
6
|
+
SECRET = "password"
|
7
|
+
VALID_URL = "http://themes.cardflick.co/themes?expires=1323693000&signature=adeb9e4c42661f04121f51bb53ddb10a"
|
8
|
+
NO_EXPIRES_URL = "http://themes.cardflick.co/themes?signature=daac5be63c57def09223748d76d713f0"
|
9
|
+
INVALID_URL = "http://themes.cardflick.co/themes?expires=1323693000&signature=adeb9e4c42661f04121f51bb53ddb20b"
|
10
|
+
NO_SIG_URL = "http://themes.cardflick.co/themes?expires=1323693000"
|
11
|
+
BASE_URL = "http://themes.cardflick.co/themes"
|
12
|
+
|
13
|
+
def verifier(time=GENERATION_TIME)
|
14
|
+
UrlAuthenticator::Verifier.new(SECRET, time)
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_verify_returns_true_for_correct_signature
|
18
|
+
assert verifier.verify(VALID_URL)
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_verify_returns_false_when_timestamp_is_stale
|
22
|
+
stale = EXPIRES_TIME + 1
|
23
|
+
assert !verifier(stale).verify(VALID_URL)
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_verify_returns_false_when_incorrect_signature
|
27
|
+
assert !verifier.verify(INVALID_URL)
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_verify_returns_false_when_no_signature
|
31
|
+
assert !verifier.verify(NO_SIG_URL)
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_verify_without_expires_is_false
|
35
|
+
assert !verifier.verify(NO_EXPIRES_URL)
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_verify_works_when_no_params
|
39
|
+
assert !verifier.verify(BASE_URL)
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = %q{url_authenticator}
|
3
|
+
s.version = "0.0.1"
|
4
|
+
s.date = %q{2011-12-13}
|
5
|
+
s.summary = %q{Helper classes for signing and verifying signed URLs with expiration time.}
|
6
|
+
s.authors = ["Tomasz Werbicki", "Tomasz Paczkowski"]
|
7
|
+
s.homepage = "https://github.com/neaf/url_authenticator"
|
8
|
+
s.files = `git ls-files`.split("\n")
|
9
|
+
s.test_files = `git ls-files -- test/*`.split("\n")
|
10
|
+
s.require_paths = ["lib"]
|
11
|
+
end
|
metadata
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: url_authenticator
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Tomasz Werbicki
|
9
|
+
- Tomasz Paczkowski
|
10
|
+
autorequire:
|
11
|
+
bindir: bin
|
12
|
+
cert_chain: []
|
13
|
+
date: 2011-12-13 00:00:00.000000000Z
|
14
|
+
dependencies: []
|
15
|
+
description:
|
16
|
+
email:
|
17
|
+
executables: []
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- MIT-LICENSE
|
22
|
+
- README.md
|
23
|
+
- Rakefile
|
24
|
+
- lib/url_authenticator.rb
|
25
|
+
- test/signer_test.rb
|
26
|
+
- test/test_helper.rb
|
27
|
+
- test/url_authenticator_test.rb
|
28
|
+
- test/verifier_test.rb
|
29
|
+
- url_authenticator.gemspec
|
30
|
+
homepage: https://github.com/neaf/url_authenticator
|
31
|
+
licenses: []
|
32
|
+
post_install_message:
|
33
|
+
rdoc_options: []
|
34
|
+
require_paths:
|
35
|
+
- lib
|
36
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
37
|
+
none: false
|
38
|
+
requirements:
|
39
|
+
- - ! '>='
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
42
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
43
|
+
none: false
|
44
|
+
requirements:
|
45
|
+
- - ! '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
requirements: []
|
49
|
+
rubyforge_project:
|
50
|
+
rubygems_version: 1.8.10
|
51
|
+
signing_key:
|
52
|
+
specification_version: 3
|
53
|
+
summary: Helper classes for signing and verifying signed URLs with expiration time.
|
54
|
+
test_files:
|
55
|
+
- test/signer_test.rb
|
56
|
+
- test/test_helper.rb
|
57
|
+
- test/url_authenticator_test.rb
|
58
|
+
- test/verifier_test.rb
|