rack-simple_auth 0.1.4 → 1.0.0rc

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 CHANGED
@@ -1,7 +1,7 @@
1
- ---
2
- SHA1:
3
- metadata.gz: a9eb2327a5e9743a78d600c3a79f6c10628d4d4e
4
- data.tar.gz: 648aba592008e3d5da11eda588352f3940b67d86
5
- SHA512:
6
- metadata.gz: c485c387b2bfd02372758c937aae019acd9160acbd1ad0436027bdf8365197444d32a360c59a421e23cf427b86212e0f02f8cf84d3981f0e9ffc3d17189fc6d8
7
- data.tar.gz: fc568199976dd711a630a5e584be13a82a741ff68f9873e67cd84e84c7c79f5d977b4ecccd7af4ae3f6cc3d768b9dfa5fd9e25d163f1da87f6eeb21dd0fb0cbd
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ebfdad444b3dd93872a40ed95da0113777be8be7
4
+ data.tar.gz: 6dd2b76e1ef8e8916dc4870a4567f71e624ff8f1
5
+ SHA512:
6
+ metadata.gz: 847a3ef324399d4bc6a9a1edc40046d200c0112997f55163cd71d6e1edb798faa163479ed046e5f49b7f57559f988549ad90ad3bc043357996ed1ecb38eacc85
7
+ data.tar.gz: 092eb1391821c56ae96a20cfb66053ccb5b4d83992c964e9d2369f72ecd7949064e0eb05b21b3de0e2454d21f532b9e8cadea92907d40d32e9ca0802e1f43613
data/MANIFEST CHANGED
@@ -10,21 +10,28 @@ Rakefile
10
10
  checksum/rack-simple_auth-0.0.9.gem.sha512
11
11
  checksum/rack-simple_auth-0.1.0.gem.sha512
12
12
  checksum/rack-simple_auth-0.1.1.gem.sha512
13
+ checksum/rack-simple_auth-0.1.2.gem.sha512
13
14
  lib/rack/simple_auth.rb
14
- lib/rack/simple_auth/hmac.rb
15
+ lib/rack/simple_auth/hmac/config.rb
16
+ lib/rack/simple_auth/hmac/middleware.rb
17
+ lib/rack/simple_auth/logger.rb
15
18
  lib/rack/simple_auth/version.rb
16
19
  rack-simple_auth.gemspec
17
20
  rubocop-todo.yml
18
21
  task/build.rake
19
22
  task/checksum.rake
23
+ task/console.rake
20
24
  task/default.rake
21
25
  task/floodtest.rake
22
26
  task/manifest.rake
23
27
  task/test.rake
24
- test/config.ru
25
- test/config_fail.ru
26
- test/config_fail_step.ru
27
- test/config_fail_tolerance.ru
28
- test/rack/simple_auth/hmac_fail_test.rb
29
- test/rack/simple_auth/hmac_test.rb
28
+ test/rack/simple_auth/hmac/config.ru
29
+ test/rack/simple_auth/hmac/config_fail.ru
30
+ test/rack/simple_auth/hmac/config_fail_option.ru
31
+ test/rack/simple_auth/hmac/config_fail_run.ru
32
+ test/rack/simple_auth/hmac/config_fail_step.ru
33
+ test/rack/simple_auth/hmac/config_fail_tolerance.ru
34
+ test/rack/simple_auth/hmac/hmac_fail_run_test.rb
35
+ test/rack/simple_auth/hmac/hmac_fail_test.rb
36
+ test/rack/simple_auth/hmac/hmac_test.rb
30
37
  test/test_helper.rb
data/README.md CHANGED
@@ -28,115 +28,37 @@ Or install it yourself as:
28
28
 
29
29
  ## Usage
30
30
 
31
- ### HMAC Authorization
31
+ ### HMAC
32
32
 
33
- HMAC should be used for communication between website backend and api server/controller/whatever..
34
-
35
- In version 0.0.5 the timestamp has been added to the msg which will be encrypted, also the possibility to configure the allowed delay a request can have has been added.
36
-
37
- Uses Authorization HTTP Header, example:
38
- ```Authorization: MessageHash:Signature```
39
-
40
- - Signature is the "Public Key"
41
- - MessageHash is the HMAC encrypted Message
42
-
43
- #### Basic Usage:
33
+ To use HMAC Authorization you have to use the ```Rack::SimpleAuth::HMAC::Middleware``` for your Rack App
44
34
 
35
+ Basic Usage:
45
36
  ```ruby
46
- config = {
47
- 'GET' => 'path',
48
- 'POST' => 'params',
49
- 'DELETE' => 'path',
50
- 'PUT' => 'path',
51
- 'PATCH' => 'path'
52
- 'tolerance' => 1,
53
- 'steps' => 0.1,
54
- 'signature' => 'signature',
55
- 'secret' => 'secret',
56
- 'logpath' => '/path/to/log/file'
57
- }
58
-
59
- map '/' do
60
- use Rack::SimpleAuth::HMAC, config
61
- run MyApplication
62
- end
63
- ```
64
-
65
- Note: Private Key and Signature should be served by a file which is not checked into git version control.
66
-
37
+ require 'rack/lobster'
38
+ require 'rack/simple_auth'
67
39
 
40
+ request_config = {
41
+ 'GET' => 'path',
42
+ 'POST' => 'params',
43
+ 'DELETE' => 'path',
44
+ 'PUT' => 'path',
45
+ 'PATCH' => 'path'
46
+ }
68
47
 
