http_signature 0.0.7 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 33793ff4276cb6c366f88d15abb0e38b69cdb468
4
- data.tar.gz: cde3efe53a20f5ef8a94c2ed21b9341300f4ed76
3
+ metadata.gz: 821df2c08e3f1d58e737250711d5d45d6baf561d
4
+ data.tar.gz: 3ee3456c48c461e7ae328b42f5c4808a7fe9cb9d
5
5
  SHA512:
6
- metadata.gz: 88cf8f428a7bafd0971b4e8d0650c8b9ee15c8f74794347afa7cdaed32da0462468f4a7f1471f1f4578886009801a822dcf990481d859dac5fa3e9b65e2e8630
7
- data.tar.gz: 516d8a279e8a340df3e2aae7e8b1bd313229dd8e8643c81bda7caea37e321d1e812e692afabe2b4535281c6c35970b2b62286ffdd07178fa5a57ca2c63d0c72f
6
+ metadata.gz: 75c29e3608b55604dcc9bbbcae30d8907e3b830b8001fc563f2c606a88f7f071e54470d56c28ee3d2d9406aa173445b176e1c1bfe9c02ca2c3994b1559b0fe9c
7
+ data.tar.gz: 73ec032a5fdf6813d1ac273aadf4b90d9f583c72e023299f62383c82f8ad92d17c72010b8571a9bb7d211c2781d9f477a901f89b6da3992bc5291159d298fed2
@@ -0,0 +1,5 @@
1
+ Metrics/LineLength:
2
+ Max: 100
3
+
4
+ Metrics/MethodLength:
5
+ Max: 15
data/README.md CHANGED
@@ -105,16 +105,46 @@ HTTPSignature.valid?(
105
105
  )
106
106
  ```
107
107
 
108
- ## Example usage with middleware
109
- ### Faraday middleware on outgoing requests
110
- Example of using it on an outgoing request.
108
+ ## Example usage
109
+ ### NET::HTTP
110
+ Example of using it with `NET::HTTP`. There's no real integration written so it's basically just
111
+ getting the request object's data and create the signature and adding it to the headers.
112
+
113
+ ```ruby
114
+ require 'net/http'
115
+ require 'http_signature'
116
+
117
+ uri = URI('http://example.com/hello')
118
+
119
+ Net::HTTP.start(uri.host, uri.port) do |http|
120
+ request = Net::HTTP::Get.new(uri)
121
+
122
+ signature = HTTPSignature.create(
123
+ url: request.uri,
124
+ method: request.method,
125
+ headers: request.each_header.map { |k, v| [k, v] }.to_h,
126
+ key: 'MYSECRETKEY',
127
+ key_id: 'KEY_1',
128
+ algorithm: 'hmac-sha256',
129
+ body: request.body ? request.body : ''
130
+ )
131
+
132
+ request['Signature'] = signature
133
+
134
+ response = http.request(request) # Net::HTTPResponse
135
+ end
136
+ ```
137
+
138
+ ### Faraday middleware
139
+ Example of using it with an outgoing faraday request. IMO, this is the smoothest usage.
140
+ Basically you set the keys and tell faraday to use the middleware.
141
+
111
142
  ```ruby
112
143
  require 'http_signature/faraday'
113
144
 
114
145
  HTTPSignature::Faraday.key = 'MySecureKey' # This should be long and random
115
146
  HTTPSignature::Faraday.key_id = 'key-1' # For the recipient to know which key to decrypt with
116
147
 
117
-
118
148
  # Tell faraday to use the middleware. Read more about it here: https://github.com/lostisland/faraday#advanced-middleware-usage
119
149
  Faraday.new('http://example.com') do |faraday|
120
150
  faraday.use(HTTPSignature::Faraday)
