warden-hmac-authentication 0.6.1 → 0.6.2

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.
data/README.md CHANGED
@@ -11,7 +11,7 @@ The gem also provides a small helper class that can be used to generate request
11
11
  ## Header-Based authentication
12
12
 
13
13
  The header-based authentication transports the authentication information in the (misnamed) `Authorization` HTTP-Header. The primary
14
- advantage of header-based authentication is that request urls are stable even if authentication information changes. The improves
14
+ advantage of header-based authentication is that request urls are stable even if authentication information changes. This improves
15
15
  cacheability of the resource.
16
16
 
17
17
  Header-based authentication is supported by the `:hmac_header` strategy.
@@ -138,9 +138,9 @@ No authentication attempt is made if the scheme name in the `Authorization` head
138
138
  ## Authentication Header Format
139
139
 
140
140
  The format of the Authentication Header can be controlled using the `:auth_header_format` directive. The given format string will be interpolated
141
- with all given options and the signature. The default value is `%{scheme} %{signature}` which will result in an auth header with a format such as `HMAC 539263f4f83878a4917d2f9c1521320c28b926a9`. The format string must contain at least the `scheme` and `signature` components.
141
+ with all given options and the signature. The default value is `%{auth_scheme} %{signature}` which will result in an auth header with a format such as `HMAC 539263f4f83878a4917d2f9c1521320c28b926a9`. The format string must contain at least the `scheme` and `signature` components.
142
142
 
143
- The `:auth_header_format` directive has a companion directive, `:auth_header_parse` which must be a regular expression. Any given regular expression will be evaluated against the authorization header. The results can be retrieved using the `parsed_auth_header` method. The regular expression must at least contain a pattern named `scheme` and pattern named `signature`. The default value for this directive is a regular expression that is auto-generated by translating the `:auth_header_format` setting to a regular expression that contains a named capture group for each named part of the format string. Each capture allows for word characters, plus, dash, underscore and dot. The default :auth_header_format `%{scheme} %{signature}` will be translated to `/(?<autschemeh_scheme>[-_+.\w]+) (?<signature>[-_+.\w]+)/`.
143
+ The `:auth_header_format` directive has a companion directive, `:auth_header_parse` which must be a regular expression. Any given regular expression will be evaluated against the authorization header. The results can be retrieved using the `parsed_auth_header` method. The regular expression must at least contain a pattern named `scheme` and pattern named `signature`. The default value for this directive is a regular expression that is auto-generated by translating the `:auth_header_format` setting to a regular expression that contains a named capture group for each named part of the format string. Each capture allows for word characters, plus, dash, underscore and dot. The default :auth_header_format `%{auth_scheme} %{signature}` will be translated to `/(?<auth_scheme>[-_+.\w]+) (?<signature>[-_+.\w]+)/`.
144
144
 
145
145
  See the section about multiple authentication secrets for a use-case and a comprehensive example.
146
146
 
@@ -326,7 +326,7 @@ secrets allows us to implement multiple signing keys:
326
326
  access_key_id = strategy.parsed_auth_header["access_key_id"]
327
327
  keys[access_key_id]
328
328
  },
329
- :auth_header_format => '%{scheme} %{access_key_id} %{signature}' }
329
+ :auth_header_format => '%{auth_scheme} %{access_key_id} %{signature}' }
330
330
  end
331
331
 
332
332
  This combination of settings uses a slightly different Format for the authorization header and transports the secret keys ID in the header of the form `HMAC KEY2 a59456da1f61f86e96622e283780f58b7428c892`