48
+ use Rack::SimpleAuth::HMAC::Middleware do |options|
49
+ options.tolerance = 0.5
50
+ options.stepsize = 0.01
69
51
 
52
+ options.secret = 'test_secret'
53
+ options.signature = 'test_signature'
70
54
 
71
- #### Config Hash
55
+ options.logpath = "#{File.expand_path('..', __FILE__)}/logs"
56
+ options.request_config = request_config
57
+ end
72
58
 
73
-
74
- Via the config hash you are able to define the 'data' for each request method.<br />
75
- This data + HTTP Methodname is your Message what will be encrypted.<br />
76
-
77
- For example ```GET '/get/user?name=rack'```:
78
-
79
- ```ruby
80
- config = {
81
- .
82
- .
83
- 'GET' => 'path'
84
- .
85
- .
86
- }
59
+ run Rack::Lobster.new
87
60
  ```
88
61
 
89
- The Message what will be HMAC encrypted is:
90
-
91
- ```ruby
92
- message = { 'method' => 'GET', 'data' => '/get/user?name=rack' }.to_json
93
- ```
94
-
95
- In Version 0.0.5 the timestamp has been added to the Message.
96
-
97
- The new Message which will be encrypted looks like this:
98
-
99
- ```ruby
100
- message = { 'method' => 'GET', 'date' => Time.now.to_i +- delay range, 'data' => '/get/user?name=rack }.to_json
101
- ```
102
-
103
- The tolerance which is configureable in the config hash sets the possible delay a request could have and still will be authorized.
104
-
105
- Notice: For a set tolerance a Encrypted Message array will be generated and compared with the MessageHash from the AUTH Header
106
-
107
- In Version 0.1.0 the stepsize option has been added
108
-
109
- You can now specify how many valid hashes are created in a range between eg.: (-1..1) (= tolerance)
110
-
111
- A minimum stepsize of 0.01 is required (0.01 are 10 milliseconds, this is the minimum because of ruby's float disaster and therefore the gem has to use Float#round(2))
112
-
113
- Let me know if you need a smaller stepsize...
114
-
115
-
116
- #### Logging
117
-
118
- With config['logpath'] you can define a destination where the internal #log method should write to.
119
-
120
- The Logging will only be triggered when a path is defined (leave config['logpath'] for disable logging) and a request is not authorized!
121
-
122
- It contains following information:
123
-
124
- - HTTP_AUTHORIZATION Header
125
- - Config for the specific Request Method (GET => path etc ...)
126
- - The Encrypted Message Array which was expected
127
- - The Signature which was expected
128
-
129
- ## TODO
130
-
131
- ~~Add Timestamp to encryption..~~
132
-
133
- ~~For now a sniffer could track a successfull request to the server and extract the HTTP_AUTHORIZATION HEADER for this request.~~
134
-
135
- ~~He got the encrypted message for the specific request && signature -> No security anymore...~~
136
-
137
-
138
-
139
-
140
62
  ## Contributing
141
63
 
142
64
  1. Fork it ( http://github.com/benny1992/rack-simple_auth/fork )
@@ -144,14 +66,3 @@ It contains following information:
144
66
  3. Commit your changes (`git commit -am 'Add some feature'`)
145
67
  4. Push to the branch (`git push origin my-new-feature`)
146
68
  5. Create new Pull Request
147
-
148
-
149
-
150
-
151
-
152
-
153
-
154
-
155
-
156
-
157
-
@@ -0,0 +1 @@
1
+ 7d8e86a09ec275f7531af9f17a77fb8e307bd95f0d4593627b94441d59f0deb95d4240757216ecb70b65a2e40a5d4d7cba8bc5bf002b458077ca73ad0f2cac11
@@ -1,6 +1,9 @@
1
1
  require 'rack/simple_auth/version'
2
2
  require 'rack/simple_auth/logger'
3
- require 'rack/simple_auth/hmac'
3
+
4
+ # HMAC utilities
5
+ require 'rack/simple_auth/hmac/config'
6
+ require 'rack/simple_auth/hmac/middleware'
4
7
 
5
8
  require 'json'
6
9
 
@@ -0,0 +1,34 @@
1
+ module Rack
2
+ module SimpleAuth
3
+ module HMAC
4
+ # class Config
5
+ # Config objects will be instantiated out of this class when using Rack::SimpleAuth::HMAC::Middleware
6
+ # Also the public instance attributes / virtual attributes will be populated via the Middleware DSL
7
+ class Config < Hash
8
+ attr_writer :tolerance, :stepsize
9
+ attr_writer :secret, :signature
10
+ attr_accessor :logpath, :request_config
11
+
12
+ def method_missing(name, *args)
13
+ fail "Unkown option #{name.to_s.gsub!('=', '')}"
14
+ end
15
+
16
+ def tolerance
17
+ @tolerance || 1
18
+ end
19
+
20
+ def stepsize
21
+ @stepsize || 1
22
+ end
23
+
24
+ def secret
25
+ @secret || ''
26
+ end
27
+
28
+ def signature
29
+ @signature || ''
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,180 @@
1
+ module Rack
2
+ # Module which Contains different Authorization / Authentication Classes (HMAC, ..)
3
+ module SimpleAuth
4
+ # module HMAC
5
+ # Contains different classes for authorizing against a hmac signed request
6
+ module HMAC
7
+ # class Middleware
8
+ # Middleware class which represents the interface to the rack api via Middleware#call
9
+ # and checks if a request is hmac authorized.
10
+ #
11
+ # Usage:
12
+ #
13
+ # require 'rack/lobster'
14
+ # require 'rack/simple_auth'
15
+ #
16
+ # request_config = {
17
+ # 'GET' => 'path',
18
+ # 'POST' => 'params',
19
+ # 'DELETE' => 'path',
20
+ # 'PUT' => 'path',
21
+ # 'PATCH' => 'path'
22
+ # }
23
+ #
24
+ # use Rack::SimpleAuth::HMAC::Middleware do |options|
25
+ # options.tolerance = 0.5
26
+ # options.stepsize = 0.01
27
+ #
28
+ # options.secret = 'test_secret'
29
+ # options.signature = 'test_signature'
30
+ #
31
+ # options.logpath = "#{File.expand_path('..', __FILE__)}/logs"
32
+ # options.request_config = request_config
33
+ # end
34
+ #
35
+ # run Rack::Lobster.new
36
+ class Middleware
37
+ def self.method_missing(name, *args)
38
+ msg = "Did you try to use HMAC Middleware as Rack Application via 'run'?\n" if name.eql?(:call)
39
+ msg << "method: #{name}\n"
40
+ msg << "args: #{args.inspect}\n" unless name.eql?(:call)
41
+ msg << "on: #{self}"
42
+
43
+ fail NoMethodError, msg
44
+ end
45
+ # Constructor for Rack Middleware (passing the rack stack)
46
+ # @param [Rack Application] app [next middleware or rack app which gets called]
47
+ # @param [Hash] config [config hash where tolerance, secret, signature etc.. are set]
48
+ def initialize(app, &block)
49
+ @app, @config = app, Config.new
50
+ yield @config if block_given?
51
+
52
+ valid_stepsize?(0.01)
53
+ valid_tolerance?
54
+ end
55
+
56
+ # call Method for Rack Middleware/Application
57
+ # @param [Hash] env [Rack Env Hash which contains headers etc..]
58
+ def call(env)
59
+ @request = Rack::Request.new(env)
60
+
61
+ if valid_request?
62
+ @app.call(env)
63
+ else
64
+ response = Rack::Response.new('Unauthorized', 401, 'Content-Type' => 'text/html')
65
+ response.finish
66
+ end
67
+ end
68
+
69
+ # checks for valid HMAC Request
70
+ # @return [boolean] ValidationStatus [If authorized returns true, else false]
71
+ def valid_request?
72
+ if @request.env['HTTP_AUTHORIZATION'].nil?
73
+ log
74
+
75
+ return false
76
+ end
77
+
78
+ if request_signature == @config.signature && allowed_messages.include?(request_message)
79
+ true
80
+ else
81
+ log
82
+
83
+ false
84
+ end
85
+ end
86
+
87
+ private
88
+
89
+ # Get request signature
90
+ def request_signature
91
+ @request.env['HTTP_AUTHORIZATION'].split(':').last
92
+ end
93
+
94
+ # Get encrypted request message
95
+ def request_message
96
+ @request.env['HTTP_AUTHORIZATION'].split(':').first
97
+ end
98
+
99
+ # Builds Array of allowed message hashs
100
+ # @return [Array] hash_array [allowed message hashes as array]
101
+ def allowed_messages
102
+ messages = []
103
+
104
+ date = Time.now.to_i.freeze
105
+ (-(@config.tolerance)..@config.tolerance).step(@config.stepsize) do |i|
106
+ i = i.round(2)
107
+ messages << OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), @config.secret, message(date, i))
108
+ end
109
+
110
+ messages
111
+ end
112
+
113
+ # Get Message for current Request and delay
114
+ # @param [Fixnum] date [current date in timestamp format]
115
+ # @param [Fixnum] delay [delay in timestamp format]
116
+ # @return [Hash] message [message which will be encrypted]
117
+ def message(date, delay = 0)
118
+ date += delay
119
+ date = date.to_i if delay.eql?(0.0)
120
+
121
+ # Print out Delay and Timestamp for each range step in development environment
122
+ puts "Delay: #{delay}, Timestamp: #{date}" if ENV['RACK_ENV'].eql?('development')
123
+
124
+ { 'method' => @request.request_method, 'date' => date, 'data' => request_data(@config) }.to_json
125
+ end
126
+
127
+ # Get Request Data specified by Config
128
+ # @param [Hash] config [Config Hash containing what type of info is data for each request]
129
+ # @return [String|Hash] data [Data for each request]
130
+ def request_data(config)
131
+ if @config.request_config[@request.request_method] == 'path' || @config.request_config[@request.request_method] == 'params'
132
+ @request.send(@config.request_config[@request.request_method].to_sym)
133
+ else
134
+ fail "Not a valid option #{@config.request_config[@request.request_method]} - Use either params or path"
135
+ end
136
+ end
137
+
138
+ # Log to @config.logpath if request is unathorized
139
+ # Contains:
140
+ # - allowed messages and received message
141
+ # - time when request was made
142
+ # - type of request
143
+ # - requested path
144
+ def log
145
+ if @config.logpath
146
+ msg = "#{Time.new} - #{@request.request_method} #{@request.path} - 400 Unauthorized\n"
147
+ msg << "HTTP_AUTHORIZATION: #{@request.env['HTTP_AUTHORIZATION']}\n"
148
+ msg << "Auth Message Config: #{@config.request_config[@request.request_method]}\n"
149
+
150
+ if allowed_messages
151
+ msg << "Allowed Encrypted Messages:\n"
152
+ allowed_messages.each do |hash|
153
+ msg << "#{hash}\n"
154
+ end
155
+ end
156
+
157
+ msg << "Auth Signature: #{@config.signature}"
158
+
159
+ Rack::SimpleAuth::Logger.log(@config.logpath, ENV['RACK_ENV'], msg)
160
+ end
161
+ end
162
+
163
+ # Check if Stepsize is valid, if > min ensure stepsize is min stepsize
164
+ # @param [float] min [minimum allowed stepsize]
165
+ # check @config.stepsize < min
166
+ def valid_stepsize?(min)
167
+ fail "Minimum allowed stepsize is #{min}" if @config.stepsize < min
168
+ end
169
+
170
+ # Check if tolerance is valid, tolerance must be greater than stepsize
171
+ # check @config.tolerance < @config.stepsize
172
+ def valid_tolerance?
173
+ if @config.tolerance < @config.stepsize
174
+ fail "Tolerance must be greater than stepsize - Tolerance: #{@config.tolerance}, Stepsize: #{@config.stepsize}"
175
+ end
176
+ end
177
+ end # Middleware
178
+ end # HMAC
179
+ end # SimpleAuth
180
+ end # Rack
@@ -0,0 +1,18 @@
1
+ module Rack
2
+ module SimpleAuth
3
+ # class Logger
4
+ # This class receives a logpath, env and message and
5
+ # prints the message to the specified logpath for the proper env file (eg.: /path/to/file/test_error.log for test env)
6
+ module Logger
7
+ def self.log(logpath, env = 'development', msg)
8
+ system("mkdir #{logpath}") unless Dir.exist?("#{logpath}")
9
+ open("#{logpath}/#{env}_error.log", 'a') do |f|
10
+ f << "#{msg}\n"
11
+ end
12
+
13
+ # Print out log to stdout for dev env
14
+ puts msg if ENV['RACK_ENV'].eql?('development')
15
+ end
16
+ end # Logger
17
+ end # SimpleAuth
18
+ end # Rack
@@ -2,6 +2,6 @@ module Rack
2
2
  # Module which Contains different Authorization / Authentication Classes (HMAC, ..)