@@ -131,16 +161,18 @@ response = conn.get('/')
131
161
  ```
132
162
 
133
163
  ### Rack middleware for incoming requests
134
- I've written a quite sloppy but totally usable rack middleware that validates every incoming request.
164
+ I've written a quite sloppy but totally usable rack middleware that validates incoming requests.
135
165
 
136
- #### General rack application
166
+ #### General Rack application
137
167
  Sinatra for example
138
168
  ```ruby
139
169
  require 'http_signature/rack'
140
170
 
141
171
  HTTPSignature.config(keys: [{ id: 'key-1', value: 'MySecureKey' }])
142
- # You can exclude paths where you don't want to validate the signature:
143
- HTTPSignature::Rack.exclude_paths = ['/']
172
+ # You can exclude paths where you don't want to validate the signature, it's using
173
+ # regexp so you can use `*` and stuff like that. Just watch out so you don't exclude
174
+ # more paths than intended. Regexp can trick you when you least expect it 👻.
175
+ HTTPSignature::Rack.exclude_paths = ['/', '/hello/*']
144
176
 
145
177
  use HTTPSignature::Rack
146
178
  run MyApp
@@ -1,9 +1,10 @@
1
1
  lib = File.expand_path('../lib', __FILE__)
2
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'http_signature/version'
3
4
 
4
5
  Gem::Specification.new do |spec|
5
6
  spec.name = 'http_signature'
6
- spec.version = '0.0.7'
7
+ spec.version = HTTPSignature::VERSION
7
8
  spec.authors = ['Joel Larsson']
8
9
  spec.email = ['bolmaster2@gmail.com']
9
10
 
@@ -5,6 +5,8 @@ require 'securerandom'
5
5
  require 'base64'
6
6
  require 'uri'
7
7
 
8
+ # Implements signing of a request according to https://tools.ietf.org/html/draft-cavage-http-signatures
9
+ # specification.
8
10
  module HTTPSignature
9
11
  # Create signature based on the data sent in
10
12
  #
@@ -18,12 +20,10 @@ module HTTPSignature
18
20
  # @param method [Symbol] Request method, default is `:get`
19
21
  # @param algorithm [String] Algorithm to use when signing, check `supported_algorithms` for
20
22
  # @return [String] The signature header value to use in "Signature" header
