soar_authentication_token 5.0.3 → 6.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 491fb012d892cd595bc740285e53eceab63a0e40
4
- data.tar.gz: c75f083d8147b4cd3d85c883b1a1b135457587ff
3
+ metadata.gz: d480cb997dfa47de93d61ea0233f01dae96c4f6e
4
+ data.tar.gz: 217e4bd00d02c269e0865a93e9d852efae326aef
5
5
  SHA512:
6
- metadata.gz: 25bdc621393d29988cb0f84228a611f475871997d80cd61a0b2e35c7c634d07507738acea54213139d5991ff1b6d7fc892d295f20c4f889f92a6c79e61ae5838
7
- data.tar.gz: d3397fd56e4436a945ab7abd3195af33beb82708455eb703011ad89acb6e30a9683be8e923eaabe8de219c6f4e413f8c487c11f90dfe741c2b07466b5ab79a6a
6
+ metadata.gz: 5d0597fd7a320cc8ceda84cc6e7a059ae7ca006790620c08fe2133b49305f81d22dd1afb7e98e068be6ec4b2e435db97623d6ef98bbb39fce9a6eac5d6ad8b0d
7
+ data.tar.gz: c2f6de36be543cfb0f24617b77012115db406196b7be048e052048eb3b58afcef9a1628b771849e3e0c82ef88aedfbf41290d3480aff41f683cfb96be36ffba6
data/README.md CHANGED
@@ -43,9 +43,10 @@ In this mode the StaticTokenValidator is configured with a list of preconfigured
43
43
  Run the rspec test tests using docker compose:
44
44
 
45
45
  ```bash
46
- export UID; docker-compose build --force-rm --no-cache
46
+ export UID
47
+ docker-compose build --force-rm --no-cache
47
48
  docker-compose down
48
- export UID; docker-compose run --rm soar-authentication-token
49
+ docker-compose run --rm soar-authentication-token
49
50
  docker-compose down
50
51
  ```
51
52
 
@@ -54,6 +55,7 @@ docker-compose down
54
55
  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:
55
56
 