3
3
  module SimpleAuth
4
4
  # Current Gem Version
5
- VERSION = '0.1.4'
5
+ VERSION = '1.0.0rc'
6
6
  end
7
7
  end
data/rubocop-todo.yml CHANGED
@@ -11,7 +11,7 @@ CyclomaticComplexity:
11
11
 
12
12
  # Offense count: 55
13
13
  LineLength:
14
- Max: 129
14
+ Max: 150
15
15
 
16
16
  # Offense count: 3
17
17
  # Configuration parameters: CountComments.
data/task/console.rake ADDED
@@ -0,0 +1,7 @@
1
+ task :console do
2
+ require 'irb'
3
+ require 'irb/completion'
4
+ require 'rack/simple_auth'
5
+ ARGV.clear
6
+ IRB.start
7
+ end
data/task/test.rake CHANGED
@@ -16,7 +16,7 @@ namespace :test do
16
16
  # end
17
17
 
18
18
  task :cleanup do
19
- system("rm -rf #{File.expand_path('../../', __FILE__)}/test/logs")
19
+ system("rm -rf #{File.expand_path('../../', __FILE__)}/test/rack/simple_auth/hmac/logs")
20
20
  end
21
21
  end
22
22
 
@@ -0,0 +1,23 @@
1
+ require 'rack/lobster'
2
+ require 'rack/simple_auth'
3
+
4
+ request_config = {
5
+ 'GET' => 'path',
6
+ 'POST' => 'params',
7
+ 'DELETE' => 'path',
8
+ 'PUT' => 'path',
9
+ 'PATCH' => 'path'
10
+ }
11
+
12
+ use Rack::SimpleAuth::HMAC::Middleware do |options|
13
+ options.tolerance = 0.5
14
+ options.stepsize = 0.01
15
+
16
+ options.secret = 'test_secret'
17
+ options.signature = 'test_signature'
18
+
19
+ options.logpath = "#{File.expand_path('..', __FILE__)}/logs"
20
+ options.request_config = request_config
21
+ end
22
+
23
+ run Rack::Lobster.new
@@ -0,0 +1,23 @@
1
+ require 'rack/lobster'
2
+ require 'rack/simple_auth'
3
+
4
+ request_config = {
5
+ 'GET' => 'pathasdf',
6
+ 'POST' => 'paramas',
7
+ 'DELETE' => 'path',
8
+ 'PUT' => 'path',
9
+ 'PATCH' => 'path',
10
+ }
11
+
12
+ use Rack::SimpleAuth::HMAC::Middleware do |options|
13
+ options.tolerance = 0.5
14
+ options.stepsize = 0.01
15
+
16
+ options.secret = 'test_secret'
17
+ options.signature = 'test_signature'
18
+
19
+ options.logpath = "#{File.expand_path('..', __FILE__)}/logs"
20
+ options.request_config = request_config
21
+ end
22
+
23
+ run Rack::Lobster.new
@@ -0,0 +1,24 @@
1
+ require 'rack/lobster'
2
+ require 'rack/simple_auth'
3
+
4
+ request_config = {
5
+ 'GET' => 'path',
6
+ 'POST' => 'params',
7
+ 'DELETE' => 'path',
8
+ 'PUT' => 'path',
9
+ 'PATCH' => 'path'
10
+ }
11
+
12
+ use Rack::SimpleAuth::HMAC::Middleware do |options|
13
+ options.tolerance = 0.5
14
+ options.stepsize = 0.01
15
+
16
+ options.secret = 'test_secret'
17
+ options.signature = 'test_signature'
18
+
19
+ options.logpath = "#{File.expand_path('..', __FILE__)}/logs"
20
+ options.request_config = request_config
21
+ options.unknown_option = 'unknown'
22
+ end
23
+
24
+ run Rack::Lobster.new
@@ -0,0 +1,22 @@
1
+ require 'rack/lobster'
2
+ require 'rack/simple_auth'
3
+
4
+ request_config = {
5
+ 'GET' => 'pathasdf',
6
+ 'POST' => 'paramas',
7
+ 'DELETE' => 'path',
8
+ 'PUT' => 'path',
9
+ 'PATCH' => 'path',
10
+ }
11
+
12
+ # Middleware should not be runnable...
13
+ run Rack::SimpleAuth::HMAC::Middleware do |options|
14
+ options.tolerance = 0.5
15
+ options.stepsize = 0.01
16
+
17
+ options.secret = 'test_secret'
18
+ options.signature = 'test_signature'
19
+
20
+ options.logpath = "#{File.expand_path('..', __FILE__)}/logs"
21
+ options.request_config = request_config
22
+ end
@@ -0,0 +1,23 @@
1
+ require 'rack/lobster'
2
+ require 'rack/simple_auth'
3
+
4
+ request_config = {
5
+ 'GET' => 'path',
6
+ 'POST' => 'params',
7
+ 'DELETE' => 'path',
8
+ 'PUT' => 'path',
9
+ 'PATCH' => 'path',
10
+ }
11
+
12
+ use Rack::SimpleAuth::HMAC::Middleware do |options|
13
+ options.tolerance = 1
14
+ options.stepsize = 0.0001
15
+
16
+ options.secret = 'test_secret'
17
+ options.signature = 'test_signature'
18
+
19
+ options.logpath = "#{File.expand_path('..', __FILE__)}/logs"
20
+ options.request_config = request_config
21
+ end
22
+
23
+ run Rack::Lobster.new
@@ -0,0 +1,23 @@
1
+ require 'rack/lobster'
2
+ require 'rack/simple_auth'
3
+
4
+ request_config = {
5
+ 'GET' => 'path',
6
+ 'POST' => 'params',
7
+ 'DELETE' => 'path',
8
+ 'PUT' => 'path',
9
+ 'PATCH' => 'path',
10
+ }
11
+
12
+ use Rack::SimpleAuth::HMAC::Middleware do |options|
13
+ options.tolerance = 0.3
14
+ options.stepsize = 0.5
15
+
16
+ options.secret = 'test_secret'
17
+ options.signature = 'test_signature'
18
+
19
+ options.logpath = "#{File.expand_path('..', __FILE__)}/logs"
20
+ options.request_config = request_config
21
+ end
22
+
23
+ run Rack::Lobster.new
@@ -0,0 +1,26 @@
1
+ require 'test_helper.rb'
2
+
3
+ # Test HMAC Authorization Method
4
+ class HMACFailRunTest < MiniTest::Unit::TestCase
5
+ include Rack::Test::Methods
6
+
7
+ def setup
8
+ @secret = 'test_secret'
9
+ @signature = 'test_signature'
10
+ end
11
+
12
+ def app
13
+ Rack::SimpleAuth::HMAC.failrunapp
14
+ end
15
+
16
+ def test_fail
17
+ uri = '/'
18
+ content = { 'method' => 'GET', 'data' => uri }.to_json
19
+ hash = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), @secret, content)
20
+
21
+ assert_raises(NoMethodError) { get uri, {}, 'HTTP_AUTHORIZATION' => "#{hash}:#{@signature}" }
22
+ end
23
+
24
+ def teardown
25
+ end
26
+ end
@@ -10,7 +10,7 @@ class HMACFailTest < MiniTest::Unit::TestCase
10
10
  end