@@ -365,8 +365,18 @@ To simplify the generation of such urls, the `HMAC::Signer` accepts an `:extra_a
365
365
 
366
366
  The library includes a faraday middleware that can be used to sign requests made with the faraday http lib. The middleware accepts the same list of options as the HMAC::Signer class.
367
367
 
368
+ ### Example (query based)
369
+
370
+ Faraday.new(:url => "http://example.com") do |builder|
371
+ builder.use Faraday::Request::Hmac, secret, {:query_based => true, :extra_auth_params => {"access_key_id" => "KEY2"}}
372
+ builder.response :raise_error
373
+ builder.adapter :net_http
374
+ end
375
+
376
+ ### Example (header based with custom scheme name)
377
+
368
378
  Faraday.new(:url => "http://example.com") do |builder|
369
- builder.use Faraday::Request::Hmac, secret, {:extra_auth_params => {"access_key_id" => "KEY2"}}
379
+ builder.use Faraday::Request::Hmac, secret, {:auth_scheme => 'MYSCHEME', :auth_key => 'TESTKEYID', :auth_header_format => '%{auth_scheme} %{auth_key} %{signature}'}}
370
380
  builder.response :raise_error
371
381
  builder.adapter :net_http
372
382
  end
@@ -1,68 +1,16 @@
1
1
  #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'warden-hmac-authentication' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
2
8
 
3
- begin
4
- require 'trollop'
5
- rescue LoadError => e
6
- puts ""
7
- puts ""
8
- puts "============= ERROR ================"
9
- puts ""
10
- puts "You need trollop installed or in your gemfile to use the signer"
11
- puts ""
12
- puts "============= ERROR ================"
13
- puts ""
14
- puts ""
15
- exit(-1)
16
- end
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
17
12
 
18
- require 'hmac/signer'
13
+ require 'rubygems'
14
+ require 'bundler/setup'
19
15
 
20
- opts = Trollop::options do
21
-
22
- version "warden-hmac-sign 0.3.0 (c) 2011 Felix Gilcher, Florian Gilcher"
23
- banner <<-EOS
24
- warden-hmac-authentication is used to create and validate signed urls for
25
- usage with the HMAC authentication scheme used by
26
- https://github.com/Asquera/warden-hmac-authentication
27
-
28
- Usage:
29
- warden-hmac-authentication [options] <command> url
30
-
31
- where command is one of
32
-
33
- sign: signs the given url
34
- validate: validates the given url
35
-
36
- and where [options] are:
37
-
38
- EOS
39
-
40
- opt :algorithm, "The hashing algorithm to use for the HMAC", :type => :string, :default => "sha1"
41
- opt :secret, "The shared secret for the HMAC", :type => :string, :required => true
42
- opt :"auth-param", "The name for the auth param in the url", :default => "auth"
43
- opt :"date", "The date to use for the signature (defaults to now)"
44
- end
45
-
46
- cmd = ARGV.shift
47
- Trollop::die "You must give a command" if cmd.nil?
48
- Trollop::die "You command must be one of [sign, validate]" unless ["sign", "validate"].include? cmd
49
- Trollop::die "You must provide a URL" if ARGV.empty?
50
- url = ARGV.shift
51
-
52
- secret = opts.delete(:secret)
53
- algorithm = opts.delete(:algorithm)
54
-
55
- signer = HMAC::Signer.new(algorithm)
56
-
57
- if "sign" == cmd
58
- puts signer.sign_url(url, secret, opts)
59
- else
60
- success = signer.validate_url_signature(url, secret, opts)
61
- if success
62
- puts "URL #{url} is valid"
63
- exit 0
64
- else
65
- puts "URL #{url} does not contain a valid signature"
66
- exit 1
67
- end
68
- end
16
+ load Gem.bin_path('warden-hmac-authentication', 'warden-hmac-authentication')
@@ -16,7 +16,7 @@ module Faraday
16
16
  #
17
17
  # @option options [String] :auth_scheme ('HMAC') The name of the authorization scheme used in the Authorization header and to construct various header-names
18
18
  # @option options [String] :auth_param ('auth') The name of the authentication param to use for query based authentication
19
- # @option options [Hash] :extra_auth_params ({}) Additional parameters to inject in the auth parameter
19
+ # @option options [Hash] :extra_auth_params ({}) Additional parameters to inject in the auth parameter. This parameter is ignored unless :query_based evaluates to true.
20
20
  # @option options [String] :auth_header ('Authorization') The name of the authorization header to use
21
21
  # @option options [String] :auth_header_format ('%{auth_scheme} %{signature}') The format of the authorization header. Will be interpolated with the given options and the signature.
22
22
  # @option options [String] :nonce_header ('X-#{auth_scheme}-Nonce') The header name for the request nonce
data/lib/hmac/signer.rb CHANGED
@@ -105,7 +105,7 @@ module HMAC
105
105
  #
106
106
  # @return [Bool] true if the signature matches
107
107
  def validate_signature(signature, params)
108
- signature == generate_signature(params)
108
+ compare_hashes(signature, generate_signature(params))
109
109
  end
110
110
 
111
111
  # convienience method to check the signature of a url with query-based authentication
@@ -268,5 +268,18 @@ module HMAC
268
268
  url
269
269
  end
270
270
 
271
+ private
272
+
273
+ # compares two hashes in a manner that's invulnerable to timing sidechannel attacks (see issue #16)
274
+ # by comparing them characterwise up to the end in all cases, no matter where the mismatch happens
275
+ # short circuits if the length does not match since this does not allow timing sidechannel attacks.
276
+ def compare_hashes(presented, computed)
277
+ if computed.length == presented.length then
278
+ computed.chars.zip(presented.chars).map {|x,y| x == y}.all?
279
+ else
280
+ false
281
+ end
282
+ end
283
+
271
284
  end
272
285
  end
@@ -188,15 +188,15 @@ module Warden
188
188
  end
189
189
 
190
190
  def ttl
191
- config[:ttl].to_i
191
+ (config[:ttl] || 900).to_i
192
192
  end
193
193
 
194
194
  def check_ttl?
195
- !config[:ttl].nil?
195
+ !config.has_key?(:ttl) || !config[:ttl].nil?
196
196
  end
197
197
 
198
198
  def timestamp
199
- Time.strptime(request_timestamp, '%a, %e %b %Y %T %z') unless request_timestamp.nil?
199
+ Time.strptime(request_timestamp, '%a, %e %b %Y %T %z') unless request_timestamp.nil? || request_timestamp.empty?
200
200
  end
201
201
 
202
202
  def has_timestamp?
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: warden-hmac-authentication
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.1
4
+ version: 0.6.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,11 +10,11 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2012-04-13 00:00:00.000000000Z
13
+ date: 2012-07-09 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: addressable
17
- requirement: &2163603720 !ruby/object:Gem::Requirement
17
+ requirement: !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
20
  - - ! '>='
@@ -22,10 +22,15 @@ dependencies:
22
22
  version: '0'
23
23
  type: :runtime
24
24
  prerelease: false
25
- version_requirements: *2163603720
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ! '>='
29
+ - !ruby/object:Gem::Version
30
+ version: '0'
26
31
  - !ruby/object:Gem::Dependency
27
32
  name: rack
28
- requirement: &2163603260 !ruby/object:Gem::Requirement
33
+ requirement: !ruby/object:Gem::Requirement
29
34
  none: false
30
35
  requirements:
31
36
  - - ! '>='
@@ -33,10 +38,15 @@ dependencies:
33
38
  version: '0'
34
39
  type: :runtime
35
40
  prerelease: false
36
- version_requirements: *2163603260
41
+ version_requirements: !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ! '>='
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
37
47
  - !ruby/object:Gem::Dependency
38
48
  name: warden
39
- requirement: &2163602820 !ruby/object:Gem::Requirement
49
+ requirement: !ruby/object:Gem::Requirement
40
50
  none: false
41
51
  requirements:
42
52
  - - ! '>='
@@ -44,10 +54,15 @@ dependencies:
44
54
  version: '0'
45
55
  type: :runtime
46
56
  prerelease: false
47
- version_requirements: *2163602820
57
+ version_requirements: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ! '>='
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
48
63
  - !ruby/object:Gem::Dependency
49
64
  name: rake
50
- requirement: &2163602340 !ruby/object:Gem::Requirement
65
+ requirement: !ruby/object:Gem::Requirement
51
66
  none: false
52
67
  requirements:
53
68
  - - ! '>='
@@ -55,10 +70,15 @@ dependencies:
55
70
  version: '0'
56
71
  type: :development
57
72
  prerelease: false
58
- version_requirements: *2163602340
73
+ version_requirements: !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ! '>='
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
59
79
  - !ruby/object:Gem::Dependency
60
80
  name: rack-test
61
- requirement: &2163601920 !ruby/object:Gem::Requirement
81
+ requirement: !ruby/object:Gem::Requirement
62
82
  none: false
63
83
  requirements:
64
84
  - - ! '>='
@@ -66,10 +86,15 @@ dependencies:
66
86
  version: '0'
67
87
  type: :development
68
88
  prerelease: false
69
- version_requirements: *2163601920
89
+ version_requirements: !ruby/object:Gem::Requirement
90
+ none: false
91
+ requirements:
92
+ - - ! '>='
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
70
95
  - !ruby/object:Gem::Dependency
71
96
  name: riot
72
- requirement: &2163601480 !ruby/object:Gem::Requirement
97
+ requirement: !ruby/object:Gem::Requirement
73
98
  none: false
74
99
  requirements:
75
100
  - - ! '>='
@@ -77,10 +102,15 @@ dependencies:
77
102
  version: '0'
78
103
  type: :development
79
104
  prerelease: false
80
- version_requirements: *2163601480
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ none: false
107
+ requirements:
108
+ - - ! '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
81
111
  - !ruby/object:Gem::Dependency
82
112
  name: timecop
83
- requirement: &2163601060 !ruby/object:Gem::Requirement
113
+ requirement: !ruby/object:Gem::Requirement
84
114
  none: false
85
115
  requirements:
86
116
  - - ! '>='
@@ -88,10 +118,15 @@ dependencies:
88
118
  version: '0'
89
119
  type: :development
90
120
  prerelease: false
91
- version_requirements: *2163601060
121
+ version_requirements: !ruby/object:Gem::Requirement
122
+ none: false
123
+ requirements:
124
+ - - ! '>='
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
92
127
  - !ruby/object:Gem::Dependency
93
128
  name: simplecov
94
- requirement: &2163593440 !ruby/object:Gem::Requirement
129
+ requirement: !ruby/object:Gem::Requirement
95
130
  none: false
96
131
  requirements:
97
132
  - - ! '>='
@@ -99,10 +134,15 @@ dependencies:
99
134
  version: '0'
100
135
  type: :development
101
136
  prerelease: false
102
- version_requirements: *2163593440
137
+ version_requirements: !ruby/object:Gem::Requirement
138
+ none: false
139
+ requirements:
140
+ - - ! '>='
141
+ - !ruby/object:Gem::Version
142
+ version: '0'
103
143
  - !ruby/object:Gem::Dependency
104
144
  name: simplecov-html
105
- requirement: &2163593000 !ruby/object:Gem::Requirement
145
+ requirement: !ruby/object:Gem::Requirement
106
146
  none: false
107
147
  requirements:
108
148
  - - ! '>='
@@ -110,10 +150,15 @@ dependencies:
110
150
  version: '0'
111
151
  type: :development
112
152
  prerelease: false
113
- version_requirements: *2163593000
153
+ version_requirements: !ruby/object:Gem::Requirement
154
+ none: false
155
+ requirements:
156
+ - - ! '>='
157
+ - !ruby/object:Gem::Version
158
+ version: '0'
114
159
  - !ruby/object:Gem::Dependency
115
160
  name: trollop
116
- requirement: &2163592540 !ruby/object:Gem::Requirement
161
+ requirement: !ruby/object:Gem::Requirement
117
162
  none: false
118
163
  requirements:
119
164
  - - ! '>='
@@ -121,7 +166,12 @@ dependencies:
121
166
  version: '0'
122
167
  type: :development
123
168
  prerelease: false
124
- version_requirements: *2163592540
169
+ version_requirements: !ruby/object:Gem::Requirement
170
+ none: false
171
+ requirements:
172
+ - - ! '>='
173
+ - !ruby/object:Gem::Version
174
+ version: '0'
125
175
  description: ! "This gem provides request authentication via [HMAC](http://en.wikipedia.org/wiki/Hmac).
126
176
  The main usage is request based, noninteractive\n authentication for API implementations.
127
177
  Two strategies are supported that differ mainly in how the authentication information
@@ -147,7 +197,8 @@ files:
147
197
  - lib/hmac/strategies/header.rb
148
198
  - lib/hmac/strategies/query.rb
149
199
  - lib/hmac/string/jruby.rb
150
- - bin/warden-hmac-authentication
200
+ - !binary |-
201
+ YmluL3dhcmRlbi1obWFjLWF1dGhlbnRpY2F0aW9u
151
202
  homepage: https://github.com/Asquera/warden-hmac-authentication
152
203
  licenses: []
153
204
  post_install_message:
@@ -168,7 +219,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
168
219
  version: '0'
169
220
  requirements: []
170
221
  rubyforge_project:
171
- rubygems_version: 1.8.7
222
+ rubygems_version: 1.8.24
172
223
  signing_key:
173
224
  specification_version: 3
174
225
  summary: Provides request based, non-interactive authentication for APIs