21
- def self.create(url:, query_string_params: {}, body: '', headers: {}, key:,
22
- key_id: SecureRandom.hex(8),
23
- method: :get,
24
- algorithm: 'hmac-sha256'
23
+ def self.create(
24
+ url:, query_string_params: {}, body: '', headers: {}, key:, key_id: SecureRandom.hex(8),
25
+ method: :get, algorithm: 'hmac-sha256'
25
26
  )
26
-
27
27
  raise 'Unsupported algorithm :(' unless supported_algorithms.include?(algorithm)
28
28
 
29
29
  uri = URI(url)
@@ -32,12 +32,11 @@ module HTTPSignature
32
32
  headers = convert_headers(headers)
33
33
  query = create_query_string(uri, query_string_params)
34
34
 
35
- string_to_sign = create_signing_string(method: method, path: path,
36
- query: query, headers: headers)
37
-
38
- signature = sign(string_to_sign, key: key, algorithm: algorithm)
39
- create_signature_header(key_id: key_id, headers: headers, signature: signature,
40
- algorithm: algorithm)
35
+ sign_string = create_signing_string(method: method, path: path, query: query, headers: headers)
36
+ signature = sign(sign_string, key: key, algorithm: algorithm)
37
+ create_signature_header(
38
+ key_id: key_id, headers: headers, signature: signature, algorithm: algorithm
39
+ )
41
40
  end
42
41
 
43
42
  def self.sign(string, key:, algorithm:)
@@ -86,7 +85,7 @@ module HTTPSignature
86
85
  # @return [String]
87
86
  def self.create_signing_string(method:, path:, query:, headers:)
88
87
  [
89
- "(request-target): #{method.upcase} #{path}#{query}",
88
+ "(request-target): #{method.downcase} #{path}#{query}"
90
89
  ].concat(headers).join("\n")
91
90
  end
92
91
 
@@ -109,6 +108,7 @@ module HTTPSignature
109
108
  uri = URI(url)
110
109
  path = uri.path
111
110
  signature = headers.delete(:signature)
111
+ headers = add_digest(headers, body)
112
112
  headers = convert_headers(headers)
113
113
  query = create_query_string(uri, query_string_params)
114
114
 
@@ -141,11 +141,13 @@ module HTTPSignature
141
141
  # When query string params is also set on the url, append the params defined
142
142
  # in `query_string_params` and make a joint query string
143
143
  def self.create_query_string(uri, query_string_params)
144
- if uri.query || !query_string_params.empty?
145
- delimiter = uri.query.nil? ? '' : '&'
146
- '?' + (query_string_params.empty? ? '' : [uri.query.to_s, delimiter, URI.encode_www_form(query_string_params)].join)
147
- end
144
+ return if !uri.query && query_string_params.empty?
145
+
146
+ delimiter = uri.query.nil? || query_string_params.empty? ? '' : '&'
147
+
148
+ ['?', uri.query.to_s, delimiter, URI.encode_www_form(query_string_params)].join
148
149
  end
150
+
149
151
  # Convert a header hash into an array with header strings
150
152
  # { header: 'value'} -> ['header: value']
151
153
  def self.convert_headers(headers)
@@ -156,7 +158,6 @@ module HTTPSignature
156
158
 
157
159
  def self.add_digest(headers, body)
158
160
  headers[:digest] = create_digest(body) unless body.empty?
159
-
160
161
  headers
161
162
  end
162
163
 
@@ -165,9 +166,7 @@ module HTTPSignature
165
166
  end
166
167
 
167
168
  def self.key(id)
168
- key = @keys.select do |o|
169
- o[:id] == id
170
- end.first
169
+ key = @keys.select { |o| o[:id] == id }.first
171
170
 
172
171
  key&.dig(:value) || (raise "Key with id #{id} could not be found")
173
172
  end
@@ -21,8 +21,8 @@ class HTTPSignature::Faraday < Faraday::Middleware
21
21
  end
22
22
 
23
23
  # Choose which headers to sign
24
- filtered_headers = %w{ Host Date Digest }
25
- headers_to_sign = env[:request_headers].select { |k, v| filtered_headers.include?(k.to_s) }
24
+ filtered_headers = %w[Host Date Digest]
25
+ headers_to_sign = env[:request_headers].select { |k, _v| filtered_headers.include?(k.to_s) }
26
26
 
27
27
  signature = HTTPSignature.create(
28
28
  url: env[:url],
@@ -34,7 +34,7 @@ class HTTPSignature::Faraday < Faraday::Middleware
34
34
  body: body
35
35
  )
36
36
 
37
- env[:request_headers].merge!('Signature' => signature)
37
+ env[:request_headers]['Signature'] = signature
38
38
 
39
39
  @app.call(env)
40
40
  end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HTTPSignature
4
+ VERSION = '0.1.0'
5
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: http_signature
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joel Larsson
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-05-02 00:00:00.000000000 Z
11
+ date: 2018-05-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -75,6 +75,7 @@ extra_rdoc_files: []
75
75
  files:
76
76
  - ".circleci/config.yml"
77
77
  - ".gitignore"
78
+ - ".rubocop.yml"
78
79
  - ".ruby-version"
79
80
  - Gemfile
80
81
  - Gemfile.lock
@@ -84,6 +85,7 @@ files:
84
85
  - lib/http_signature.rb
85
86
  - lib/http_signature/faraday.rb
86
87
  - lib/http_signature/rack.rb
88
+ - lib/http_signature/version.rb
87
89
  homepage: https://github.com/bolmaster2/http-signature
88
90
  licenses:
89
91
  - MIT