11
11
 
12
12
  def app
13
- Rack::SimpleAuth.failapp
13
+ Rack::SimpleAuth::HMAC.failapp
14
14
  end
15
15
 
16
16
  def test_fail
@@ -22,11 +22,15 @@ class HMACFailTest < MiniTest::Unit::TestCase
22
22
  end
23
23
 
24
24
  def test_fail_step
25
- assert_raises(RuntimeError) { Rack::Builder.parse_file("#{Rack::SimpleAuth.root}/test/config_fail_step.ru").first }
25
+ assert_raises(RuntimeError) { Rack::Builder.parse_file("#{Rack::SimpleAuth.root}/test/rack/simple_auth/hmac/config_fail_step.ru").first }
26
26
  end
27
27
 
28
28
  def test_fail_tolerance
29
- assert_raises(RuntimeError) { Rack::Builder.parse_file("#{Rack::SimpleAuth.root}/test/config_fail_tolerance.ru").first }
29
+ assert_raises(RuntimeError) { Rack::Builder.parse_file("#{Rack::SimpleAuth.root}/test/rack/simple_auth/hmac/config_fail_tolerance.ru").first }
30
+ end
31
+
32
+ def test_unknown_dsl_option
33
+ assert_raises(RuntimeError) { Rack::Builder.parse_file("#{Rack::SimpleAuth.root}/test/rack/simple_auth/hmac/config_fail_option.ru").first }
30
34
  end
