soar_authentication_token 3.0.5 → 3.0.6

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: e7996fa1857b1b57684079260f326c2f706a0f78
4
- data.tar.gz: 44ccf374373fbc7d6596fd1638e2e4016d0f7cee
3
+ metadata.gz: 275c14010dd496f6d91233ac79a73fd9755b628a
4
+ data.tar.gz: 190b1794277f7916ba2cb551946777c5bc98af66
5
5
  SHA512:
6
- metadata.gz: 64764a63384c843c5bf5c056f2a1f479b72c234f42d2d2ba3daa55690b60627eff2446580910ab007952dd432ec31256b6794af979041977f83f5f733f69315f
7
- data.tar.gz: a385a5cf6a96bb4b927b924844417e5551e75a8085fda8fb8fd18670cedbbdf5dcbb550d01a46284fc8e7bb2fa48158745625b5794be9d525681e2435222d6c6
6
+ metadata.gz: a622e8ab76aae89f5578a0d30051351d2d481d56cbb1804ad2369d45886dbf54fe9c4abe36251225c2f99feffdb09b57d1e36b7451125c7ab5e70790ff474ec7
7
+ data.tar.gz: fe4d4a1a62f2705632d9e5a1839d5839ddd3552956616533e817761a4b17e1a89190332d1e4ff1dfdd0a777cc61f374a56cfa07b8f55f0e2fd1288da8ac6bc96
data/.gitignore CHANGED
@@ -1,3 +1,4 @@
1
1
  Gemfile.lock
2
2
  *.gem
3
3
  .byebug_history
