api-auth 2.2.1 → 2.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +12 -2
  3. data/.rubocop_todo.yml +51 -9
  4. data/.travis.yml +9 -25
  5. data/CHANGELOG.md +36 -0
  6. data/Gemfile +1 -1
  7. data/README.md +91 -50
  8. data/VERSION +1 -1
  9. data/api_auth.gemspec +7 -5
  10. data/gemfiles/http4.gemfile +3 -3
  11. data/gemfiles/rails_52.gemfile +9 -0
  12. data/gemfiles/rails_60.gemfile +9 -0
  13. data/gemfiles/rails_61.gemfile +11 -0
  14. data/lib/api_auth.rb +1 -0
  15. data/lib/api_auth/base.rb +4 -4
  16. data/lib/api_auth/headers.rb +22 -11
  17. data/lib/api_auth/helpers.rb +2 -2
  18. data/lib/api_auth/railtie.rb +13 -5
  19. data/lib/api_auth/request_drivers/action_controller.rb +9 -8
  20. data/lib/api_auth/request_drivers/curb.rb +4 -4
  21. data/lib/api_auth/request_drivers/faraday.rb +13 -12
  22. data/lib/api_auth/request_drivers/grape_request.rb +87 -0
  23. data/lib/api_auth/request_drivers/http.rb +13 -8
  24. data/lib/api_auth/request_drivers/httpi.rb +9 -8
  25. data/lib/api_auth/request_drivers/net_http.rb +9 -8
  26. data/lib/api_auth/request_drivers/rack.rb +9 -8
  27. data/lib/api_auth/request_drivers/rest_client.rb +9 -8
  28. data/spec/api_auth_spec.rb +15 -8
  29. data/spec/headers_spec.rb +51 -25
  30. data/spec/helpers_spec.rb +1 -1
  31. data/spec/railtie_spec.rb +3 -3
  32. data/spec/request_drivers/action_controller_spec.rb +45 -39
  33. data/spec/request_drivers/action_dispatch_spec.rb +51 -45
  34. data/spec/request_drivers/curb_spec.rb +16 -10
  35. data/spec/request_drivers/faraday_spec.rb +49 -43
  36. data/spec/request_drivers/grape_request_spec.rb +280 -0
  37. data/spec/request_drivers/http_spec.rb +29 -23
  38. data/spec/request_drivers/httpi_spec.rb +28 -22
  39. data/spec/request_drivers/net_http_spec.rb +29 -23
  40. data/spec/request_drivers/rack_spec.rb +41 -35
  41. data/spec/request_drivers/rest_client_spec.rb +42 -36
  42. data/spec/spec_helper.rb +2 -1
  43. metadata +51 -26
  44. data/gemfiles/http2.gemfile +0 -7
  45. data/gemfiles/http3.gemfile +0 -7
  46. data/gemfiles/rails_4.gemfile +0 -11
  47. data/gemfiles/rails_41.gemfile +0 -11
  48. data/gemfiles/rails_42.gemfile +0 -11
  49. data/gemfiles/rails_5.gemfile +0 -11
  50. data/gemfiles/rails_51.gemfile +0 -9
  51. data/spec/.rubocop.yml +0 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 74847c2470f870ce0206badfda86189773a6bb96b109d0fca6ab276f5bb70523
4
- data.tar.gz: 5b24a84ec9a7617b3dfe33e9c97cccf5edc7caa627b51b76b3044f2952e32e80
3
+ metadata.gz: cdc2295825296be5b720b2df6ca984f247a71f549af9f4a8397a68e37e08707e
4
+ data.tar.gz: 9171431679afa0ab3bc8ab74a06a0bd14424034b0fb3af4202bfb45458f6b7a0
5
5
  SHA512:
6
- metadata.gz: 507f3c7f5e1570c9014e953179a42c13c5502ea50483172fd7650a6b9853297e9220cb096599c4498a95f1873bf06d37852355cb2bc566481c2b93c61a4a9cb6
7
- data.tar.gz: 05515f1bd95793f5c0497e2d3e0ea9cd65d9d14015f8f2abe151aa40ea0dfb849250505f0a132ba6b161d31d0839ebaec6adb7e8cef91dc286d123f7b04a1f37
6
+ metadata.gz: e07b3ad4db78a4f12339dc542827b0c43ee4aa3c7c1068f1ee639ca88c67ead6953e4158b6f9950127ab200fff06f7ee66312cc54dd6b3a59810ee1ceeb987b4
7
+ data.tar.gz: '051628373d800d5248fa1d9bdd6f3b57ba27ad898199dc84a241be2b551f22468e79facf208ba47141ef2d6591d462bf2f279233d7f8df4d7cef05b179e87da7'
data/.rubocop.yml CHANGED
@@ -1,16 +1,26 @@
1
1
  inherit_from: .rubocop_todo.yml
2
2
 
3
+ AllCops:
4
+ TargetRubyVersion: 2.5
5
+
3
6
  Metrics/AbcSize:
4
- Max: 25
7
+ Max: 28
5
8
 
6
9
  # Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
7
10
  # URISchemes: http, https
8
- Metrics/LineLength:
11
+ Layout/LineLength:
9
12
  Max: 140
10
13
 
11
14
  Metrics/MethodLength:
12
15
  Max: 40
13
16
 
17
+ Metrics/BlockLength:
18
+ Exclude:
19
+ - 'spec/**/*.rb'
20
+
14
21
  Naming/FileName:
15
22
  Exclude:
16
23
  - 'lib/api-auth.rb'
24
+
25
+ Style/FrozenStringLiteralComment:
26
+ Enabled: false
data/.rubocop_todo.yml CHANGED
@@ -1,60 +1,102 @@
1
1
  # This configuration was generated by
2
2
  # `rubocop --auto-gen-config`
3
- # on 2018-02-12 13:27:16 +0300 using RuboCop version 0.52.1.
3
+ # on 2021-03-26 22:04:17 UTC using RuboCop version 1.12.0.
4
4
  # The point is for the user to remove these configuration records
5
5
  # one by one as the offenses are removed from the code base.
6
6
  # Note that changes in the inspected code, or installation of new
7
7
  # versions of RuboCop, may require this file to be generated again.
8
8
 
9
+ # Offense count: 1
10
+ # Cop supports --auto-correct.
11
+ # Configuration parameters: TreatCommentsAsGroupSeparators, ConsiderPunctuation, Include.
12
+ # Include: **/*.gemspec
13
+ Gemspec/OrderedDependencies:
14
+ Exclude:
15
+ - 'api_auth.gemspec'
16
+
9
17
  # Offense count: 1
10
18
  # Configuration parameters: AllowSafeAssignment.
11
19
  Lint/AssignmentInCondition:
12
20
  Exclude:
13
21
  - 'lib/api_auth/base.rb'
14
22
 
15
- # Offense count: 8
23
+ # Offense count: 4
24
+ # Configuration parameters: AllowedMethods.
25
+ # AllowedMethods: enums
26
+ Lint/ConstantDefinitionInBlock:
27
+ Exclude:
28
+ - 'spec/railtie_spec.rb'
29
+
30
+ # Offense count: 9
31
+ # Configuration parameters: CheckForMethodsWithNoSideEffects.
16
32
  Lint/Void:
17
33
  Exclude:
18
34
  - 'lib/api_auth/headers.rb'
19
35
  - 'lib/api_auth/request_drivers/action_controller.rb'
20
36
  - 'lib/api_auth/request_drivers/curb.rb'
21
37
  - 'lib/api_auth/request_drivers/faraday.rb'
38
+ - 'lib/api_auth/request_drivers/grape_request.rb'
22
39
  - 'lib/api_auth/request_drivers/httpi.rb'
23
40
  - 'lib/api_auth/request_drivers/net_http.rb'
24
41
  - 'lib/api_auth/request_drivers/rack.rb'
25
42
  - 'lib/api_auth/request_drivers/rest_client.rb'
26
43
 
27
44
  # Offense count: 1
28
- Metrics/CyclomaticComplexity:
29
- Max: 14
45
+ # Configuration parameters: IgnoredMethods, CountRepeatedAttributes.
46
+ Metrics/AbcSize:
47
+ Max: 28
30
48
 
31
49
  # Offense count: 1
32
- Metrics/PerceivedComplexity:
33
- Max: 8
50
+ # Configuration parameters: CountComments, CountAsOne, ExcludedMethods, IgnoredMethods.
51
+ # IgnoredMethods: refine
52
+ Metrics/BlockLength:
53
+ Max: 27
34
54
 