31
35
 
32
36
  def teardown
@@ -10,7 +10,7 @@ class HMACTest < MiniTest::Unit::TestCase
10
10
  end
11
11
 
12
12
  def app
13
- Rack::SimpleAuth.testapp
13
+ Rack::SimpleAuth::HMAC.testapp
14
14
  end
15
15
 
16
16
  def test_get_without_auth_header
data/test/test_helper.rb CHANGED
@@ -33,14 +33,18 @@ require 'rack/simple_auth'
33
33
  module Rack
34
34
  # Module which Contains different Authorization / Authentication Classes (HMAC, ..)
35
35
  module SimpleAuth
36
- class << self
37
- attr_accessor :testapp, :failapp
36
+ # HMAC module
37
+ module HMAC
38
+ class << self
39
+ attr_accessor :testapp, :failapp, :failrunapp
40
+ end
38
41
  end
39
42
  end
40
43
  end
41
44
 
42
- Rack::SimpleAuth.testapp = Rack::Builder.parse_file("#{Rack::SimpleAuth.root}/test/config.ru").first
43
- Rack::SimpleAuth.failapp = Rack::Builder.parse_file("#{Rack::SimpleAuth.root}/test/config_fail.ru").first
45
+ Rack::SimpleAuth::HMAC.testapp = Rack::Builder.parse_file("#{Rack::SimpleAuth.root}/test/rack/simple_auth/hmac/config.ru").first
46
+ Rack::SimpleAuth::HMAC.failapp = Rack::Builder.parse_file("#{Rack::SimpleAuth.root}/test/rack/simple_auth/hmac/config_fail.ru").first
47
+ Rack::SimpleAuth::HMAC.failrunapp = Rack::Builder.parse_file("#{Rack::SimpleAuth.root}/test/rack/simple_auth/hmac/config_fail_run.ru").first
44
48
 
