hawk-auth 0.2.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 +7 -0
- data/LICENSE +2 -2
- data/lib/hawk.rb +1 -0
- data/lib/hawk/authentication_failure.rb +1 -1
- data/lib/hawk/authorization_header.rb +11 -9
- data/lib/hawk/client.rb +1 -1
- data/lib/hawk/crypto.rb +165 -54
- data/lib/hawk/server.rb +12 -9
- data/lib/hawk/timestamp_mac_header.rb +30 -0
- data/lib/hawk/version.rb +1 -1
- data/spec/client_spec.rb +4 -4
- data/spec/crypto_spec.rb +3 -1
- data/spec/server_spec.rb +43 -5
- metadata +10 -19
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 0520600ff04a5b34f08821c26c42350db21ee2b4
|
4
|
+
data.tar.gz: 6bd61486e985287d0cc944595444f4f9012bc736
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 0b8136675219d0dfb65acb94022f5fc14b1b4595e61fe2391ecf8969b1e3fc0420b19b0c62ee52d54ad9de4650c8891c4c4a675704f0c2ccb3df244c281023e9
|
7
|
+
data.tar.gz: 567bd2820b6a62f80337d37d1c45899d425e770030b060447b1cd92f25aadb06a2542815ef1604692390323ea2c75993eb3a1090a0ffe417efac3f1e5f7fbe80
|
data/LICENSE
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Copyright (c) 2013
|
1
|
+
Copyright (c) 2013 Tent.is, LLC. All rights reserved.
|
2
2
|
|
3
3
|
Redistribution and use in source and binary forms, with or without
|
4
4
|
modification, are permitted provided that the following conditions are
|
@@ -10,7 +10,7 @@ notice, this list of conditions and the following disclaimer.
|
|
10
10
|
copyright notice, this list of conditions and the following disclaimer
|
11
11
|
in the documentation and/or other materials provided with the
|
12
12
|
distribution.
|
13
|
-
* Neither the name of
|
13
|
+
* Neither the name of Tent.is, LLC nor the names of its
|
14
14
|
contributors may be used to endorse or promote products derived from
|
15
15
|
this software without specific prior written permission.
|
16
16
|
|
data/lib/hawk.rb
CHANGED
@@ -8,7 +8,7 @@ module Hawk
|
|
8
8
|
def header
|
9
9
|
timestamp = Time.now.to_i
|
10
10
|
if @options[:credentials]
|
11
|
-
timestamp_mac = Crypto.ts_mac(:ts => timestamp, :credentials => @options[:credentials])
|
11
|
+
timestamp_mac = Crypto.ts_mac(:ts => timestamp, :credentials => @options[:credentials]).to_s
|
12
12
|
%(Hawk ts="#{timestamp}", tsm="#{timestamp_mac}", error="#{message}")
|
13
13
|
else
|
14
14
|
%(Hawk error="#{message}")
|
@@ -34,14 +34,14 @@ module Hawk
|
|
34
34
|
raise InvalidAlgorithmError.new("#{credentials[:algorithm].inspect} is not a supported algorithm! Use one of the following: #{SUPPORTED_ALGORITHMS.join(', ')}")
|
35
35
|
end
|
36
36
|
|
37
|
-
hash = Crypto.hash(options)
|
37
|
+
hash = Crypto.hash(options).to_s
|
38
38
|
mac = Crypto.mac(options)
|
39
39
|
|
40
40
|
parts = {
|
41
41
|
:id => credentials[:id],
|
42
42
|
:ts => options[:ts],
|
43
43
|
:nonce => options[:nonce],
|
44
|
-
:mac => mac
|
44
|
+
:mac => mac.to_s
|
45
45
|
}
|
46
46
|
parts[:hash] = hash if options.has_key?(:payload) && !options[:payload].nil?
|
47
47
|
parts[:ext] = options[:ext] if options.has_key?(:ext)
|
@@ -89,21 +89,23 @@ module Hawk
|
|
89
89
|
end
|
90
90
|
end
|
91
91
|
|
92
|
-
|
92
|
+
mac_opts = options.merge(
|
93
93
|
:credentials => credentials,
|
94
94
|
:ts => parts[:ts],
|
95
95
|
:nonce => parts[:nonce],
|
96
96
|
:ext => parts[:ext],
|
97
97
|
:app => options[:app] || parts[:app],
|
98
98
|
:dig => options[:dig] || parts[:dig]
|
99
|
-
)
|
100
|
-
unless expected_mac == parts[:mac]
|
101
|
-
return AuthenticationFailure.new(:mac, "Invalid mac")
|
102
|
-
end
|
99
|
+
)
|
103
100
|
|
104
101
|
expected_hash = parts[:hash] ? Crypto.hash(options.merge(:credentials => credentials)) : nil
|
105
|
-
if expected_hash && expected_hash != parts[:hash]
|
106
|
-
return AuthenticationFailure.new(:hash, "Invalid hash")
|
102
|
+
if expected_hash && expected_hash.to_s != parts[:hash]
|
103
|
+
return AuthenticationFailure.new(:hash, "Invalid hash. #{expected_hash.normalized_string}")
|
104
|
+
end
|
105
|
+
|
106
|
+
expected_mac = Crypto.mac(mac_opts)
|
107
|
+
unless expected_mac.eql?(parts[:mac])
|
108
|
+
return AuthenticationFailure.new(:mac, "Invalid mac. #{expected_mac.normalized_string}")
|
107
109
|
end
|
108
110
|
|
109
111
|
credentials
|
data/lib/hawk/client.rb
CHANGED
@@ -14,7 +14,7 @@ module Hawk
|
|
14
14
|
|
15
15
|
def calculate_time_offset(authorization_header, options)
|
16
16
|
parts = AuthorizationHeader.parse(authorization_header)
|
17
|
-
expected_mac = Crypto.ts_mac(:ts => parts[:ts], :credentials => options[:credentials])
|
17
|
+
expected_mac = Crypto.ts_mac(:ts => parts[:ts], :credentials => options[:credentials]).to_s
|
18
18
|
return unless expected_mac == parts[:tsm]
|
19
19
|
parts[:ts].to_i - Time.now.to_i
|
20
20
|
end
|
data/lib/hawk/crypto.rb
CHANGED
@@ -22,82 +22,193 @@ module Hawk
|
|
22
22
|
module Crypto
|
23
23
|
extend self
|
24
24
|
|
25
|
-
|
26
|
-
|
25
|
+
class Base
|
26
|
+
def to_s(options = {})
|
27
|
+
if options[:raw]
|
28
|
+
digest
|
29
|
+
else
|
30
|
+
encode64
|
31
|
+
end
|
32
|
+
end
|
27
33
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
parts << nil # trailing newline
|
34
|
+
def encode64
|
35
|
+
Base64.encode64(digest).chomp
|
36
|
+
end
|
32
37
|
|
33
|
-
|
34
|
-
|
38
|
+
def ==(other)
|
39
|
+
if self.class === other
|
40
|
+
secure_compare(to_s(:raw => true), other.to_s(:raw => true))
|
41
|
+
else
|
42
|
+
# assume base64 encoded mac
|
43
|
+
secure_compare(to_s(:raw => true), Base64.decode64(other))
|
44
|
+
end
|
45
|
+
end
|
35
46
|
|
36
|
-
|
37
|
-
|
38
|
-
if !options[:hash] && options.has_key?(:payload) && !options[:payload].nil?
|
39
|
-
options[:hash] = hash(options)
|
47
|
+
def eql?(other)
|
48
|
+
self == other
|
40
49
|
end
|
41
50
|
|
42
|
-
|
51
|
+
private
|
52
|
+
|
53
|
+
def secure_compare(a, b)
|
54
|
+
return false if a.empty? || b.empty? || a.bytesize != b.bytesize
|
55
|
+
b_bytes = b.unpack "C#{b.bytesize}"
|
56
|
+
|
57
|
+
res = 0
|
58
|
+
a.each_byte { |byte| res |= byte ^ b_bytes.shift }
|
59
|
+
res == 0
|
60
|
+
end
|
43
61
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
parts << options[:request_uri]
|
49
|
-
parts << options[:host]
|
50
|
-
parts << options[:port]
|
51
|
-
parts << options[:hash]
|
52
|
-
parts << options[:ext]
|
62
|
+
def openssl_digest(algorithm)
|
63
|
+
OpenSSL::Digest.const_get(algorithm.upcase)
|
64
|
+
end
|
65
|
+
end
|
53
66
|
|
54
|
-
|
55
|
-
|
56
|
-
|
67
|
+
class Mac < Base
|
68
|
+
def initialize(key, options, algorithm = 'sha256')
|
69
|
+
@key, @options, @algorithm = key, options, algorithm
|
57
70
|
end
|
58
71
|
|
59
|
-
|
72
|
+
def normalized_string
|
73
|
+
options = @options.dup
|
74
|
+
if !options[:hash] && options.has_key?(:payload) && !options[:payload].nil?
|
75
|
+
options[:hash] = Crypto.hash(options)
|
76
|
+
end
|
77
|
+
|
78
|
+
parts = []
|
79
|
+
|
80
|
+
parts << "hawk.1.#{options[:type] || 'header'}"
|
81
|
+
parts << options[:ts]
|
82
|
+
parts << options[:nonce]
|
83
|
+
parts << options[:method].to_s.upcase
|
84
|
+
parts << options[:request_uri]
|
85
|
+
parts << options[:host]
|
86
|
+
parts << options[:port]
|
87
|
+
parts << options[:hash]
|
88
|
+
parts << options[:ext]
|
89
|
+
|
90
|
+
if options[:app]
|
91
|
+
parts << options[:app]
|
92
|
+
parts << options[:dig]
|
93
|
+
end
|
94
|
+
|
95
|
+
parts << nil # trailing newline
|
60
96
|
|
61
|
-
|
97
|
+
parts.join("\n")
|
98
|
+
end
|
99
|
+
|
100
|
+
def digest
|
101
|
+
@digest ||= OpenSSL::HMAC.digest(openssl_digest(@algorithm).new, @key, normalized_string)
|
102
|
+
end
|
62
103
|
end
|
63
104
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
105
|
+
class Hash < Base
|
106
|
+
def initialize(content_type, payload, algorithm)
|
107
|
+
@content_type, @payload, @algorithm = content_type, payload, algorithm
|
108
|
+
end
|
109
|
+
|
110
|
+
def normalized_string
|
111
|
+
@normalized_string ||= begin
|
112
|
+
parts = []
|
113
|
+
|
114
|
+
parts << "hawk.1.payload"
|
115
|
+
parts << @content_type
|
116
|
+
parts << @payload.to_s
|
117
|
+
parts << nil # trailing newline
|
118
|
+
|
119
|
+
parts.join("\n")
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def digest
|
124
|
+
@digest ||= openssl_digest(@algorithm).digest(normalized_string)
|
125
|
+
end
|
72
126
|
end
|
73
127
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
128
|
+
class TSMac < Base
|
129
|
+
def initialize(key, ts, algorithm = 'sha256')
|
130
|
+
@key, @ts, @algorithm = key, ts, algorithm
|
131
|
+
end
|
132
|
+
|
133
|
+
def normalized_string
|
134
|
+
@normalized_string ||= "hawk.1.ts\n#{@ts}\n"
|
135
|
+
end
|
136
|
+
|
137
|
+
def digest
|
138
|
+
@digest ||= OpenSSL::HMAC.digest(openssl_digest(@algorithm).new, @key, normalized_string)
|
139
|
+
end
|
82
140
|
end
|
83
141
|
|
84
|
-
|
85
|
-
|
142
|
+
class Bewit < Base
|
143
|
+
def self.decode(bewit)
|
144
|
+
padding = '=' * ((4 - bewit.size) % 4)
|
145
|
+
id, timestamp, mac, ext = Base64.decode64(bewit + padding).split('\\')
|
146
|
+
|
147
|
+
new(id, nil, { :mac => mac, :ext => ext, :ts => timestamp }, nil)
|
148
|
+
end
|
86
149
|
|
87
|
-
|
150
|
+
attr_reader :id, :ts, :ext
|
151
|
+
def initialize(id, key, options, algorithm = 'sha256')
|
152
|
+
@ts = options[:ts] ||= Time.now.to_i + options[:ttl].to_i
|
153
|
+
@ext = options[:ext]
|
154
|
+
@id, @key, @options, @algorithm = id, key, options.dup, algorithm
|
155
|
+
@mac = options.delete(:mac) if options[:mac]
|
156
|
+
end
|
157
|
+
|
158
|
+
def mac
|
159
|
+
@mac ||= Crypto::Mac.new(@key, @options.merge(:type => 'bewit'), @algorithm)
|
160
|
+
end
|
161
|
+
|
162
|
+
def normalized_string
|
163
|
+
@normalized_string ||= begin
|
164
|
+
parts = []
|
88
165
|
|
89
|
-
|
166
|
+
parts << @id
|
167
|
+
parts << @ts
|
168
|
+
parts << mac.to_s
|
169
|
+
parts << @ext
|
90
170
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
171
|
+
parts.join("\\")
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
def encode64
|
176
|
+
@encoded ||= Base64.urlsafe_encode64(normalized_string).chomp.sub(/=+\Z/, '')
|
177
|
+
end
|
95
178
|
|
96
|
-
|
179
|
+
def to_s(options = {})
|
180
|
+
encode64
|
181
|
+
end
|
182
|
+
|
183
|
+
def ==(other)
|
184
|
+
if self.class === other
|
185
|
+
mac == other.mac
|
186
|
+
else
|
187
|
+
# assume base64 encoded bewit
|
188
|
+
self == self.class.decode(other)
|
189
|
+
end
|
190
|
+
end
|
97
191
|
end
|
98
192
|
|
99
|
-
def
|
100
|
-
|
193
|
+
def hash(options)
|
194
|
+
Hash.new(options[:content_type], options[:payload], options[:credentials][:algorithm])
|
195
|
+
end
|
196
|
+
|
197
|
+
def mac(options)
|
198
|
+
Mac.new(options[:credentials][:key], options, options[:credentials][:algorithm])
|
199
|
+
end
|
200
|
+
|
201
|
+
def ts_mac(options)
|
202
|
+
TSMac.new(options[:credentials][:key], options[:ts], options[:credentials][:algorithm])
|
203
|
+
end
|
204
|
+
|
205
|
+
def bewit(options)
|
206
|
+
Bewit.new(
|
207
|
+
options[:credentials][:id],
|
208
|
+
options[:credentials][:key],
|
209
|
+
options,
|
210
|
+
options[:credentials][:algorithm]
|
211
|
+
)
|
101
212
|
end
|
102
213
|
end
|
103
214
|
end
|
data/lib/hawk/server.rb
CHANGED
@@ -6,15 +6,14 @@ module Hawk
|
|
6
6
|
Hawk::AuthorizationHeader.authenticate(authorization_header, options)
|
7
7
|
end
|
8
8
|
|
9
|
-
def authenticate_bewit(
|
10
|
-
|
11
|
-
id, timestamp, mac, ext = Base64.decode64(bewit + padding).split('\\')
|
9
|
+
def authenticate_bewit(encoded_bewit, options)
|
10
|
+
bewit = Crypto::Bewit.decode(encoded_bewit)
|
12
11
|
|
13
|
-
unless options[:credentials_lookup].respond_to?(:call) && (credentials = options[:credentials_lookup].call(id))
|
12
|
+
unless options[:credentials_lookup].respond_to?(:call) && (credentials = options[:credentials_lookup].call(bewit.id))
|
14
13
|
return AuthenticationFailure.new(:id, "Unidentified id")
|
15
14
|
end
|
16
15
|
|
17
|
-
if Time.at(
|
16
|
+
if Time.at(bewit.ts.to_i) < Time.now
|
18
17
|
return AuthenticationFailure.new(:ts, "Stale timestamp")
|
19
18
|
end
|
20
19
|
|
@@ -24,13 +23,13 @@ module Hawk
|
|
24
23
|
:request_uri => remove_bewit_param_from_path(options[:request_uri]),
|
25
24
|
:port => options[:port],
|
26
25
|
:method => options[:method],
|
27
|
-
:ts =>
|
28
|
-
:ext => ext
|
26
|
+
:ts => bewit.ts,
|
27
|
+
:ext => bewit.ext
|
29
28
|
)
|
30
29
|
|
31
|
-
unless expected_bewit
|
30
|
+
unless expected_bewit.eql?(bewit)
|
32
31
|
if options[:request_uri].to_s =~ /\Ahttp/
|
33
|
-
return authenticate_bewit(
|
32
|
+
return authenticate_bewit(encoded_bewit, options.merge(
|
34
33
|
:request_uri => options[:request_uri].sub(%r{\Ahttps?://[^/]+}, '')
|
35
34
|
))
|
36
35
|
else
|
@@ -45,6 +44,10 @@ module Hawk
|
|
45
44
|
Hawk::AuthorizationHeader.build(options, [:hash, :ext, :mac])
|
46
45
|
end
|
47
46
|
|
47
|
+
def build_tsm_header(options)
|
48
|
+
Hawk::TimestampMacHeader.build(options)
|
49
|
+
end
|
50
|
+
|
48
51
|
private
|
49
52
|
|
50
53
|
def remove_bewit_param_from_path(path)
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Hawk
|
2
|
+
module TimestampMacHeader
|
3
|
+
extend self
|
4
|
+
|
5
|
+
REQUIRED_CREDENTIAL_MEMBERS = AuthorizationHeader::REQUIRED_CREDENTIAL_MEMBERS
|
6
|
+
SUPPORTED_ALGORITHMS = AuthorizationHeader::SUPPORTED_ALGORITHMS
|
7
|
+
|
8
|
+
InvalidCredentialsError = Class.new(StandardError)
|
9
|
+
InvalidAlgorithmError = Class.new(StandardError)
|
10
|
+
|
11
|
+
def build(options)
|
12
|
+
options[:ts] ||= Time.now.to_i
|
13
|
+
|
14
|
+
credentials = options[:credentials]
|
15
|
+
REQUIRED_CREDENTIAL_MEMBERS.each do |key|
|
16
|
+
unless credentials.has_key?(key)
|
17
|
+
raise InvalidCredentialsError.new("#{key.inspect} is missing!")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
unless SUPPORTED_ALGORITHMS.include?(credentials[:algorithm])
|
22
|
+
raise InvalidAlgorithmError.new("#{credentials[:algorithm].inspect} is not a supported algorithm! Use one of the following: #{SUPPORTED_ALGORITHMS.join(', ')}")
|
23
|
+
end
|
24
|
+
|
25
|
+
tsm = Crypto.ts_mac(options)
|
26
|
+
|
27
|
+
%(Hawk ts="#{options[:ts]}", tsm="#{tsm}")
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/hawk/version.rb
CHANGED
data/spec/client_spec.rb
CHANGED
@@ -40,8 +40,8 @@ describe Hawk::Client do
|
|
40
40
|
_input
|
41
41
|
end
|
42
42
|
|
43
|
-
let(:expected_mac) { Hawk::Crypto.mac(client_input) }
|
44
|
-
let(:expected_hash) { client_input[:payload] ? Hawk::Crypto.hash(client_input) : nil }
|
43
|
+
let(:expected_mac) { Hawk::Crypto.mac(client_input).to_s }
|
44
|
+
let(:expected_hash) { client_input[:payload] ? Hawk::Crypto.hash(client_input).to_s : nil }
|
45
45
|
|
46
46
|
let(:authorization_header) do
|
47
47
|
parts = []
|
@@ -74,8 +74,8 @@ describe Hawk::Client do
|
|
74
74
|
Time.stubs(:now).returns(now)
|
75
75
|
end
|
76
76
|
|
77
|
-
let(:expected_mac) { Hawk::Crypto.mac(input) }
|
78
|
-
let(:expected_hash) { input[:payload] ? Hawk::Crypto.hash(input) : nil }
|
77
|
+
let(:expected_mac) { Hawk::Crypto.mac(input).to_s }
|
78
|
+
let(:expected_hash) { input[:payload] ? Hawk::Crypto.hash(input).to_s : nil }
|
79
79
|
|
80
80
|
let(:input) do
|
81
81
|
_input = {
|
data/spec/crypto_spec.rb
CHANGED
@@ -125,13 +125,15 @@ describe Hawk::Crypto do
|
|
125
125
|
expect(described_class.ts_mac(input)).to eql("h/Ff6XI1euObD78ZNflapvLKXGuaw1RiLI4Q6Q5sAbM=")
|
126
126
|
end
|
127
127
|
end
|
128
|
+
end
|
128
129
|
|
130
|
+
describe Hawk::Crypto::Mac do
|
129
131
|
describe ".normalized_string" do
|
130
132
|
let(:normalization_method) { "normalized_string" }
|
131
133
|
|
132
134
|
shared_examples "an input normalization method" do
|
133
135
|
it "returns a valid normalized string" do
|
134
|
-
expect(described_class.
|
136
|
+
expect(described_class.new(nil, input, nil).send(normalization_method)).to eql(expected_output)
|
135
137
|
end
|
136
138
|
end
|
137
139
|
|
data/spec/server_spec.rb
CHANGED
@@ -54,8 +54,8 @@ describe Hawk::Server do
|
|
54
54
|
_input
|
55
55
|
end
|
56
56
|
|
57
|
-
let(:expected_mac) { Hawk::Crypto.mac(client_input) }
|
58
|
-
let(:expected_hash) { client_input[:payload] ? Hawk::Crypto.hash(client_input) : nil }
|
57
|
+
let(:expected_mac) { Hawk::Crypto.mac(client_input).to_s }
|
58
|
+
let(:expected_hash) { client_input[:payload] ? Hawk::Crypto.hash(client_input).to_s : nil }
|
59
59
|
|
60
60
|
let(:authorization_header) do
|
61
61
|
parts = []
|
@@ -116,7 +116,7 @@ describe Hawk::Server do
|
|
116
116
|
it "returns error object" do
|
117
117
|
actual = described_class.authenticate(authorization_header, input)
|
118
118
|
expect(actual).to be_a(Hawk::AuthenticationFailure)
|
119
|
-
expect(actual.key).to eql(:
|
119
|
+
expect(actual.key).to eql(:hash)
|
120
120
|
expect(actual.message).to_not eql(nil)
|
121
121
|
end
|
122
122
|
end
|
@@ -176,8 +176,8 @@ describe Hawk::Server do
|
|
176
176
|
end
|
177
177
|
|
178
178
|
describe ".build_authorization_header" do
|
179
|
-
let(:expected_mac) { Hawk::Crypto.mac(input) }
|
180
|
-
let(:expected_hash) { input[:payload] ? Hawk::Crypto.hash(input) : nil }
|
179
|
+
let(:expected_mac) { Hawk::Crypto.mac(input).to_s }
|
180
|
+
let(:expected_hash) { input[:payload] ? Hawk::Crypto.hash(input).to_s : nil }
|
181
181
|
let(:timestamp) { Time.now.to_i }
|
182
182
|
let(:nonce) { 'Ygvqdz' }
|
183
183
|
|
@@ -221,6 +221,44 @@ describe Hawk::Server do
|
|
221
221
|
end
|
222
222
|
end
|
223
223
|
|
224
|
+
describe ".build_tsm_header" do
|
225
|
+
let(:expected_tsm) { Hawk::Crypto.ts_mac(input).to_s }
|
226
|
+
let(:timestamp) { Time.now.to_i }
|
227
|
+
|
228
|
+
let(:input) do
|
229
|
+
{
|
230
|
+
:credentials => credentials,
|
231
|
+
:ts => timestamp
|
232
|
+
}
|
233
|
+
end
|
234
|
+
|
235
|
+
let(:expected_output_parts) do
|
236
|
+
[
|
237
|
+
%(ts="#{timestamp}"),
|
238
|
+
%(tsm="#{expected_tsm}")
|
239
|
+
]
|
240
|
+
end
|
241
|
+
|
242
|
+
let(:expected_output) do
|
243
|
+
"Hawk #{expected_output_parts.join(', ')}"
|
244
|
+
end
|
245
|
+
|
246
|
+
context "when using sha256" do
|
247
|
+
let(:algorithm) { "sha256" }
|
248
|
+
|
249
|
+
it "builds tsm header" do
|
250
|
+
actual = described_class.build_tsm_header(input)
|
251
|
+
|
252
|
+
expected_output_parts.each do |expected_part|
|
253
|
+
matcher = Regexp === expected_part ? expected_part : Regexp.new(Regexp.escape(expected_part))
|
254
|
+
expect(actual).to match(matcher)
|
255
|
+
end
|
256
|
+
|
257
|
+
expect(actual).to eql(expected_output)
|
258
|
+
end
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
224
262
|
describe ".authenticate_bewit" do
|
225
263
|
shared_examples "authenticate_bewit" do
|
226
264
|
context "when valid" do
|
metadata
CHANGED
@@ -1,20 +1,18 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hawk-auth
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
5
|
-
prerelease:
|
4
|
+
version: 0.2.1
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Jesse Stuart
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date: 2013-
|
11
|
+
date: 2013-09-03 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: bundler
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
17
|
- - ~>
|
20
18
|
- !ruby/object:Gem::Version
|
@@ -22,7 +20,6 @@ dependencies:
|
|
22
20
|
type: :development
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
24
|
- - ~>
|
28
25
|
- !ruby/object:Gem::Version
|
@@ -30,23 +27,20 @@ dependencies:
|
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: rake
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
|
-
- -
|
31
|
+
- - '>='
|
36
32
|
- !ruby/object:Gem::Version
|
37
33
|
version: '0'
|
38
34
|
type: :development
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
|
-
- -
|
38
|
+
- - '>='
|
44
39
|
- !ruby/object:Gem::Version
|
45
40
|
version: '0'
|
46
41
|
- !ruby/object:Gem::Dependency
|
47
42
|
name: rspec
|
48
43
|
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
44
|
requirements:
|
51
45
|
- - ~>
|
52
46
|
- !ruby/object:Gem::Version
|
@@ -54,7 +48,6 @@ dependencies:
|
|
54
48
|
type: :development
|
55
49
|
prerelease: false
|
56
50
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
51
|
requirements:
|
59
52
|
- - ~>
|
60
53
|
- !ruby/object:Gem::Version
|
@@ -62,7 +55,6 @@ dependencies:
|
|
62
55
|
- !ruby/object:Gem::Dependency
|
63
56
|
name: mocha
|
64
57
|
requirement: !ruby/object:Gem::Requirement
|
65
|
-
none: false
|
66
58
|
requirements:
|
67
59
|
- - ~>
|
68
60
|
- !ruby/object:Gem::Version
|
@@ -70,7 +62,6 @@ dependencies:
|
|
70
62
|
type: :development
|
71
63
|
prerelease: false
|
72
64
|
version_requirements: !ruby/object:Gem::Requirement
|
73
|
-
none: false
|
74
65
|
requirements:
|
75
66
|
- - ~>
|
76
67
|
- !ruby/object:Gem::Version
|
@@ -95,6 +86,7 @@ files:
|
|
95
86
|
- lib/hawk/client.rb
|
96
87
|
- lib/hawk/crypto.rb
|
97
88
|
- lib/hawk/server.rb
|
89
|
+
- lib/hawk/timestamp_mac_header.rb
|
98
90
|
- lib/hawk/version.rb
|
99
91
|
- spec/authentication_header_spec.rb
|
100
92
|
- spec/client_spec.rb
|
@@ -104,27 +96,26 @@ files:
|
|
104
96
|
- spec/support/shared_examples/authorization_header.rb
|
105
97
|
homepage: ''
|
106
98
|
licenses: []
|
99
|
+
metadata: {}
|
107
100
|
post_install_message:
|
108
101
|
rdoc_options: []
|
109
102
|
require_paths:
|
110
103
|
- lib
|
111
104
|
required_ruby_version: !ruby/object:Gem::Requirement
|
112
|
-
none: false
|
113
105
|
requirements:
|
114
|
-
- -
|
106
|
+
- - '>='
|
115
107
|
- !ruby/object:Gem::Version
|
116
108
|
version: '0'
|
117
109
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
118
|
-
none: false
|
119
110
|
requirements:
|
120
|
-
- -
|
111
|
+
- - '>='
|
121
112
|
- !ruby/object:Gem::Version
|
122
113
|
version: '0'
|
123
114
|
requirements: []
|
124
115
|
rubyforge_project:
|
125
|
-
rubygems_version:
|
116
|
+
rubygems_version: 2.0.7
|
126
117
|
signing_key:
|
127
|
-
specification_version:
|
118
|
+
specification_version: 4
|
128
119
|
summary: Ruby implementation of Hawk
|
129
120
|
test_files:
|
130
121
|
- spec/authentication_header_spec.rb
|