rack-simple_auth 0.1.4 → 1.0.0rc

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
- ---
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