45
49
  @logpath = "#{File.expand_path("..", __FILE__)}/logs"
46
50
  system("mkdir #{@logpath}")
metadata CHANGED
@@ -1,81 +1,96 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: rack-simple_auth
3
- version: !ruby/object:Gem::Version
4
- version: 0.1.4
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0rc
5
5
  platform: ruby
6
- authors:
6
+ authors:
7
7
  - Benny1992
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
-
12
- date: 2014-04-28 00:00:00 Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
11
+ date: 2014-04-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
15
14
  name: rack
16
- prerelease: false
17
- requirement: &id001 !ruby/object:Gem::Requirement
18
- requirements:
19
- - &id006
20
- - ">="
21
- - !ruby/object:Gem::Version
22
- version: "0"
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
23
20
  type: :runtime
24
- version_requirements: *id001
25
- - !ruby/object:Gem::Dependency
26
- name: bundler
27
21
  prerelease: false
28
- requirement: &id002 !ruby/object:Gem::Requirement
29
- requirements:
30
- - - ~>
31
- - !ruby/object:Gem::Version
32
- version: "1.6"
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.6'
33
34
  type: :development
34
- version_requirements: *id002
35
- - !ruby/object:Gem::Dependency
36
- name: rake
37
35
  prerelease: false
38
- requirement: &id003 !ruby/object:Gem::Requirement
39
- requirements:
40
- - - ~>
41
- - !ruby/object:Gem::Version
42
- version: "10.3"
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.6'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '10.3'
43
48
  type: :development
44
- version_requirements: *id003
45
- - !ruby/object:Gem::Dependency
46
- name: coveralls
47
49
  prerelease: false
48
- requirement: &id004 !ruby/object:Gem::Requirement
49
- requirements:
50
- - - ~>
51
- - !ruby/object:Gem::Version
52
- version: "0.7"
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '10.3'
55
+ - !ruby/object:Gem::Dependency
56
+ name: coveralls
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.7'
53
62
  type: :development
54
- version_requirements: *id004
55
- - !ruby/object:Gem::Dependency
56
- name: rack-test
57
63
  prerelease: false
58
- requirement: &id005 !ruby/object:Gem::Requirement
59
- requirements:
60
- - - ~>
61
- - !ruby/object:Gem::Version
62
- version: "0.6"
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.7'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rack-test
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '0.6'
63
76
  type: :development
64
- version_requirements: *id005
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '0.6'
65
83
  description: SimpleAuth HMAC authentication
66
- email:
84
+ email:
67
85
  - r3qnbenni@gmail.com
68
86
  executables: []
69
-
70
87
  extensions: []
71
-
72
88
  extra_rdoc_files: []
73
-
74
- files:
75
- - .gitignore
76
- - .rubocop.yml
77
- - .travis.yml
78
- - .yardopts
89
+ files:
90
+ - ".gitignore"
91
+ - ".rubocop.yml"
92
+ - ".travis.yml"
93
+ - ".yardopts"
79
94
  - Gemfile
80
95
  - LICENSE.txt
81
96
  - MANIFEST
@@ -84,48 +99,54 @@ files:
84
99
  - checksum/rack-simple_auth-0.0.9.gem.sha512
85
100
  - checksum/rack-simple_auth-0.1.0.gem.sha512
86
101
  - checksum/rack-simple_auth-0.1.1.gem.sha512
102
+ - checksum/rack-simple_auth-0.1.2.gem.sha512
87
103
  - lib/rack/simple_auth.rb
88
- - lib/rack/simple_auth/hmac.rb
104
+ - lib/rack/simple_auth/hmac/config.rb
105
+ - lib/rack/simple_auth/hmac/middleware.rb
106
+ - lib/rack/simple_auth/logger.rb
89
107
  - lib/rack/simple_auth/version.rb
90
108
  - rack-simple_auth.gemspec
91
109
  - rubocop-todo.yml
92
110
  - task/build.rake
93
111
  - task/checksum.rake