4
+ coverage
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # SoarAuditingProvider
1
+ # SoarAuthenticationToken
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/soar_authentication_token.png)](https://badge.fury.io/rb/soar_authentication_token)
4
4
 
@@ -13,25 +13,28 @@ gem 'soar_authentication_token'
13
13
  ```
14
14
 
15
15
  And then execute:
16
-
17
- $ bundle
16
+ ```bash
17
+ bundle
18
+ ```
18
19
 
19
20
  Or install it yourself as:
21
+ ```bash
22
+ gem install soar_authentication_token
23
+ ```
20
24
 
21
- $ gem install soar_authentication_token
25
+ ## Configuration of generators and validators
22
26
 
23
- ## Configuration
27
+ There are three modes of operation: local, remote or static
24
28
 
25
- There are three modes of operation.
26
29
  ### Local
27
- In local mode the tokens are decoded, verified and meta extracted locally using configured key material.
30
+ In local mode the tokens are decoded, verified and meta extracted locally using configured key material. In practice the the token generation and validation services run in this mode since their roles are to generate and validate tokens.
28
31
 
29
32
  ### Remote
30
- In remote mode the tokens are passed to a validation service for dynamic validation. The key material are therefore managed on the validation service. In this mode you only have to provide the url of the validation service.
33
+ In remote mode the tokens are passed to a token validation service for validation. This allows for a centralized management of tokens. The key material are therefore managed on the validation service and . In this mode you only have to provide the url of the validation service.
31
34
 
32
35
  ### Static
33
- In this mode the validator are configured with a list of preconfigured static tokens. Incoming tokens are simply checked against this list. No extraction of meta is performed on the tokens but retrieved from the configuration. This mode is to be used in only two scenarios:
34
- * Between the various authentication token services that requires authentication between themselves. These services do not have such a service to rely on. Circular dependency.
36
+ In this mode the validator is configured with a list of preconfigured static tokens. Incoming tokens are simply checked against this list. No extraction of meta is performed on the tokens but retrieved from the configuration. Rotation of tokens is simple since many tokens can be configured. This mode is to be used in only two scenarios:
37
+ * Between the various authentication token services that requires authentication between themselves. These services themselves do not the benefit of another centralized authentication service to rely on.
35
38
  * In test scenarios where you do not want to pull in the authentication services to perform testing of your services.
36
39
 
37
40
 
@@ -39,33 +42,123 @@ In this mode the validator are configured with a list of preconfigured static to
39
42
 
40
43
  Run the rspec test tests using docker compose:
41
44
 
42
- $ docker-compose build
43
- $ docker-compose run --rm soar-authentication-token
44
-
45
- Properly clean up containers afterwards:
46
-
47
- $ docker-compose down
48
-
49
- Locally run a subset:
50
-
51
- $ bundle exec rspec -cfd spec/rack_middleware_spec.rb
52
-
45
+ ```bash
46
+ docker-compose build
47
+ docker-compose run --rm soar-authentication-token
48
+ docker-compose down
49
+ ```
53
50
 
54
51
  ## Updating
55
52
 
56
- In order to pull the latest from the referenced projects, simply the following command:
53
+ For test purposes this repo relies on various other repos with services. This is to test the interaction between the generator and validation clients and these services. In order to pull the latest from the referenced projects and build fresh docker images, simply the following commands:
57
54
 
58
55
  ```bash
59
56
  git pull && git submodule foreach 'git fetch origin --tags; git checkout master; git pull'
57
+ docker-compose down
60
58
  docker-compose build
61
59
  ```
62
60
 
63
61
  ## Usage
64
62
 
63
+ ### KeypairGenerator
64
+
65
+ In support of generating JWT tokens this class is responsible for generating an EC keypairs in PEM format. Use this when rotating keypairs in production or for testing the generators/validators.
66
+
67
+ ```ruby
68
+ generator = SoarAuthenticationToken::KeypairGenerator.new
69
+ private_key, public_key = generator.generate
70
+ ```
71
+
72
+ ### RackMiddleware
73
+
74
+ The rack middleware allows you to perform validation of all requests before it even hits your resource. The middleware also populates the 'user' key in the rack session with the authenticated identifier and the 'auth_token_meta' key with meta regarding the authentication that might be useful to more sensitive services.
75
+
76
+ First step is to configure the middleware. Actually you are not configuring the middleware but the TokenValidator instance that will be used in the validation. Most of the time you will be reaching out to a remote validation service and configure it as such:
77
+
78
+ ```ruby
79
+ @iut_configuration = {
80
+ 'mode' => 'remote',
81
+ 'validator-url' => 'http://authentication-token-validator-service:9393/validate'
82
+ }
83
+ @iut = SoarAuthenticationToken::RackMiddleware.new(@test_app, @iut_configuration)
84
+ ```
85
+
86
+ The middleware will look for the authentication token in the HTTP header 'AUTHORIZATION'.
87
+
88
+ Please refer to the rack middleware spec for detailed examples on how to use the middleware.
65
89
 
90
+ ### TokenGenerator
66
91
 
67
- ## Detailed example
92
+ The class generates tokens or requests a token from a generator service as configured.
68
93
 
94
+ For remote token generation, configure as such:
95
+ ```ruby
96
+ @configuration_remote = {
97
+ 'mode' => 'remote',
98
+ 'generator-url' => 'http://authentication-token-generator-service:9393/generate',
99
+ 'generator-client-auth-token' => 'xxxx'
100
+ }
101
+ ```
102
+
103
+ For local token generation, configure as such:
104
+ ```ruby
105
+ generator = SoarAuthenticationToken::KeypairGenerator.new
106
+ private_key, public_key = generator.generate
107
+ @configuration_local = {
108
+ 'mode' => 'local',
109
+ 'private_key' => private_key
110
+ }
111
+ ```
112
+
113
+ Create storage client. The example here uses a local stub client that uses a in-memory store.
114
+ ```ruby
115
+ gem 'auth_token_store_provider', "~> 1.0.1"
116
+ require 'auth_token_store_provider'
117
+ store = AuthTokenStoreProvider::StubClient.new
118
+ ```
119
+
120
+ After configuration you simply generate a token like this:
121
+ ```ruby
122
+ generator = SoarAuthenticationToken::TokenGenerator.new(configuration)
123
+ generator.inject_store_provider(store)
124
+ token, token_generator_meta = generator.generate(authenticated_identifier: 'someone@hetzner.co.za', flow_identifier: 'test-flow-id')
125
+ ```
126
+
127
+ ### TokenValidator
128
+
129
+ The class validates tokens or requests validation of a token from a validation service as configured.
130
+
131
+ For remote token validation, configure as such:
132
+ ```ruby
133
+ @configuration_remote = {
134
+ 'mode' => 'remote',
135
+ 'validator-url' => 'http://authentication-token-validator-service:9393/validate',
136
+ }
137
+ ```
138
+
139
+ For local token validation, configure as such:
140
+ ```ruby
141
+ generator = SoarAuthenticationToken::KeypairGenerator.new
142
+ private_key, public_key = generator.generate
143
+ @configuration_local = {
144
+ 'mode' => 'local',
145
+ 'public_key' => public_key
146
+ }
147
+ ```
148
+
149
+ Create storage client. The example here uses a local stub client that uses a in-memory store.
150
+ ```ruby
151
+ gem 'auth_token_store_provider', "~> 1.0.1"
152
+ require 'auth_token_store_provider'
153
+ store = AuthTokenStoreProvider::StubClient.new
154
+ ```
155
+
156
+ After configuration you simply valiate a token like this:
157
+ ```ruby
158
+ validator = SoarAuthenticationToken::TokenValidator.new(configuration)
159
+ validator.inject_store_provider(store)
160
+ token_validity, token_validator_meta, messages = validator.validate(authentication_token: token, flow_identifier: 'test-flow-id')
161
+ ```
69
162
 
70
163
 
71
164
  ## Contributing
@@ -2,9 +2,6 @@ require 'openssl'
2
2
 
3
3
  module SoarAuthenticationToken
4
4
  class KeypairGenerator
5
- def initialize
6
- end
7
-
8
5
  def generate
9
6
  private_key = OpenSSL::PKey::EC.new 'secp521r1'
10
7
  private_key.generate_key
@@ -12,8 +9,5 @@ module SoarAuthenticationToken
12
9
  public_key.private_key = nil
13
10
  [private_key.to_pem, public_key.to_pem]
14
11
  end
15
-
16
- private
17
-
18
12
  end
19
13
  end
@@ -9,21 +9,27 @@ module SoarAuthenticationToken
9
9
  end
10
10
 
11
11
  def call(env)
12
- request = Rack::Request.new env
13
- session, params = request.session, request.params
14
- token_valid, token_meta, message = validate_and_resolve_token(request.env['HTTP_AUTHORIZATION'],params['flow_identifier'])
12
+ session, params, token, flow_id = get_request_information(env)
13
+ token_valid, token_meta, message = validate_and_resolve_token(token,flow_id)
15
14
  if token_valid
16
15
  session['user'] = token_meta['authenticated_identifier']
17
16
  session['auth_token_meta'] = token_meta
18
- @app.call env
19
- else
20
- audit_token_rejection("Token rejected due to #{message}",params['flow_identifier'])
21
- [401, {"Content-Type" => "text/html"}, ["401 - Not authenticated"]]
17
+ return @app.call env
22
18
  end
19
+ audit_token_rejection("Token rejected due to #{message}",flow_id)
20
+ rejection
23
21
  end
24
22
 
25
23
  private
26
24
 
25
+ def get_request_information(env)
26
+ request = Rack::Request.new env
27
+ [ request.session,
28
+ request.params,
29
+ request.env['HTTP_AUTHORIZATION'],
30
+ request.params['flow_identifier'] ]
31
+ end
32
+
27
33
  def validate_and_resolve_token(authentication_token,flow_identifier)
28
34
  token_validator = SoarAuthenticationToken::TokenValidator.new(@configuration)
29
35
  token_validator.validate(authentication_token: authentication_token,flow_identifier: flow_identifier)
@@ -32,5 +38,9 @@ module SoarAuthenticationToken
32
38
  def audit_token_rejection(message, flow_id)
33
39
  @auditing.warn(message,flow_id) if @auditing
34
40
  end
41
+
42
+ def rejection
43
+ [401, {"Content-Type" => "text/html"}, ["401 - Not authenticated"]]
44
+ end
35
45
  end
36
46
  end
@@ -31,7 +31,7 @@ module SoarAuthenticationToken
31
31
  private
32
32
 
33
33
  def generate_locally(authenticated_identifier)
34
- token_meta = meta(authenticated_identifier)
34
+ token_meta = generate_meta(authenticated_identifier)
35
35
  token = encode(token_meta)
36
36
  add_token_to_store(token_meta)
37
37
  [token, token_meta]
@@ -60,7 +60,7 @@ module SoarAuthenticationToken
60
60
  body['data']['token']
61
61
  end
62
62
 
63
- def meta(authenticated_identifier)
63
+ def generate_meta(authenticated_identifier)
64
64
  current_time = Time.now
65
65
  { 'authenticated_identifier' => authenticated_identifier,
66
66
  'token_issue_time' => current_time.utc.iso8601(3),
@@ -76,13 +76,18 @@ module SoarAuthenticationToken
76
76
  def validate_configuration
77
77
  raise "'mode' must be configured" unless @configuration['mode']
78
78
  raise "'mode' must be configured as either 'local' or 'remote'" unless ['local','remote'].include?(@configuration['mode'])
79
- if 'remote' == @configuration['mode']
80
- raise "'generator-url' must be configured in remote mode" if @configuration['generator-url'].nil?
81
- else
82
- raise "'private_key' must be configured in local mode" unless @configuration['private_key']
83
- raise "'expiry' must be configured in local mode" unless @configuration['expiry']
84
- raise "'expiry' must be an integer" unless Integer(@configuration['expiry'])
85
- end
79
+ validate_local_mode_configuration if 'local' == @configuration['mode']
80
+ validate_remote_mode_configuration if 'remote' == @configuration['mode']
81
+ end
82
+
83
+ def validate_remote_mode_configuration
84
+ raise "'generator-url' must be configured in remote mode" if @configuration['generator-url'].nil?
85
+ end
86
+
87
+ def validate_local_mode_configuration
88
+ raise "'private_key' must be configured in local mode" unless @configuration['private_key']
89
+ raise "'expiry' must be configured in local mode" unless @configuration['expiry']
90
+ raise "'expiry' must be an integer" unless Integer(@configuration['expiry'])
86
91
  end
87
92
 
88
93
  def merge_with_default_configuration(configuration)
@@ -22,7 +22,8 @@ module SoarAuthenticationToken
22
22
  def validate(authentication_token:,flow_identifier: nil)
23
23
  return validate_locally(authentication_token) if 'local' == @configuration['mode']
24
24
  return validate_statically(authentication_token) if 'static' == @configuration['mode']
25
- return validate_remotely(authentication_token,flow_identifier)
25
+ return validate_remotely(authentication_token,flow_identifier) if 'remote' == @configuration['mode']
26
+ raise 'invalid validation mode configured'
26
27
  end
27
28
 
28
29
  private
@@ -36,7 +37,6 @@ module SoarAuthenticationToken
36
37
  token_expiry_time: found_static_token['token_expiry_time'])
37
38
  return rejection_result(reason: "Expired token <#{meta['token_expiry_time']}> for <#{meta['authenticated_identifier']}>") if token_expired?(meta)
38
39
  return success_result(token_meta: meta)
39
-
40
40
  end
41
41
 
42
42
  def find_configured_static_token(authentication_token)
@@ -1,3 +1,3 @@
1
1
  module SoarAuthenticationToken
2
- VERSION = '3.0.5'
2
+ VERSION = '3.0.6'
3
3
  end
@@ -24,10 +24,12 @@ Gem::Specification.new do |spec|
24
24
  spec.add_dependency "rack", '~> 1.6', '>= 1.6.4'
25
25
  spec.add_dependency 'authenticated_client', '~> 0.0.2'
26
26
 
27
- spec.add_development_dependency 'auth_token_store_provider', "~> 1.0.1"
27
+ spec.add_development_dependency 'auth_token_store_provider', "~> 1.0"
28
28
  spec.add_development_dependency 'pry', '~> 0'
29
29
  spec.add_development_dependency 'bundler', '~> 1.3'
30
30
  spec.add_development_dependency 'rake', '~> 10.0'
31
31
  spec.add_development_dependency 'rspec', '~> 2.13'
32
32
  spec.add_development_dependency "capybara", '~> 2.1', '>= 2.1.0'
33
+ spec.add_development_dependency "simplecov", '~> 0'
34
+ spec.add_development_dependency "simplecov-rcov", '~> 0'
33
35
  end
@@ -44,7 +44,12 @@ describe SoarAuthenticationToken::RackMiddleware do
44
44
  @test_app = lambda do |env|
45
45
  request = Rack::Request.new env
46
46
  session = request.session
47
- [200, {"Content-Type"=>"text/html"}, ["tested with authenticated user #{session['user']}"] ]
47
+ test_app_response_data = {
48
+ 'message' => "tested with authenticated user #{session['user']}",
49
+ 'user' => session['user'],
50
+ 'auth_token_meta' => session['auth_token_meta']
51
+ }
52
+ [200, {"Content-Type"=>"text/html"}, test_app_response_data ]
48
53
  end
49
54
  @iut_configuration = {
50
55
  'mode' => 'remote',
@@ -68,23 +73,41 @@ describe SoarAuthenticationToken::RackMiddleware do
68
73
  end
69
74
  end
70
75
 
71
- context "when called with an environment" do
72
- it "should return 401 if the request contains no authentication token" do
73
- opts = { }
74
- code, env, body = @iut.call Rack::MockRequest.env_for('http://service', opts)
75
- expect([code, env, body]).to eq([401, {"Content-Type" => "text/html"}, ["401 - Not authenticated"]])
76
+ context "when called with a request environment" do
77
+ context 'with no authentication token' do
78
+ it "return with 401" do
79
+ opts = { }
80
+ code, env, body = @iut.call Rack::MockRequest.env_for('http://service', opts)
81
+ expect([code, env, body]).to eq([401, {"Content-Type" => "text/html"}, ["401 - Not authenticated"]])
82
+ end
76
83
  end
77
84
 
78
- it "should return 401 if the request contains an invalid authentication token" do
79
- opts = { 'HTTP_AUTHORIZATION' => @local_invalid_generator.generate(authenticated_identifier: 'a@b.com') }
80
- code, env, body = @iut.call Rack::MockRequest.env_for('http://service', opts)
81
- expect([code, env, body]).to eq([401, {"Content-Type" => "text/html"}, ["401 - Not authenticated"]])
85
+ context 'with an invalid authentication token' do
86
+ it "return with 401" do
87
+ opts = { 'HTTP_AUTHORIZATION' => @local_invalid_generator.generate(authenticated_identifier: 'a@b.com') }
88
+ code, env, body = @iut.call Rack::MockRequest.env_for('http://service', opts)
89
+ expect([code, env, body]).to eq([401, {"Content-Type" => "text/html"}, ["401 - Not authenticated"]])
90
+ end
82
91
  end
83
92
 
84
- it "should pass requests that are authenticated through to the application" do
85
- opts = { 'HTTP_AUTHORIZATION' => @local_valid_generator.generate(authenticated_identifier: 'a@b.com') }
86
- code, env, body = @iut.call Rack::MockRequest.env_for('http://service', opts)
87
- expect([code, env, body]).to eq([200, {"Content-Type"=>"text/html"}, ["tested with authenticated user a@b.com"] ])
93
+ context 'with a valid authentiation token' do
94
+ it "pass requests to the application" do
95
+ opts = { 'HTTP_AUTHORIZATION' => @local_valid_generator.generate(authenticated_identifier: 'a@b.com') }
96
+ code, env, body = @iut.call Rack::MockRequest.env_for('http://service', opts)
97
+ expect([code, env, body['message']]).to eq([200, {"Content-Type"=>"text/html"}, "tested with authenticated user a@b.com" ])
98
+ end
99
+
100
+ it "populate the 'user' key in the rack session with the authenticated user" do
101
+ opts = { 'HTTP_AUTHORIZATION' => @local_valid_generator.generate(authenticated_identifier: 'a@b.com') }
102
+ code, env, body = @iut.call Rack::MockRequest.env_for('http://service', opts)
103
+ expect(body['user']).to eq('a@b.com')
104
+ end
105
+
106
+ it "populate the 'auth_token_meta' key in the rack session with the hash containing the token meta" do
107
+ opts = { 'HTTP_AUTHORIZATION' => @local_valid_generator.generate(authenticated_identifier: 'a@b.com') }
108
+ code, env, body = @iut.call Rack::MockRequest.env_for('http://service', opts)
109
+ expect(body['auth_token_meta']['authenticated_identifier']).to eq('a@b.com')
110
+ end
88
111
  end
89
112
  end
90
113
  end
data/spec/spec_helper.rb CHANGED
@@ -1,6 +1,18 @@
1
+ require 'simplecov'
2
+ require 'simplecov-rcov'
3
+
4
+ SimpleCov.formatter = SimpleCov::Formatter::RcovFormatter
5
+ SimpleCov.start do
6
+ add_filter "/spec/"
7
+ end
8
+
1
9
  $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
10
  $LOAD_PATH.unshift File.expand_path('../../spec/support', __FILE__)
3
11
 
4
12
  require 'soar_authentication_token'
5
13
  require 'pry'
6
14
  require 'auth_token_store_provider'
15
+
16
+ def one_year_in_seconds
17
+ 31536000
18
+ end
@@ -83,51 +83,144 @@ describe SoarAuthenticationToken::TokenValidator do
83
83
  expect(SoarAuthenticationToken::VERSION).not_to be nil
84
84
  end
85
85
 
86
+ describe "#validate" do
87
+ context "given that the validator is configured for local validation" do
88
+ context 'given valid token' do
89
+ let!(:token_validation_result) {
90
+ token, token_generator_meta = @local_valid_generator.generate(authenticated_identifier: @test_identifier)
91
+ @iut_local.validate(authentication_token: token)
92
+ }
93
+ let!(:token_validity) { token_validation_result[0] }
94
+ let!(:token_meta) { token_validation_result[1] }
95
+ let!(:message) { token_validation_result[2] }
86
96
 
87
- context "when validating a token locally using the configured public key" do
88
- it 'should indicate valid if the token is valid' do
89
- token, token_generator_meta = @local_valid_generator.generate(authenticated_identifier: @test_identifier)
90
- token_validity, token_meta, message = @iut_local.validate(authentication_token: token)
91
- expect(token_validity).to eq true
92
- end
97
+ it 'indicate token is valid' do
98
+ expect(token_validity).to eq true
99
+ end
100
+
101
+ it 'provide the token meta' do
102
+ expect(token_meta['authenticated_identifier']).to eq @test_identifier
103
+ end
93
104
 
94
- it 'should indicate invalid if the token is not valid' do
95
- token, token_generator_meta = @local_invalid_generator.generate(authenticated_identifier: @test_identifier)
96
- token_validity, token_meta, message = @iut_local.validate(authentication_token: token)
97
- expect(token_validity).to eq false
98
- end
105
+ it 'provide a message indicating that the token is valid' do
106
+ expect(message).to match /Valid token for/
107
+ end
108
+ end
99
109
 
100
- it 'should provide the token meta if the token is valid' do
101
- token, token_generator_meta = @local_valid_generator.generate(authenticated_identifier: @test_identifier)
102
- token_validity, token_meta, message = @iut_local.validate(authentication_token: token)
103
- expect(token_meta['authenticated_identifier']).to eq @test_identifier
104
- end
110
+ context 'given expired token' do
111
+ let!(:token_validation_result) {
112
+ token, token_generator_meta = @local_valid_generator.generate(authenticated_identifier: @test_identifier)
113
+ allow(Time).to receive(:now).and_return(Time.now+one_year_in_seconds)
114
+ @iut_local.validate(authentication_token: token)
115
+ }
116
+ let!(:token_validity) { token_validation_result[0] }
117
+ let!(:token_meta) { token_validation_result[1] }
118
+ let!(:message) { token_validation_result[2] }
105
119
 
106
- it 'should not provide the token meta if the token is invalid' do
107
- token, token_generator_meta = @local_invalid_generator.generate(authenticated_identifier: @test_identifier)
108
- token_validity, token_meta, message = @iut_local.validate(authentication_token: token)
109
- expect(token_meta).to eq nil
110
- end
120
+ it 'indicate token is invalid' do
121
+ expect(token_validity).to eq false
122
+ end
111
123
 
112
- it 'should provide a message indicating that that token is valid if the token is valid' do
113
- end
124
+ it 'does not provide the token meta' do
125
+ expect(token_meta).to eq nil
126
+ end
114
127
 
115
- it 'should indicate as invalid tokens that are older than the configured expiry time' do
116
- #TODO
117
- #expect(true).to eq false
118
- end
128
+ it 'provide a message indicating that the token is invalid' do
129
+ expect(message).to match /Expired token/
130
+ end
131
+ end
119
132
 
120
- it 'should indicate as valid tokens that are not older than the configured expiry time' do
121
- #TODO
122
- #expect(true).to eq false
123
- end
133
+ context 'given unknown token (not in store)' do
134
+ let!(:token_validation_result) {
135
+ token, token_generator_meta = @local_valid_generator.generate(authenticated_identifier: @test_identifier)
136
+ @test_store.instance_variable_set("@store", []) #clear store
137
+ @iut_local.validate(authentication_token: token)
138
+ }
139
+ let!(:token_validity) { token_validation_result[0] }
140
+ let!(:token_meta) { token_validation_result[1] }
141
+ let!(:message) { token_validation_result[2] }
142
+
143
+ it 'indicate that token is invalid' do
144
+ expect(token_validity).to eq false
145
+ end
146
+
147
+ it 'does not provide the token meta' do
148
+ expect(token_meta).to eq nil
149
+ end
150
+
151
+ it 'provide a message indicating that the token is invalid' do
152
+ expect(message).to match /Unknown token/
153
+ end
154
+ end
155
+
156
+ context 'given invalid token (garbage or different key)' do
157
+ let!(:token_validation_result) {
158
+ token, token_generator_meta = @remote_generator.generate(authenticated_identifier: @test_identifier)
159
+ @iut_local.validate(authentication_token: token)
160
+ }
161
+ let!(:token_validity) { token_validation_result[0] }
162
+ let!(:token_meta) { token_validation_result[1] }
163
+ let!(:message) { token_validation_result[2] }
164
+
165
+ it 'indicate token is invalid' do
166
+ expect(token_validity).to eq false
167
+ end
168
+
169
+ it 'does not provide the token meta' do
170
+ expect(token_meta).to eq nil
171
+ end
124
172
 
125
- it 'should indicate as invalid tokens that are not in the token store' do
173
+ it 'provide a message indicating that the token is invalid' do
174
+ expect(message).to match /Token decode\/verification failure/
175
+ end
176
+ end
126
177
  end
127
- end
128
178
 
129
179
 
130
- describe "#validate" do
180
+
181
+ context "given that the validator is configured for remote validation" do
182
+ context 'given valid token' do
183
+ let!(:token_validation_result) {
184
+ token, token_generator_meta = @remote_generator.generate(authenticated_identifier: @test_identifier)
185
+ @iut_remote.validate(authentication_token: token)
186
+ }
187
+ let!(:token_validity) { token_validation_result[0] }
188
+ let!(:token_meta) { token_validation_result[1] }
189
+ let!(:message) { token_validation_result[2] }
190
+
191
+ it 'should indicate valid if the token is valid' do
192
+ expect(token_validity).to eq true
193
+ end
194
+
195
+ it 'should provide the authenticated_identifier if the token is valid' do
196
+ expect(token_meta['authenticated_identifier']).to eq @test_identifier
197
+ end
198
+ end
199
+
200
+ context 'given invalid (generalized) token' do
201
+ let!(:token_validation_result) {
202
+ token, token_generator_meta = @local_invalid_generator.generate(authenticated_identifier: @test_identifier)
203
+ @iut_remote.validate(authentication_token: token)
204
+ }
205
+ let!(:token_validity) { token_validation_result[0] }
206
+ let!(:token_meta) { token_validation_result[1] }
207
+ let!(:message) { token_validation_result[2] }
208
+
209
+ it 'indicate token is invalid' do
210
+ expect(token_validity).to eq false
211
+ end
212
+
213
+ it 'does not provide the token meta' do
214
+ expect(token_meta).to eq nil
215
+ end
216
+
217
+ it 'provides a message indicating the token is invalid' do
218
+ expect(message).to match /Token decode\/verification failure/
219
+ end
220
+ end
221
+
222
+
223
+ end
131
224
  context "given that the validator is configured for static tokens" do
132
225
  let(:iut) { subject.new(@static_validator_configuration) }
133
226
  context "given a token that is in the list of static tokens and not expired" do
@@ -188,41 +281,4 @@ describe SoarAuthenticationToken::TokenValidator do
188
281
  end
189
282
  end
190
283
  end
191
-
192
-
193
- context "when validating a token remotely using the configured url" do
194
- it 'should indicate valid if the token is valid' do
195
- token, token_generator_meta = @remote_generator.generate(authenticated_identifier: @test_identifier)
196
- token_validity, token_meta, message = @iut_remote.validate(authentication_token: token)
197
- expect(token_validity).to eq true
198
- end
199
-
200
- it 'should indicate invalid if the token is invalid' do
201
- token, token_generator_meta = @local_invalid_generator.generate(authenticated_identifier: @test_identifier)
202
- token_validity, token_meta, message = @iut_remote.validate(authentication_token: token)
203
- expect(token_validity).to eq false
204
- end
205
-
206
- it 'should provide the authenticated_identifier if the token is valid' do
207
- token, token_generator_meta = @remote_generator.generate(authenticated_identifier: @test_identifier)
208
- token_validity, token_meta, message = @iut_remote.validate(authentication_token: token)
209
- expect(token_meta['authenticated_identifier']).to eq @test_identifier
210
- end
211
-
212
- it 'should not provide the authenticated_identifier if the token is invalid' do
213
- token, token_generator_meta = @local_invalid_generator.generate(authenticated_identifier: @test_identifier)
214
- token_validity, token_meta, message = @iut_remote.validate(authentication_token: token)
215
- expect(token_meta).to eq nil
216
- end
217
-
218
- it 'should indicate as invalid tokens that are older than the configured expiry time' do
219
- #TODO
220
- #expect(true).to eq false
221
- end
222
-
223
- it 'should indicate as valid tokens that are not older than the configured expiry time' do
224
- #TODO
225
- #expect(true).to eq false
226
- end
227
- end
228
284
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: soar_authentication_token
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.5
4
+ version: 3.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Barney de Villiers
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-01-23 00:00:00.000000000 Z
11
+ date: 2017-01-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: soar_xt
@@ -84,14 +84,14 @@ dependencies:
84
84
  requirements:
85
85
  - - "~>"
86
86
  - !ruby/object:Gem::Version
87
- version: 1.0.1
87
+ version: '1.0'
88
88
  type: :development
89
89
  prerelease: false
90
90
  version_requirements: !ruby/object:Gem::Requirement
91
91
  requirements:
92
92
  - - "~>"
93
93
  - !ruby/object:Gem::Version
94
- version: 1.0.1
94
+ version: '1.0'
95
95
  - !ruby/object:Gem::Dependency
96
96
  name: pry
97
97
  requirement: !ruby/object:Gem::Requirement
@@ -168,6 +168,34 @@ dependencies:
168
168
  - - ">="
169
169
  - !ruby/object:Gem::Version
170
170
  version: 2.1.0
171
+ - !ruby/object:Gem::Dependency
172
+ name: simplecov
173
+ requirement: !ruby/object:Gem::Requirement
174
+ requirements:
175
+ - - "~>"
176
+ - !ruby/object:Gem::Version
177
+ version: '0'
178
+ type: :development
179
+ prerelease: false
180
+ version_requirements: !ruby/object:Gem::Requirement
181
+ requirements:
182
+ - - "~>"
183
+ - !ruby/object:Gem::Version
184
+ version: '0'
185
+ - !ruby/object:Gem::Dependency
186
+ name: simplecov-rcov
187
+ requirement: !ruby/object:Gem::Requirement
188
+ requirements:
189
+ - - "~>"
190
+ - !ruby/object:Gem::Version
191
+ version: '0'
192
+ type: :development
193
+ prerelease: false
194
+ version_requirements: !ruby/object:Gem::Requirement
195
+ requirements:
196
+ - - "~>"
197
+ - !ruby/object:Gem::Version
198
+ version: '0'
171
199
  description: Interface to the authentication token service
172
200
  email:
173
201
  - barney.de.villiers@hetzner.co.za
@@ -204,7 +232,6 @@ files:
204
232
  - sanity/.ruby-version
205
233
  - sanity/Gemfile
206
234
  - sanity/sanity.rb
207
- - sanity/sanity_benchmark.rb
208
235
  - soar_authentication_token.gemspec
209
236
  - spec/keypair_generator_spec.rb
210
237
  - spec/rack_middleware_spec.rb
@@ -1,83 +0,0 @@
1
- require 'soar_auditing_provider'
2
- require 'log4r_auditor'
3
- require 'soar_flow'
4
- require 'benchmark'
5
- require 'byebug'
6
-
7
- class Main
8
-
9
- AUDITING_CONFIGURATION = {
10
- 'auditing' => {
11
- 'level' => 'debug',
12
- 'install_exit_handler' => 'false',
13
- 'add_caller_source_location' => 'false',
14
- 'queue_worker' => {
15
- 'queue_size' => 1000000,
16
- 'initial_back_off_in_seconds' => 1,
17
- 'back_off_multiplier' => 2,
18
- 'back_off_attempts' => 5
19
- },
20
- 'default_nfrs' => {
21
- 'accessibility' => 'local',
22
- 'privacy' => 'not encrypted',
23
- 'reliability' => 'instance',
24
- 'performance' => 'high'
25
- },
26
- 'auditors' => {
27
- 'log4r' => {
28
- 'adaptor' => 'Log4rAuditor::Log4rAuditor',
29
- 'file_name' => 'soar_sc.log',
30
- 'standard_stream' => 'none',
31
- 'nfrs' => {
32
- 'accessibility' => 'local',
33
- 'privacy' => 'not encrypted',
34
- 'reliability' => 'instance',
35
- 'performance' => 'high'
36
- }
37
- }
38
- }
39
- }
40
- }
41
-
42
- def test_sanity
43
- iterations = 1000000
44
-
45
- #create and configure auditing instance
46
- myauditing = SoarAuditingProvider::AuditingProvider.new( AUDITING_CONFIGURATION['auditing'] )
47
- myauditing.startup_flow_id = SoarFlow::ID::generate_flow_id
48
- myauditing.service_identifier = 'my-test-service.com'
49
-
50
- #associate a set of auditing entries with a flow by generating a flow identifiers
51
- flow_id = SoarFlow::ID::generate_flow_id
52
-
53
- Benchmark.bm do |x|
54
- myauditing = SoarAuditingProvider::AuditingProvider.new( AUDITING_CONFIGURATION['auditing'].dup.merge("level" => "warn") )
55
- myauditing.startup_flow_id = SoarFlow::ID::generate_flow_id
56
- myauditing.service_identifier = 'my-test-service.com'
57
- x.report ("audit_call_below_audit_threshold:") {
58
- iterations.times {
59
- myauditing.info("Benchmarking test",flow_id)
60
- }
61
- }
62
- myauditing = SoarAuditingProvider::AuditingProvider.new( AUDITING_CONFIGURATION['auditing'].dup.merge("add_caller_source_location" => "false") )
63
- myauditing.startup_flow_id = SoarFlow::ID::generate_flow_id
64
- myauditing.service_identifier = 'my-test-service.com'
65
- x.report ("audit_call_without_caller_info :") {
66
- iterations.times {
67
- myauditing.info("Benchmarking test",flow_id)
68
- }
69
- }
70
- myauditing = SoarAuditingProvider::AuditingProvider.new( AUDITING_CONFIGURATION['auditing'].dup.merge("add_caller_source_location" => "true") )
71
- myauditing.startup_flow_id = SoarFlow::ID::generate_flow_id
72
- myauditing.service_identifier = 'my-test-service.com'
73
- x.report ("audit_call_with_caller_info :") {
74
- iterations.times {
75
- myauditing.info("Benchmarking test",flow_id)
76
- }
77
- }
78
- end
79
- end
80
- end
81
-
82
- main = Main.new
83
- main.test_sanity