56
57
  ```bash
58
+ export UID
57
59
  git pull && git submodule foreach 'git fetch origin --tags; git checkout master; git pull'
58
60
  docker-compose down
59
61
  docker-compose build --force-rm --no-cache
data/docker-compose.yml CHANGED
@@ -14,6 +14,7 @@ services:
14
14
  build: authentication-token-generator-service
15
15
  image: authentication-token-generator-service
16
16
  command: soaring start -e production
17
+ user: $UID:$UID
17
18
  expose:
18
19
  - "9393"
19
20
  volumes:
@@ -27,26 +28,29 @@ services:
27
28
  build: authentication-token-validator-service
28
29
  image: authentication-token-validator-service
29
30
  command: soaring start -e production
31
+ user: $UID:$UID
30
32
  expose:
31
33
  - "9393"
32
34
  volumes:
33
35
  - ./authentication-token-validator-service:/usr/local/src/
34
36
  environment:
35
- - RACK_ENV=development
37
+ - RACK_ENV=production
36
38
  - ENVIRONMENT_FILE=environment_local_ecosystem.yml
37
39
  links:
38
40
  - authentication-token-store
39
41
  authentication-token-store:
40
42
  build: authentication-token-store
41
43
  image: authentication-token-store
42
- command: soaring start -e development
44
+ command: soaring start -e production
45
+ user: $UID:$UID
43
46
  expose:
44
47
  - "9393"
48
+ volumes:
49
+ - ./authentication-token-store:/usr/local/src/
45
50
  environment:
46
- - RACK_ENV=development
51
+ - RACK_ENV=production
47
52
  - ENVIRONMENT_FILE=environment_local_ecosystem.yml
48
53
  links:
49
54
  - authentication-token-redis-store
50
55
  authentication-token-redis-store:
51
56
  image: redis
52
- command: redis-server --requirepass redis_password
@@ -12,7 +12,7 @@ module SoarAuthenticationToken
12
12
  @store_provider = store_provider
13
13
  end
14
14
 
15
- def validate(authentication_token:,flow_identifier: nil)
15
+ def validate(authentication_token:,flow_identifier:, request_information:)
16
16
  decoded_token_payload = decode(authentication_token)
17
17
  return rejection_result(reason: 'Token decode/verification failure') if decoded_token_payload.nil?
18
18
  meta = compile_meta_from_payload(decoded_token_payload)
@@ -12,11 +12,11 @@ module SoarAuthenticationToken
12
12
  #ignore the store provider since this validator does not use a store
13
13
  end
14
14
 
15
- def validate(authentication_token:,flow_identifier: nil)
15
+ def validate(authentication_token:, request_information:, flow_identifier:)
16
16
  attempt = 0
17
17
  begin
18
18
  Timeout::timeout(@configuration['timeout']) do
19
- response = send_request(authentication_token,flow_identifier)
19
+ response = send_request(authentication_token,request_information,flow_identifier)
20
20
  validate_and_extract_information_from_response(response)
21
21
  end
22
22
  rescue Timeout::Error
@@ -33,13 +33,14 @@ module SoarAuthenticationToken
33
33
  @configuration['attempts'] ||= 2
34
34
  end
35
35
 
36
- def send_request(authentication_token,flow_identifier)
36
+ def send_request(authentication_token,request_information,flow_identifier)
37
37
  uri = URI.parse(@configuration['validator-url'])
38
38
  uri.query = URI.encode_www_form( {'flow_identifier' => flow_identifier} )
39
39
  http = Net::HTTP.new(uri.host, uri.port)
40
40
  http.use_ssl = true if uri.is_a?(URI::HTTPS)
41
41
  request = Net::HTTP::Post.new(uri.request_uri)
42
- request.body = { 'authentication_token' => authentication_token }.to_json
42
+ request.body = { 'authentication_token' => authentication_token,
43
+ 'request_information' => request_information }.to_json
43
44
  http.request(request)
44
45
  end
45
46
 
@@ -1,16 +1,19 @@
1
1
  require 'rack'
2
+ require 'json'
2
3
 
3
4
  module SoarAuthenticationToken
4
5
  class RackMiddleware
5
- def initialize(app, configuration, auditing = nil)
6
+ def initialize(app, configuration, service_identifier, auditing = nil)
6
7
  @app = app
7
8
  @configuration = configuration
9
+ @service_identifier = service_identifier
8
10
  @auditing = auditing
9
11
  end
10
12
 
11
13
  def call(env)
12
- session, params, token, flow_id = get_request_information(env)
13
- token_valid, token_meta, message = validate_and_resolve_token(token,flow_id)
14
+ session, params, token, flow_id, request_information, = get_request_information(env)
15
+ token_valid, token_meta, message = validate_and_resolve_token(token, request_information, flow_id)
16
+ $stderr.puts token_valid, token_meta, message
14
17
  if token_valid
15
18
  session['user'] = token_meta['authenticated_identifier']
16
19
  session['auth_token_meta'] = token_meta
@@ -27,12 +30,20 @@ module SoarAuthenticationToken
27
30
  [ request.session,
28
31
  request.params,
29
32
  request.env['HTTP_AUTHORIZATION'],
30
- request.params['flow_identifier'] ]
33
+ request.params['flow_identifier'],
34
+ { 'source_address' => request.env['REMOTE_ADDR'],
35
+ 'user_agent' => request.env['HTTP_USER_AGENT'],
36
+ 'service' => @service_identifier,
37
+ 'resource' => request.env['REQUEST_PATH']
38
+ }
39
+ ]
31
40
  end
32
41
 
33
- def validate_and_resolve_token(authentication_token,flow_identifier)
42
+ def validate_and_resolve_token(authentication_token, request_information, flow_identifier)
34
43
  token_validator = SoarAuthenticationToken::TokenValidator.new(@configuration)
35
- token_validator.validate(authentication_token: authentication_token,flow_identifier: flow_identifier)
44
+ token_validator.validate(authentication_token: authentication_token,
45
+ request_information: request_information,
46
+ flow_identifier: flow_identifier)
36
47
  end
37
48
 
38
49
  def audit_token_rejection(message, flow_id)
@@ -40,7 +51,15 @@ module SoarAuthenticationToken
40
51
  end
41
52
 
42
53
  def rejection
43
- [401, { 'Content-Type' => 'application/json'}, ["401 - Not authenticated"]]
54
+ [ 401,
55
+ { 'Content-Type' => 'application/json'},
56
+ {
57
+ 'status' => 'fail',
58
+ 'data' => {
59
+ 'notifications' => ['Not authenticated']
60
+ }
61
+ }
62
+ ]
44
63
  end
45
64
  end
46
65
  end
@@ -10,8 +10,9 @@ module SoarAuthenticationToken
10
10
  @provider.inject_store_provider(store_provider)
11
11
  end
12
12
 
13
- def validate(authentication_token:,flow_identifier: nil)
13
+ def validate(authentication_token:, request_information: {}, flow_identifier: nil)
14
14
  @provider.validate(authentication_token: authentication_token,
15
+ request_information: request_information,
15
16
  flow_identifier: flow_identifier)
16
17
  end
17
18
 
@@ -1,3 +1,3 @@
1
1
  module SoarAuthenticationToken
2
- VERSION = '5.0.3'
2
+ VERSION = '6.0.0'
3
3
  end
@@ -4,7 +4,7 @@ require 'yaml'
4
4
  describe SoarAuthenticationToken::JwtTokenValidator do
5
5
  subject { SoarAuthenticationToken::JwtTokenValidator }
6
6
  before :all do
7
- @test_store = AuthTokenStoreProvider::StubClient.new
7
+ @test_store = AuthTokenStoreProvider::LocalStubClient.new
8
8
  keypair_generator = SoarAuthenticationToken::KeypairGenerator.new
9
9
  @valid_private_key, @valid_public_key = keypair_generator.generate
10
10
  @invalid_private_key, @invalid_public_key = keypair_generator.generate
@@ -63,6 +63,10 @@ describe SoarAuthenticationToken::JwtTokenValidator do
63
63
  @remote_generator = SoarAuthenticationToken::TokenGenerator.new(@remote_generator_configuration)
64
64
  end
65
65
 
66
+ before :each do
67
+ @test_store.clear_store
68
+ end
69
+
66
70
  it 'has a version number' do
67
71
  expect(SoarAuthenticationToken::VERSION).not_to be nil
68
72
  end
@@ -122,8 +126,9 @@ describe SoarAuthenticationToken::JwtTokenValidator do
122
126
  context 'given unknown token (not in store)' do
123
127
  let!(:token_validation_result) {
124
128
  token, token_generator_meta = @local_valid_generator.generate(authenticated_identifier: @test_identifier)
125
- @test_store.instance_variable_set("@store", []) #clear store
126
- iut.validate(authentication_token: token)
129
+ @test_store.clear_store
130
+ token_validation_result = iut.validate(authentication_token: token)
131
+ token_validation_result
127
132
  }
128
133
  let!(:token_validity) { token_validation_result[0] }
129
134
  let!(:token_meta) { token_validation_result[1] }
@@ -202,7 +207,7 @@ describe SoarAuthenticationToken::JwtTokenValidator do
202
207
  expect(iut).to receive(:attempt_decode_using_a_key).once.ordered.with(token, @multiple_key_configuration['keys']['KEYPAIR_20160108T190001']).and_return(nil)
203
208
  expect(iut).to receive(:attempt_decode_using_a_key).once.ordered.with(token, @multiple_key_configuration['keys']['KEYPAIR_20160107T230001']).and_return(nil)
204
209
 
205
- iut.validate(authentication_token: token)
210
+ iut.validate(authentication_token: token, flow_identifier: nil, request_information: nil)
206
211
  end
207
212
 
208
213
  it 'attempts to use all the public keys' do
@@ -211,7 +216,7 @@ describe SoarAuthenticationToken::JwtTokenValidator do
211
216
 
212
217
  expect(iut).to receive(:attempt_decode_using_a_key).exactly(3).times
213
218
 
214
- iut.validate(authentication_token: token)
219
+ iut.validate(authentication_token: token, flow_identifier: nil, request_information: nil)
215
220
  end
216
221
  end
217
222
 
@@ -229,7 +234,7 @@ describe SoarAuthenticationToken::JwtTokenValidator do
229
234
  it 'responds indicating the token is valid' do
230
235
  iut = SoarAuthenticationToken::JwtTokenValidator.new(@multiple_key_configuration)
231
236
  iut.inject_store_provider(@test_store)
232
- token_validity, token_meta, message = iut.validate(authentication_token: token)
237
+ token_validity, token_meta, message = iut.validate(authentication_token: token, flow_identifier: nil, request_information: nil)
233
238
 
234
239
  expect(token_validity).to eq true
235
240
  end
@@ -245,7 +250,7 @@ describe SoarAuthenticationToken::JwtTokenValidator do
245
250
  iut.inject_store_provider(@test_store)
246
251
 
247
252
  expect(iut).to receive(:attempt_decode_using_a_key).once.with(token, @multiple_key_configuration['keys']['KEYPAIR_20160108T200001']).and_return([token_meta])
248
- iut.validate(authentication_token: token)
253
+ iut.validate(authentication_token: token, flow_identifier: nil, request_information: nil)
249
254
  end
250
255
  end
251
256
 
@@ -283,7 +288,7 @@ describe SoarAuthenticationToken::JwtTokenValidator do
283
288
  expect(iut).to receive(:attempt_decode_using_a_key).once.with(token, @multiple_key_configuration['keys']['KEYPAIR_20160108T200001']).and_return(nil)
284
289
  expect(iut).to receive(:attempt_decode_using_a_key).once.with(token, @multiple_key_configuration['keys']['KEYPAIR_20160108T190001']).and_return([token_meta])
285
290
  expect(iut).not_to receive(:attempt_decode_using_a_key).with(token, @multiple_key_configuration['keys']['KEYPAIR_20160107T230001'])
286
- iut.validate(authentication_token: token)
291
+ iut.validate(authentication_token: token, flow_identifier: nil, request_information: nil)
287
292
  end
288
293
  end
289
294
  end
@@ -32,19 +32,23 @@ describe SoarAuthenticationToken::RackMiddleware do
32
32
  end
33
33
 
34
34
  def get_store
35
- AuthTokenStoreProvider::Client.new({ 'service_url' => 'http://authentication-token-store:9393/'})
35
+ AuthTokenStoreProvider::Client.new({ 'service_url' => 'http://authentication-token-store:9393/',
36
+ 'auth_token' => 'test_ecosystem_token_for_auth_token_generator_service'})
36
37
  end
37
38
 
38
39
  before :all do
39
40
  @local_valid_generator, @valid_private_key, @valid_public_key = create_valid_token_generator
40
41
  @local_invalid_generator, @imvalid_private_key, @invalid_public_key = create_invalid_token_generator
42
+ @failure_response_json = { 'status' => 'fail', 'data' => {
43
+ 'notifications' => ['Not authenticated']
44
+ }
45
+ }
41
46
  end
42
47
 
43
48
  before :each do
44
49
  @test_app = lambda do |env|
45
50
  request = Rack::Request.new env
46
51
  session = request.session
47
- $stderr.puts "In the controller"
48
52
  test_app_response_data = {
49
53
  'message' => "tested with authenticated user #{session['user']}",
50
54
  'user' => session['user'],
@@ -56,7 +60,7 @@ describe SoarAuthenticationToken::RackMiddleware do
56
60
  'provider' => 'SoarAuthenticationToken::RemoteTokenValidator',
57
61
  'validator-url' => 'http://authentication-token-validator-service:9393/validate'
58
62
  }
59
- @iut = SoarAuthenticationToken::RackMiddleware.new(@test_app, @iut_configuration)
63
+ @iut = SoarAuthenticationToken::RackMiddleware.new(@test_app, @iut_configuration, "test-service", nil)
60
64
  end
61
65
 
62
66
  it 'has a version number' do
@@ -78,7 +82,7 @@ describe SoarAuthenticationToken::RackMiddleware do
78
82
  it "return with 401" do
79
83
  opts = { }
80
84
  code, env, body = @iut.call Rack::MockRequest.env_for('http://service', opts)
81
- expect([code, env, body]).to eq([401, {"Content-Type" => "application/json"}, ["401 - Not authenticated"]])
85
+ expect([code, env, body]).to eq([401, {"Content-Type" => "application/json"}, @failure_response_json])
82
86
  end
83
87
  end
84
88
 
@@ -86,7 +90,7 @@ describe SoarAuthenticationToken::RackMiddleware do
86
90
  it "return with 401" do
87
91
  opts = { 'HTTP_AUTHORIZATION' => @local_invalid_generator.generate(authenticated_identifier: 'a@b.com') }
88
92
  code, env, body = @iut.call Rack::MockRequest.env_for('http://service', opts)
89
- expect([code, env, body]).to eq([401, {"Content-Type" => "application/json"}, ["401 - Not authenticated"]])
93
+ expect([code, env, body]).to eq([401, {"Content-Type" => "application/json"}, @failure_response_json])
90
94
  end
91
95
  end
92
96
 
@@ -38,7 +38,7 @@ describe SoarAuthenticationToken::RemoteTokenValidator do
38
38
  context 'given valid token' do
39
39
  let!(:token_validation_result) {
40
40
  token, token_generator_meta = @remote_generator.generate(authenticated_identifier: @test_identifier)
41
- iut.validate(authentication_token: token)
41
+ iut.validate(authentication_token: token, request_information: nil, flow_identifier: nil)
42
42
  }
43
43
  let!(:token_validity) { token_validation_result[0] }
44
44
  let!(:token_meta) { token_validation_result[1] }
@@ -56,7 +56,7 @@ describe SoarAuthenticationToken::RemoteTokenValidator do
56
56
  context 'given invalid (generalized) token' do
57
57
  let!(:token_validation_result) {
58
58
  token, token_generator_meta = @local_invalid_generator.generate(authenticated_identifier: @test_identifier)
59
- iut.validate(authentication_token: token)
59
+ iut.validate(authentication_token: token, request_information: nil, flow_identifier: nil)
60
60
  }
61
61
  let!(:token_validity) { token_validation_result[0] }
62
62
  let!(:token_meta) { token_validation_result[1] }
@@ -88,13 +88,13 @@ describe SoarAuthenticationToken::RemoteTokenValidator do
88
88
  }
89
89
  it 'raise error after attempt that timeout has occured' do
90
90
  expect{
91
- iut.validate(authentication_token: valid_token)
91
+ iut.validate(authentication_token: valid_token, request_information: nil, flow_identifier: nil)
92
92
  }.to raise_error Timeout::Error
93
93
  end
94
94
  it 'by default attempts 2 times with 3 second timeout' do
95
95
  start_time = Time.now
96
96
  expect{
97
- iut.validate(authentication_token: valid_token)
97
+ iut.validate(authentication_token: valid_token, request_information: nil, flow_identifier: nil)
98
98
  }.to raise_error Timeout::Error
99
99
  expect(Time.now - start_time).to be_within(1).of 6
100
100
  end
data/spec/spec_helper.rb CHANGED
@@ -16,3 +16,70 @@ require 'auth_token_store_provider'
16
16
  def one_year_in_seconds
17
17
  31536000
18
18
  end
19
+
20
+
21
+ module AuthTokenStoreProvider
22
+ class LocalStubClient
23
+ def store
24
+ @@store ||= []
25
+ end
26
+
27
+ def clear_store
28
+ @@store = []
29
+ end
30
+
31
+ def initialize(configuration = {})
32
+ if configuration['stub-data'] != {} || configuration['stub-data'] != nil
33
+ @@store = configuration['stub-data']
34
+ end
35
+ end
36
+
37
+ def store_failure(state = true)
38
+ @@store_failure = state
39
+ end
40
+
41
+ def store_failure?
42
+ @@store_failure ||= false
43
+ @@store_failure
44
+ end
45
+
46
+ def add(token_identifier:, authenticated_identifier:, token_issue_time:, token_expiry_time:, flow_identifier: nil)
47
+ raise RuntimeError, 'Failure accessing store' if store_failure?
48
+ store << { token_identifier: token_identifier,
49
+ authenticated_identifier: authenticated_identifier,
50
+ token_issue_time: token_issue_time,
51
+ token_expiry_time: token_expiry_time }
52
+ end
53
+
54
+ def remove(token_identifier:, flow_identifier: nil)
55
+ raise RuntimeError, 'Failure accessing store' if store_failure?
56
+ store.delete_if { |x| x[:token_identifier] == token_identifier }
57
+ true
58
+ end
59
+
60
+ def token_exist?(token_identifier:, authenticated_identifier:, token_issue_time:, token_expiry_time:, flow_identifier: nil)
61
+ raise RuntimeError, 'Failure accessing store' if store_failure?
62
+
63
+ store.each { |x|
64
+ if ((x[:token_identifier] == token_identifier) and
65
+ (x[:authenticated_identifier] == authenticated_identifier) and
66
+ (x[:token_issue_time] == token_issue_time) and
67
+ (x[:token_expiry_time] == token_expiry_time))
68
+ return true
69
+ end
70
+ }
71
+ false
72
+ end
73
+
74
+ def remove_tokens_for(authenticated_identifier:, flow_identifier: nil)
75
+ raise RuntimeError, 'Failure accessing store' if store_failure?
76
+ store.delete_if { |x| x[:authenticated_identifier] == authenticated_identifier }
77
+ true
78
+ end
79
+
80
+ def list_tokens_for(authenticated_identifier:, flow_identifier: nil)
81
+ raise RuntimeError, 'Failure accessing store' if store_failure?
82
+ store.select { |x| x[:authenticated_identifier] == authenticated_identifier}
83
+ end
84
+ end
85
+ 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: 5.0.3
4
+ version: 6.0.0
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-02-27 00:00:00.000000000 Z
11
+ date: 2017-04-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: soar_xt
@@ -221,7 +221,6 @@ files:
221
221
  - bin/keypair-generator
222
222
  - bin/rotate-configs
223
223
  - bin/setup
224
- - docker-compose-isolated.yml
225
224
  - docker-compose.yml
226
225
  - lib/soar_authentication_token.rb
227
226
  - lib/soar_authentication_token/config_rotator.rb
@@ -1,49 +0,0 @@
1
- version: '2.0'
2
- services:
3
- soar-authentication-token:
4
- command: /bin/bash -c 'sleep 5; bundle exec rspec -cfd spec'
5
- build: .
6
- image: soar-authentication-token
7
- volumes:
8
- - .:/usr/local/src/
9
- links:
10
- - authentication-token-generator-service
11
- - authentication-token-validator-service
12
- authentication-token-generator-service:
13
- build: authentication-token-generator-service
14
- image: authentication-token-generator-service
15
- expose:
16
- - "9393"
17
- volumes:
18
- - ./authentication-token-generator-service:/usr/local/src/
19
- environment:
20
- - RACK_ENV=development
21
- - ENVIRONMENT_FILE=environment_local_ecosystem.yml
22
- links:
23
- - authentication-token-store
24
- authentication-token-validator-service:
25
- build: authentication-token-validator-service
26
- image: authentication-token-validator-service
27
- expose:
28
- - "9393"
29
- volumes:
30
- - ./authentication-token-validator-service:/usr/local/src/
31
- environment:
32
- - RACK_ENV=development
33
- - ENVIRONMENT_FILE=environment_local_ecosystem.yml
34
- links:
35
- - authentication-token-store
36
- authentication-token-store:
37
- build: authentication-token-store
38
- image: authentication-token-store
39
- command: soaring start
40
- expose:
41
- - "9393"
42
- environment:
43
- - RACK_ENV=development
44
- - ENVIRONMENT_FILE=environment_local_ecosystem.yml
45
- links:
46
- - authentication-token-redis-store
47
- authentication-token-redis-store:
48
- image: redis
49
- command: redis-server --requirepass redis_password