112
+ - task/console.rake
94
113
  - task/default.rake
95
114
  - task/floodtest.rake
96
115
  - task/manifest.rake
97
116
  - task/test.rake
98
- - test/config.ru
99
- - test/config_fail.ru
100
- - test/config_fail_step.ru
101
- - test/config_fail_tolerance.ru
102
- - test/rack/simple_auth/hmac_fail_test.rb
103
- - test/rack/simple_auth/hmac_test.rb
117
+ - test/rack/simple_auth/hmac/config.ru
118
+ - test/rack/simple_auth/hmac/config_fail.ru
119
+ - test/rack/simple_auth/hmac/config_fail_option.ru
120
+ - test/rack/simple_auth/hmac/config_fail_run.ru
121
+ - test/rack/simple_auth/hmac/config_fail_step.ru
122
+ - test/rack/simple_auth/hmac/config_fail_tolerance.ru
123
+ - test/rack/simple_auth/hmac/hmac_fail_run_test.rb
124
+ - test/rack/simple_auth/hmac/hmac_fail_test.rb
125
+ - test/rack/simple_auth/hmac/hmac_test.rb
104
126
  - test/test_helper.rb
105
127
  homepage: https://github.com/Benny1992/rack-simple_auth
106
- licenses:
128
+ licenses:
107
129
  - MIT
108
130
  metadata: {}
109
-
110
- post_install_message: "Please report any issues at: https://github.com/Benny1992/rack-simple_auth/issues/new"
131
+ post_install_message: 'Please report any issues at: https://github.com/Benny1992/rack-simple_auth/issues/new'
111
132
  rdoc_options: []
112
-
113
- require_paths:
133
+ require_paths:
114
134
  - lib
115
- required_ruby_version: !ruby/object:Gem::Requirement
116
- requirements:
135
+ required_ruby_version: !ruby/object:Gem::Requirement
136
+ requirements:
117
137
  - - ">="
118
- - !ruby/object:Gem::Version
138
+ - !ruby/object:Gem::Version
119
139
  version: 1.8.7
120
- required_rubygems_version: !ruby/object:Gem::Requirement
121
- requirements:
122
- - *id006
140
+ required_rubygems_version: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - ">"
143
+ - !ruby/object:Gem::Version
144
+ version: 1.3.1
123
145
  requirements: []
124
-
125
146
  rubyforge_project:
126
147
  rubygems_version: 2.2.2
127
148
  signing_key:
128
149
  specification_version: 4
129
150
  summary: SimpleAuth HMAC authentication
130
151
  test_files: []
