warden-hmac-authentication 0.6.1 → 0.6.2

Sign up to get free protection for your applications and to get access to all the features.
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