35
- # Offense count: 9
55
+ # Offense count: 2
56
+ # Configuration parameters: IgnoredMethods.
57
+ Metrics/CyclomaticComplexity:
58
+ Max: 15
59
+
60
+ # Offense count: 10
36
61
  Naming/AccessorMethodName:
37
62
  Exclude:
38
63
  - 'lib/api_auth/railtie.rb'
39
64
  - 'lib/api_auth/request_drivers/action_controller.rb'
40
65
  - 'lib/api_auth/request_drivers/curb.rb'
41
66
  - 'lib/api_auth/request_drivers/faraday.rb'
67
+ - 'lib/api_auth/request_drivers/grape_request.rb'
42
68
  - 'lib/api_auth/request_drivers/http.rb'
43
69
  - 'lib/api_auth/request_drivers/httpi.rb'
44
70
  - 'lib/api_auth/request_drivers/net_http.rb'
45
71
  - 'lib/api_auth/request_drivers/rack.rb'
46
72
  - 'lib/api_auth/request_drivers/rest_client.rb'
47
73
 
74
+ # Offense count: 3
75
+ # Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames.
76
+ # AllowedNames: at, by, db, id, in, io, ip, of, on, os, pp, to
77
+ Naming/MethodParameterName:
78
+ Exclude:
79
+ - 'lib/api_auth/base.rb'
80
+ - 'spec/railtie_spec.rb'
81
+
48
82
  # Offense count: 9
83
+ # Cop supports --auto-correct.
49
84
  Style/CommentedKeyword:
50
85
  Exclude:
51
86
  - 'lib/api_auth/base.rb'
52
87
  - 'lib/api_auth/railtie.rb'
53
88
 
54
- # Offense count: 4
89
+ # Offense count: 3
90
+ # Configuration parameters: AllowedConstants.
55
91
  Style/Documentation:
56
92
  Exclude:
57
93
  - 'spec/**/*'
58
94
  - 'test/**/*'
59
95
  - 'lib/api_auth/railtie.rb'
60
- - 'lib/api_auth/request_drivers/rest_client.rb'
96
+
97
+ # Offense count: 1
98
+ # Configuration parameters: AllowedMethods.
99
+ # AllowedMethods: respond_to_missing?
100
+ Style/OptionalBooleanParameter:
101
+ Exclude:
102
+ - 'lib/api_auth/railtie.rb'
data/.travis.yml CHANGED
@@ -2,19 +2,14 @@ language: ruby
2
2
  sudo: false
3
3
  cache: bundler
4
4
  rvm:
5
- - 2.1.10
6
- - 2.2.9
7
- - 2.3.6
8
- - 2.4.3
9
- - 2.5.0
5
+ - 2.5.3
6
+ - 2.6.1
7
+ - 2.7.1
8
+ - 3.0.0
10
9
  gemfile:
11
- - gemfiles/rails_4.gemfile
12
- - gemfiles/rails_41.gemfile
13
- - gemfiles/rails_42.gemfile
14
- - gemfiles/rails_5.gemfile
15
- - gemfiles/rails_51.gemfile
16
- - gemfiles/http2.gemfile
17
- - gemfiles/http3.gemfile
10
+ - gemfiles/rails_52.gemfile
11
+ - gemfiles/rails_60.gemfile
12
+ - gemfiles/rails_61.gemfile
18
13
  - gemfiles/http4.gemfile
19
14
  env:
20
15
  - TEST_SUITE=rake
@@ -26,20 +21,9 @@ script:
26
21
  - bundle exec $TEST_SUITE
27
22
 
28
23
  matrix:
29
- exclude:
30
- - rvm: 2.1.10
31
- gemfile: gemfiles/rails_5.gemfile
32
- - rvm: 2.1.10
33
- gemfile: gemfiles/rails_51.gemfile
34
- - rvm: 2.1.9
35
- gemfile: gemfiles/http2.gemfile
36
- - rvm: 2.1.9
37
- gemfile: gemfiles/http3.gemfile
38
- - rvm: 2.1.9
39
- gemfile: gemfiles/http4.gemfile
40
24
  include:
41
- - rvm: 2.5.0
42
- gemfile: gemfiles/rails_5.gemfile
25
+ - rvm: 3.0.0
26
+ gemfile: gemfiles/rails_61.gemfile
43
27
  env: TEST_SUITE="rubocop lib/ spec/"
44
28
 
45
29
  notifications:
data/CHANGELOG.md CHANGED
@@ -1,3 +1,39 @@
1
+ # 2.5.0 (2021-05-11)
2
+ - Add support for Ruby 3.0 (#194 fwininger)
3
+ - Add support for Rails 6.1 (#194 fwininger)
4
+ - Drop support for Ruby 2.4 (#193 fwininger)
5
+ - Drop support for Rails 5.0 (#194 fwininger)
6
+ - Drop support for Rails 5.1 (#194 fwininger)
7
+ - Fix Faraday warning: `WARNING: Faraday::Request#method is deprecated` (#191 fwininger)
8
+
9
+ # 2.4.1 (2020-06-23)
10
+ - Fix inadvertant ActiveSupport dependecy (#189 taylorthurlow)
11
+
12
+ # 2.4.0 (2020-05-05)
13
+ - Improved support for Rails 6.0 (#179 taylorthurlow, #177 fwininger)
14
+ - Added Ruby 2.6.0 support (#174 fwininger)
15
+ - README updates (#186 iranthau)
16
+
17
+ # 2.3.1 (2018-11-06)
18
+ - Fixed a regression in the http.rb driver (#173 tycooon)
19
+
20
+ # 2.3.0 (2018-10-23)
21
+ - Added support for Grape API (#169 phuongnd08 & dunghuynh)
22
+ - Added option for specifying customer headers to sign via new `headers_to_sign`
23
+ argument (#170 fakenine)
24
+ - Fix tests and drop support for Ruby < 2.3 (#171 fwininger)
25
+
26
+ # 2.2.0 (2018-03-12)
27
+ - Drop support ruby 1.x, rails 2.x, rails 3.x (#141 fwininger)
28
+ - Add http.rb request driver (#164 tycooon)
29
+ - Fix POST and PUT requests in RestClient (#151 fwininger)
30
+ - Allow clock skew to be user-defined (#136 mlarraz)
31
+ - Adds #original_uri method to all request drivers (#137 iMacTia)
32
+ - Rubocop and test fixes (fwininger & nicolasleger)
33
+ - Changed return type for request #content_md5 #timestamp #content_type (fwininger)
34
+ - Fix URI edge case where a URI contains another URI (zfletch)
35
+ - Updates to the README (zfletch)
36
+
1
37
  # 2.1.0 (2016-12-22)
2
38
  - Fixed a NoMethodError that might occur when using the NetHttp Driver (#130 grahamkenville)
3
39
  - More securely compare signatures in a way that prevents timing attacks (#56 leishman, #133 will0)
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
1
  source 'https://rubygems.org'
2
2
  gemspec
3
3
 
4
- gem 'rubocop', platforms: %i[ruby_20 ruby_21 ruby_22 ruby_23 ruby_24]
4
+ gem 'rubocop'
data/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # ApiAuth
2
2
 
3
- [![Build Status](https://travis-ci.org/mgomes/api_auth.png?branch=master)](https://travis-ci.org/mgomes/api_auth)
3
+ [![Build Status](https://travis-ci.org/mgomes/api_auth.svg?branch=master)](https://travis-ci.org/mgomes/api_auth)
4
+ [![Gem Version](https://badge.fury.io/rb/api-auth.svg)](https://badge.fury.io/rb/api-auth)
4
5
 
5
6
  Logins and passwords are for humans. Communication between applications need to
6
7
  be protected through different means.
@@ -20,19 +21,35 @@ have to be written in the same language as the clients.
20
21
  ## How it works
21
22
 
22
23
  1. A canonical string is first created using your HTTP headers containing the
23
- content-type, content-MD5, request URI and the timestamp. If content-type or
24
- content-MD5 are not present, then a blank string is used in their place. If the
25
- timestamp isn't present, a valid HTTP date is automatically added to the
26
- request. The canonical string is computed as follows:
24
+ `content-type`, `X-Authorization-Content-SHA256`, request path and the date/time stamp.
25
+ If `content-type` or `X-Authorization-Content-SHA256` are not present, then a blank
26
+ string is used in their place. If the timestamp isn't present, a valid HTTP date is
27
+ automatically added to the request. The canonical string is computed as follows:
27
28
 
28
- canonical_string = 'http method,content-type,content-MD5,request URI,timestamp'
29
+ ```ruby
30
+ canonical_string = "#{http method},#{content-type},#{X-Authorization-Content-SHA256},#{request URI},#{timestamp}"
31
+ ```
32
+
33
+ e.g.,
34
+
35
+ ```ruby
36
+ canonical_string = 'POST,application/json,,request_path,Tue, 30 May 2017 03:51:43 GMT'
37
+ ```
29
38
 
30
39
  2. This string is then used to create the signature which is a Base64 encoded
31
40
  SHA1 HMAC, using the client's private secret key.
32
41
 
33
42
  3. This signature is then added as the `Authorization` HTTP header in the form:
34
43
 
35
- Authorization = APIAuth 'client access id':'signature from step 2'
44
+ ```ruby
45
+ Authorization = APIAuth "#{client access id}:#{signature from step 2}"
46
+ ```
47
+
48
+ A cURL request would look like:
49
+
50
+ ```sh
51
+ curl -X POST --header 'Content-Type: application/json' --header "Date: Tue, 30 May 2017 03:51:43 GMT" --header "Authorization: ${AUTHORIZATION}" http://my-app.com/request_path`
52
+ ```
36
53
 
37
54
  5. On the server side, the SHA1 HMAC is computed in the same way using the
38
55
  request headers and the client's secret key, which is known to only
@@ -41,7 +58,6 @@ access id that was attached in the header. The access id can be any integer or
41
58
  string that uniquely identifies the client. The signed request expires after 15
42
59
  minutes in order to avoid replay attacks.
43
60
 
44
-
45
61
  ## References
46
62
 
47
63
  * [Hash functions](http://en.wikipedia.org/wiki/Cryptographic_hash_function)
@@ -51,9 +67,9 @@ minutes in order to avoid replay attacks.
51
67
 
52
68
  ## Requirement
53
69
 
54
- v3.X require Ruby >= 2.1 and Rails >= 4.0 if you use rails.
70
+ This gem require Ruby >= 2.5 and Rails >= 5.1 if you use rails.
55
71
 
56
- For older version of Ruby or Rails, please use ApiAuth v2.X.
72
+ For older version of Ruby or Rails, please use ApiAuth v2.1 and older.
57
73
 
58
74
  **IMPORTANT: v2.0.0 is backwards incompatible with the default settings of v1.x to address a security vulnerability. See [CHANGELOG.md](/CHANGELOG.md) for security update information.**
59
75
 
@@ -62,7 +78,9 @@ For older version of Ruby or Rails, please use ApiAuth v2.X.
62
78
  The gem doesn't have any dependencies outside of having a working OpenSSL
63
79
  configuration for your Ruby VM. To install:
64
80
 
65
- [sudo] gem install api-auth
81
+ ```sh
82
+ [sudo] gem install api-auth
83
+ ```
66
84
 
67
85
  Please note the dash in the name versus the underscore.
68
86
 
@@ -87,26 +105,30 @@ Here's a sample implementation of signing a request created with RestClient.
87
105
 
88
106
  Assuming you have a client access id and secret as follows:
89
107
 
90
- ``` ruby
91
- @access_id = "1044"
92
- @secret_key = ApiAuth.generate_secret_key
108
+ ```ruby
109
+ @access_id = "1044"
110
+ @secret_key = ApiAuth.generate_secret_key
93
111
  ```
94
112
 
95
113
  A typical RestClient PUT request may look like:
96
114
 
97
- ``` ruby
98
- headers = { 'Content-MD5' => "e59ff97941044f85df5297e1c302d260",
99
- 'Content-Type' => "text/plain",
100
- 'Date' => "Mon, 23 Jan 1984 03:29:56 GMT" }
101
- @request = RestClient::Request.new(:url => "/resource.xml?foo=bar&bar=foo",
102
- :headers => headers,
103
- :method => :put)
115
+ ```ruby
116
+ headers = { 'X-Authorization-Content-SHA256' => "dWiCWEMZWMxeKM8W8Yuh/TbI29Hw5xUSXZWXEJv63+Y=",
117
+ 'Content-Type' => "text/plain",
118
+ 'Date' => "Mon, 23 Jan 1984 03:29:56 GMT"
119
+ }
120
+
121
+ @request = RestClient::Request.new(
122
+ url: "/resource.xml?foo=bar&bar=foo",
123
+ headers: headers,
124
+ method: :put
125
+ )
104
126
  ```
105
127
 
106
128
  To sign that request, simply call the `sign!` method as follows:
107
129
 
108
- ``` ruby
109
- @signed_request = ApiAuth.sign!(@request, @access_id, @secret_key)
130
+ ```ruby
131
+ @signed_request = ApiAuth.sign!(@request, @access_id, @secret_key)
110
132
  ```
111
133
 
112
134
  The proper `Authorization` request header has now been added to that request
@@ -119,34 +141,38 @@ If you are signing a request for a driver that doesn't support automatic http
119
141
  method detection (like Curb or httpi), you can pass the http method as an option
120
142
  into the sign! method like so:
121
143
 
122
- ``` ruby
123
- @signed_request = ApiAuth.sign!(@request, @access_id, @secret_key, :override_http_method => "PUT")
144
+ ```ruby
145
+ @signed_request = ApiAuth.sign!(@request, @access_id, @secret_key, :override_http_method => "PUT")
124
146
  ```
125
147
 
126
148
  If you want to use another digest existing in `OpenSSL::Digest`,
127
149
  you can pass the http method as an option into the sign! method like so:
128
150
 
129
- ``` ruby
130
- @signed_request = ApiAuth.sign!(@request, @access_id, @secret_key, :digest => 'sha256')
151
+ ```ruby
152
+ @signed_request = ApiAuth.sign!(@request, @access_id, @secret_key, :digest => 'sha256')
131
153
  ```
132
154
 
133
155
  With the `digest` option, the `Authorization` header will be change from:
134
156
 
135
- Authorization = APIAuth 'client access id':'signature'
157
+ ```sh
158
+ Authorization = APIAuth 'client access id':'signature'
159
+ ```
136
160
 
137
161
  to:
138
162
 
139
- Authorization = APIAuth-HMAC-DIGEST_NAME 'client access id':'signature'
163
+ ```sh
164
+ Authorization = APIAuth-HMAC-DIGEST_NAME 'client access id':'signature'
165
+ ```
140
166
 
141
167
  ### ActiveResource Clients
142
168
 
143
169
  ApiAuth can transparently protect your ActiveResource communications with a
144
170
  single configuration line:
145
171
 
146
- ``` ruby
147
- class MyResource < ActiveResource::Base
148
- with_api_auth(access_id, secret_key)
149
- end
172
+ ```ruby
173
+ class MyResource < ActiveResource::Base
174
+ with_api_auth(access_id, secret_key)
175
+ end
150
176
  ```
151
177
 
152
178
  This will automatically sign all outgoing ActiveResource requests from your app.
@@ -156,7 +182,7 @@ This will automatically sign all outgoing ActiveResource requests from your app.
156
182
  ApiAuth also works with [Flexirest](https://github.com/andyjeffries/flexirest) (used to be ActiveRestClient, but that is now unsupported) in a very similar way.
157
183
  Simply add this configuration to your Flexirest initializer in your app and it will automatically sign all outgoing requests.
158
184
 
159
- ``` ruby
185
+ ```ruby
160
186
  Flexirest::Base.api_auth_credentials(@access_id, @secret_key)
161
187
  ```
162
188
 
@@ -167,27 +193,29 @@ clients as well as verifying incoming API requests.
167
193
 
168
194
  To generate a Base64 encoded API key for a client:
169
195
 
170
- ``` ruby
171
- ApiAuth.generate_secret_key
196
+ ```ruby
197
+ ApiAuth.generate_secret_key
172
198
  ```
173
199
 
174
200
  To validate whether or not a request is authentic:
175
201
 
176
- ``` ruby
177
- ApiAuth.authentic?(signed_request, secret_key)
202
+ ```ruby
203
+ ApiAuth.authentic?(signed_request, secret_key)
178
204
  ```
179
205
 
180
206
  The `authentic?` method uses the digest specified in the `Authorization` header.
181
207
  For example SHA256 for:
182
208
 
183
- Authorization = APIAuth-HMAC-SHA256 'client access id':'signature'
209
+ ```sh
210
+ Authorization = APIAuth-HMAC-SHA256 'client access id':'signature'
211
+ ```
184
212
 
185
213
  And by default SHA1 if the HMAC-DIGEST is not specified.
186
214
 
187
215
  If you want to force the usage of another digest method, you should pass it as an option parameter:
188
216
 
189
- ``` ruby
190
- ApiAuth.authentic?(signed_request, secret_key, :digest => 'sha256')
217
+ ```ruby
218
+ ApiAuth.authentic?(signed_request, secret_key, :digest => 'sha256')
191
219
  ```
192
220
 
193
221
  For security, requests dated older or newer than a certain timespan are considered inauthentic.
@@ -198,16 +226,24 @@ can't be dated into the far future.
198
226
  The default span is 15 minutes, but you can override this:
199
227
 
200
228
  ```ruby
201
- ApiAuth.authentic?(signed_request, secret_key, :clock_skew => 60) # or 1.minute in ActiveSupport
229
+ ApiAuth.authentic?(signed_request, secret_key, :clock_skew => 60) # or 1.minute in ActiveSupport
230
+ ```
231
+
232
+ If you want to sign custom headers, you can pass them as an array of strings in the options like so:
233
+
234
+ ``` ruby
235
+ ApiAuth.authentic?(signed_request, secret_key, headers_to_sign: %w[HTTP_HEADER_NAME])
202
236
  ```
203
237
 
238
+ With the specified headers values being at the end of the canonical string in the same order.
239
+
204
240
  If your server is a Rails app, the signed request will be the `request` object.
205
241
 
206
242
  In order to obtain the secret key for the client, you first need to look up the
207
243
  client's access_id. ApiAuth can pull that from the request headers for you:
208
244
 
209
245
  ``` ruby
210
- ApiAuth.access_id(signed_request)
246
+ ApiAuth.access_id(signed_request)
211
247
  ```
212
248
 
213
249
  Once you've looked up the client's record via the access id, you can then verify
@@ -219,12 +255,12 @@ Here's a sample method that can be used in a `before_action` if your server is a
219
255
  Rails app:
220
256
 
221
257
  ``` ruby
222
- before_action :api_authenticate
258
+ before_action :api_authenticate
223
259
 
224
- def api_authenticate
225
- @current_account = Account.find_by_access_id(ApiAuth.access_id(request))
226
- head(:unauthorized) unless @current_account && ApiAuth.authentic?(request, @current_account.secret_key)
227
- end
260
+ def api_authenticate
261
+ @current_account = Account.find_by_access_id(ApiAuth.access_id(request))
262
+ head(:unauthorized) unless @current_account && ApiAuth.authentic?(request, @current_account.secret_key)
263
+ end
228
264
  ```
229
265
 
230
266
  ## Development
@@ -237,11 +273,15 @@ To run the tests:
237
273
 
238
274
  Install the dependencies for a particular Rails version by specifying a gemfile in `gemfiles` directory:
239
275
 
240
- BUNDLE_GEMFILE=gemfiles/rails_5.gemfile bundle install
276
+ ```sh
277
+ BUNDLE_GEMFILE=gemfiles/rails_5.gemfile bundle install
278
+ ```
241
279
 
242
280
  Run the tests with those dependencies:
243
281
 
244
- BUNDLE_GEMFILE=gemfiles/rails_5.gemfile bundle exec rake
282
+ ```sh
283
+ BUNDLE_GEMFILE=gemfiles/rails_5.gemfile bundle exec rake
284
+ ```
245
285
 
246
286
  If you'd like to add support for additional HTTP clients, check out the already
247
287
  implemented drivers in `lib/api_auth/request_drivers` for reference. All of
@@ -251,6 +291,7 @@ the public methods for each driver are required to be implemented by your driver
251
291
 
252
292
  * [Mauricio Gomes](http://github.com/mgomes)
253
293
  * [Kevin Glowacz](http://github.com/kjg)
294
+ * [Florian Wininger](http://github.com/fwininger)
254
295
 
255
296
  ## Copyright
256
297