131
-
152
+ has_rdoc:
@@ -1,156 +0,0 @@
1
- module Rack
2
- # Module which Contains different Authorization / Authentication Classes (HMAC, ..)
3
- module SimpleAuth
4
- # HMAC Middleware uses HMAC Authorization for Securing an REST API
5
- class HMAC
6
- # Constructor for Rack Middleware (passing the rack stack)
7
- # @param [Rack Application] app [next middleware or rack app which gets called]
8
- # @param [Hash] config [config hash where tolerance, secret, signature etc.. are set]
9
- def initialize(app, config)
10
- @app = app
11
- @signature = config['signature'] || ''
12
- @secret = config['secret'] || ''
13
- @tolerance = config['tolerance'] || 1 # 0 if tolerance not set in config hash
14
- @logpath = config['logpath']
15
- @steps = config['steps'] || 1
16
-
17
- valid_stepsize?(0.01)
18
- valid_tolerance?
19
-
20
- @config = config
21
- end
22
-
23
- # call Method for Rack Middleware/Application
24
- # @param [Hash] env [Rack Env Hash which contains headers etc..]
25
- def call(env)
26
- @request = Rack::Request.new(env)
27
-
28
- if valid_request?
29
- @app.call(env)
30
- else
31
- response = Rack::Response.new('Unauthorized', 401, 'Content-Type' => 'text/html')
32
- response.finish
33
- end
34
- end
35
-
36
- # checks for valid HMAC Request
37
- # @return [boolean] ValidationStatus [If authorized returns true, else false]
38
- def valid_request?
39
- if @request.env['HTTP_AUTHORIZATION'].nil?
40
- log(allowed_messages)
41
-
42
- return false
43
- end
44
-
45
- if request_signature == @signature && allowed_messages.include?(request_message)
46
- true
47
- else
48
- log(allowed_messages)
49
-
50
- false
51
- end
52
- end
53
-
54
- private
55
-
56
- # Get request signature
57
- def request_signature
58
- @request.env['HTTP_AUTHORIZATION'].split(':').last
59
- end
60
-
61
- # Get encrypted request message
62
- def request_message
63
- @request.env['HTTP_AUTHORIZATION'].split(':').first
64
- end
65
-
66
- # Builds Array of allowed message hashs
67
- # @return [Array] hash_array [allowed message hashes as array]
68
- def allowed_messages
69
- messages = []
70
-
71
- @date = Time.now.to_i.freeze
72
- (-(@tolerance)..@tolerance).step(@steps) do |i|
73
- i = i.round(2)
74
- messages << OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), @secret, message(i))
75
- end
76
-
77
- messages
78
- end
79
-
80
- # Get Message for current Request and delay
81
- # @param [Fixnum] delay [delay in timestamp format]
82
- # @return [Hash] message [message which will be encrypted]
83
- def message(delay = 0)
84
- date = @date + delay
85
- date = date.to_i if delay.eql?(0.0)
86
-
87
- # Print out Delay and Timestamp for each range step in development environment
88
- puts "Delay: #{delay}, Timestamp: #{date}" if ENV['RACK_ENV'].eql?('development')
89
-
90
- case @request.request_method
91
- when 'GET'
92
- return { 'method' => @request.request_method, 'date' => date, 'data' => request_data(@config) }.to_json
93
- when 'POST'
94
- return { 'method' => @request.request_method, 'date' => date, 'data' => request_data(@config) }.to_json
95
- when 'DELETE'
96
- return { 'method' => @request.request_method, 'date' => date, 'data' => request_data(@config) }.to_json
97
- when 'PUT'
98
- return { 'method' => @request.request_method, 'date' => date, 'data' => request_data(@config) }.to_json
99
- when 'PATCH'
100
- return { 'method' => @request.request_method, 'date' => date, 'data' => request_data(@config) }.to_json
101
- end
102
- end
103
-
104
- # Get Request Data specified by Config
105
- # @param [Hash] config [Config Hash containing what type of info is data for each request]
106
- # @return [String|Hash] data [Data for each request]
107
- def request_data(config)
108
- if config[@request.request_method] == 'path' || config[@request.request_method] == 'params'
109
- @request.send(config[@request.request_method].to_sym)
110
- else
111
- fail "Not a valid option #{config[@request.request_method]} - Use either params or path"
112
- end
113
- end
114
-
115
- # Log to @logpath if request is unathorized
116
- # Contains:
117
- # - allowed messages and received message
118
- # - time when request was made
119
- # - type of request
120
- # - requested path
121
- def log(hash_array)
122
- if @logpath
123
- msg = "#{Time.new} - #{@request.request_method} #{@request.path} - 400 Unauthorized\n"
124
- msg << "HTTP_AUTHORIZATION: #{@request.env['HTTP_AUTHORIZATION']}\n"
125
- msg << "Auth Message Config: #{@config[@request.request_method]}\n"
126
-
127
- if hash_array
128
- msg << "Allowed Encrypted Messages:\n"
129
- hash_array.each do |hash|
130
- msg << "#{hash}\n"
131
- end
132
- end
133
-
134
- msg << "Auth Signature: #{@signature}"
135
-
136
- Rack::SimpleAuth::Logger.log(@logpath, ENV['RACK_ENV'], msg)
137
- end
138
- end
139
-
140
- # Check if Stepsize is valid, if > min ensure stepsize is min stepsize
141
- # @param [float] min [minimum allowed stepsize]
142
- def valid_stepsize?(min)
143
- if @steps < min
144
- fail "Minimum allowed stepsize is #{min}"
145
- end
146
- end
147
-
148
- # Check if tolerance is valid, tolerance must be greater than stepsize
149
- def valid_tolerance?
150
- if @tolerance < @steps
151
- fail "Tolerance must be greater than stepsize - Tolerance: #{@tolerance}, Stepsize: #{@steps}"
152
- end
153
- end
154
- end # HMAC
155
- end # SimpleAuth
156
- end # Rack
data/test/config.ru DELETED
@@ -1,18 +0,0 @@
1
- require 'rack/lobster'
2
- require 'rack/simple_auth'
3
-
4
- config = {
5
- 'GET' => 'path',
6
- 'POST' => 'params',
7
- 'DELETE' => 'path',
8
- 'PUT' => 'path',
9
- 'PATCH' => 'path',
10
- 'tolerance' => 0.5,
11
- 'signature' => 'test_signature',
12
- 'secret' => 'test_secret',
13
- 'logpath' => "#{File.expand_path('..', __FILE__)}/logs",
14
- 'steps' => 0.01
15
- }
16
-
17
- use Rack::SimpleAuth::HMAC, config
18
- run Rack::Lobster.new
data/test/config_fail.ru DELETED
@@ -1,15 +0,0 @@
1
- require 'rack/lobster'
2
- require 'rack/simple_auth'
3
-
4
- config = {
5
- 'GET' => 'pathasdf',
6
- 'POST' => 'paramas',
7
- 'DELETE' => 'path',
8
- 'PUT' => 'path',
9
- 'PATCH' => 'path',
10
- 'signature' => 'test_signature',
11
- 'secret' => 'test_secret'
12
- }
13
-
14
- use Rack::SimpleAuth::HMAC, config
15
- run Rack::Lobster.new
@@ -1,17 +0,0 @@
1
- require 'rack/lobster'
2
- require 'rack/simple_auth'
3
-
4
- config = {
5
- 'GET' => 'path',
6
- 'POST' => 'params',
7
- 'DELETE' => 'path',
8
- 'PUT' => 'path',
9
- 'PATCH' => 'path',
10
- 'signature' => 'test_signature',
11
- 'secret' => 'test_secret',
12
- 'steps' => 0.0001,
13
- 'tolerance' => 1
14
- }
15
-
16
- use Rack::SimpleAuth::HMAC, config
17
- run Rack::Lobster.new
@@ -1,17 +0,0 @@
1
- require 'rack/lobster'
2
- require 'rack/simple_auth'
3
-
4
- config = {
5
- 'GET' => 'path',
6
- 'POST' => 'params',
7
- 'DELETE' => 'path',
8
- 'PUT' => 'path',
9
- 'PATCH' => 'path',
10
- 'signature' => 'test_signature',
11
- 'secret' => 'test_secret',
12
- 'steps' => 0.5,
13
- 'tolerance' => 0.3
14
- }
15
-
16
- use Rack::SimpleAuth::HMAC, config
17
- run Rack::Lobster.new