soar_authentication_token 6.1.1 → 7.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/docker-compose.yml +1 -48
- data/lib/soar_authentication_token.rb +4 -0
- data/lib/soar_authentication_token/providers/authorization_header_provider.rb +18 -0
- data/lib/soar_authentication_token/providers/cascade_provider.rb +34 -0
- data/lib/soar_authentication_token/providers/cookie_provider.rb +24 -0
- data/lib/soar_authentication_token/rack_middleware.rb +5 -1
- data/lib/soar_authentication_token/token_provider.rb +25 -0
- data/lib/soar_authentication_token/version.rb +1 -1
- data/soar_authentication_token.gemspec +3 -0
- data/spec/jwt_token_validator_spec.rb +1 -1
- data/spec/{rack_middleware_spec.rb → rack_middleware/authorization_header_spec.rb} +42 -7
- data/spec/remote_token_validator_spec.rb +56 -30
- data/spec/token_generator_spec.rb +16 -11
- metadata +56 -5
- data/.gitmodules +0 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 92c8dc7a3dbedcf217cd7573c32d50c5d38d2c0c
|
4
|
+
data.tar.gz: de77e06ab5a8a930c88aa713a8e32ccfcc63373c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 57a51e1c0ea4fda47b35f1fa3988d3717efd106dfdbab932010d0255abb1f31c3d8b82947997abb85d51fb42c8ae4773d0220b8de479d7170aab3637458751c1
|
7
|
+
data.tar.gz: f97c53ba7e18ca910c5468a4f7ed5c83059e5cb50b08ed8f31daa48ade8387bf38713ff204966345a2c88f03792418ded04a1026dac0f961bc3b1bcc5856a12d
|
data/docker-compose.yml
CHANGED
@@ -1,56 +1,9 @@
|
|
1
1
|
version: '2.0'
|
2
2
|
services:
|
3
3
|
soar-authentication-token:
|
4
|
-
command: /bin/bash -c '
|
4
|
+
command: /bin/bash -c 'bundle exec rspec -cfd ./spec/'
|
5
5
|
user: $UID:$UID
|
6
6
|
build: .
|
7
7
|
image: soar-authentication-token
|
8
8
|
volumes:
|
9
9
|
- .:/usr/local/src/
|
10
|
-
links:
|
11
|
-
- authentication-token-generator-service
|
12
|
-
- authentication-token-validator-service
|
13
|
-
authentication-token-generator-service:
|
14
|
-
build: authentication-token-generator-service
|
15
|
-
image: authentication-token-generator-service
|
16
|
-
command: soaring start -e production
|
17
|
-
user: $UID:$UID
|
18
|
-
expose:
|
19
|
-
- "9393"
|
20
|
-
volumes:
|
21
|
-
- ./authentication-token-generator-service:/usr/local/src/
|
22
|
-
environment:
|
23
|
-
- RACK_ENV=production
|
24
|
-
- ENVIRONMENT_FILE=environment_local_ecosystem.yml
|
25
|
-
links:
|
26
|
-
- authentication-token-store
|
27
|
-
authentication-token-validator-service:
|
28
|
-
build: authentication-token-validator-service
|
29
|
-
image: authentication-token-validator-service
|
30
|
-
command: soaring start -e production
|
31
|
-
user: $UID:$UID
|
32
|
-
expose:
|
33
|
-
- "9393"
|
34
|
-
volumes:
|
35
|
-
- ./authentication-token-validator-service:/usr/local/src/
|
36
|
-
environment:
|
37
|
-
- RACK_ENV=production
|
38
|
-
- ENVIRONMENT_FILE=environment_local_ecosystem.yml
|
39
|
-
links:
|
40
|
-
- authentication-token-store
|
41
|
-
authentication-token-store:
|
42
|
-
build: authentication-token-store
|
43
|
-
image: authentication-token-store
|
44
|
-
command: soaring start -e production
|
45
|
-
user: $UID:$UID
|
46
|
-
expose:
|
47
|
-
- "9393"
|
48
|
-
volumes:
|
49
|
-
- ./authentication-token-store:/usr/local/src/
|
50
|
-
environment:
|
51
|
-
- RACK_ENV=production
|
52
|
-
- ENVIRONMENT_FILE=environment_local_ecosystem.yml
|
53
|
-
links:
|
54
|
-
- authentication-token-redis-store
|
55
|
-
authentication-token-redis-store:
|
56
|
-
image: redis
|
@@ -6,6 +6,10 @@ require 'soar_authentication_token/providers/jwt_token_validator'
|
|
6
6
|
require 'soar_authentication_token/providers/remote_token_generator'
|
7
7
|
require 'soar_authentication_token/providers/remote_token_validator'
|
8
8
|
require 'soar_authentication_token/providers/static_token_validator'
|
9
|
+
require 'soar_authentication_token/token_provider'
|
10
|
+
require 'soar_authentication_token/providers/cookie_provider'
|
11
|
+
require 'soar_authentication_token/providers/authorization_header_provider'
|
12
|
+
require 'soar_authentication_token/providers/cascade_provider'
|
9
13
|
require 'soar_authentication_token/keypair_generator'
|
10
14
|
require 'soar_authentication_token/config_rotator'
|
11
15
|
require 'soar_authentication_token/token_generator'
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module SoarAuthenticationToken
|
2
|
+
class AuthorizationHeaderProvider
|
3
|
+
def initialize(configuration)
|
4
|
+
@configuration = configuration
|
5
|
+
validate_configuration
|
6
|
+
end
|
7
|
+
|
8
|
+
def fetch(request)
|
9
|
+
return false unless request.env[@configuration['header_name']]
|
10
|
+
|
11
|
+
request.env[@configuration['header_name']]
|
12
|
+
end
|
13
|
+
|
14
|
+
def validate_configuration
|
15
|
+
raise "'cookie_name' must be configured" unless @configuration['header_name']
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module SoarAuthenticationToken
|
2
|
+
class CascadeProvider
|
3
|
+
def initialize(configuration)
|
4
|
+
@configuration = configuration
|
5
|
+
validate_configuration
|
6
|
+
end
|
7
|
+
|
8
|
+
def fetch(request)
|
9
|
+
# TODO: refactor this functionality into modules - DON'T DUPLICATE!
|
10
|
+
fetch_by_cookie(request) || fetch_by_auth_header(request)
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
def fetch_by_cookie(request)
|
15
|
+
return false unless request.env.has_key?('HTTP_COOKIE')
|
16
|
+
|
17
|
+
cookies = HTTP::CookieJar.new.parse(request.env['HTTP_COOKIE'], 'http://irrelevant')
|
18
|
+
auth_cookie = cookies.find { |cookie| cookie.name == @configuration['cookie_name'] }
|
19
|
+
return false unless auth_cookie.is_a?(HTTP::Cookie)
|
20
|
+
|
21
|
+
auth_cookie.value
|
22
|
+
end
|
23
|
+
|
24
|
+
def fetch_by_auth_header(request)
|
25
|
+
return false unless request.env[@configuration['header_name']]
|
26
|
+
|
27
|
+
request.env[@configuration['header_name']]
|
28
|
+
end
|
29
|
+
|
30
|
+
def validate_configuration
|
31
|
+
raise "'cookie_name' must be configured" unless @configuration['header_name']
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'http-cookie'
|
2
|
+
|
3
|
+
module SoarAuthenticationToken
|
4
|
+
class CookieProvider
|
5
|
+
def initialize(configuration)
|
6
|
+
@configuration = configuration
|
7
|
+
validate_configuration
|
8
|
+
end
|
9
|
+
|
10
|
+
def fetch(request)
|
11
|
+
return false unless request.env.has_key?('HTTP_COOKIE')
|
12
|
+
|
13
|
+
cookies = HTTP::CookieJar.new.parse(request.env['HTTP_COOKIE'], 'http://irrelevant')
|
14
|
+
auth_cookie = cookies.find { |cookie| cookie.name == @configuration['cookie_name'] }
|
15
|
+
return false unless auth_cookie.is_a?(HTTP::Cookie)
|
16
|
+
|
17
|
+
auth_cookie.value
|
18
|
+
end
|
19
|
+
|
20
|
+
def validate_configuration
|
21
|
+
raise "'cookie_name' must be configured" unless @configuration['cookie_name']
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -26,9 +26,11 @@ module SoarAuthenticationToken
|
|
26
26
|
|
27
27
|
def get_request_information(env)
|
28
28
|
request = Rack::Request.new env
|
29
|
+
auth_token = SoarAuthenticationToken::TokenProvider.new(@configuration).fetch(request)
|
30
|
+
|
29
31
|
[ request.session,
|
30
32
|
request.params,
|
31
|
-
|
33
|
+
auth_token,
|
32
34
|
request.params['flow_identifier'],
|
33
35
|
{ 'source_address' => request.ip,
|
34
36
|
'user_agent' => request.user_agent,
|
@@ -42,6 +44,8 @@ module SoarAuthenticationToken
|
|
42
44
|
end
|
43
45
|
|
44
46
|
def validate_and_resolve_token(authentication_token, request_information, flow_identifier)
|
47
|
+
return false, nil, 'No token provided or retrievable from request' unless authentication_token
|
48
|
+
|
45
49
|
token_validator = SoarAuthenticationToken::TokenValidator.new(@configuration)
|
46
50
|
token_validator.validate(authentication_token: authentication_token,
|
47
51
|
request_information: request_information,
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module SoarAuthenticationToken
|
2
|
+
class TokenProvider
|
3
|
+
def initialize(configuration)
|
4
|
+
@configuration = configuration
|
5
|
+
validate_configuration
|
6
|
+
instantiate_provider
|
7
|
+
end
|
8
|
+
|
9
|
+
def fetch(request)
|
10
|
+
@provider.fetch(request)
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def instantiate_provider
|
16
|
+
@provider = Object::const_get(@configuration['authentication_token']['provider'])
|
17
|
+
.new(@configuration['authentication_token'])
|
18
|
+
end
|
19
|
+
|
20
|
+
def validate_configuration
|
21
|
+
raise 'authentication_token provider must be configured' if @configuration['authentication_token'].nil? or
|
22
|
+
@configuration['authentication_token']['provider'].nil?
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -23,6 +23,7 @@ Gem::Specification.new do |spec|
|
|
23
23
|
spec.add_dependency 'jwt', '~> 1.5', '>= 1.5.6'
|
24
24
|
spec.add_dependency "rack", '>= 1.6.4', '< 3.0.0'
|
25
25
|
spec.add_dependency 'authenticated_client', '~> 0.0.2'
|
26
|
+
spec.add_dependency 'http-cookie', '~> 1.0', '>= 1.0.3'
|
26
27
|
|
27
28
|
spec.add_development_dependency 'auth_token_store_provider', "~> 1.0"
|
28
29
|
spec.add_development_dependency 'pry', '~> 0'
|
@@ -32,4 +33,6 @@ Gem::Specification.new do |spec|
|
|
32
33
|
spec.add_development_dependency "capybara", '~> 2.1', '>= 2.1.0'
|
33
34
|
spec.add_development_dependency "simplecov", '~> 0'
|
34
35
|
spec.add_development_dependency "simplecov-rcov", '~> 0'
|
36
|
+
spec.add_development_dependency 'webmock', '~> 3.0'
|
37
|
+
spec.add_development_dependency 'byebug'
|
35
38
|
end
|
@@ -149,7 +149,7 @@ describe SoarAuthenticationToken::JwtTokenValidator do
|
|
149
149
|
|
150
150
|
context 'given invalid token (garbage or different key)' do
|
151
151
|
let!(:token_validation_result) {
|
152
|
-
token, token_generator_meta = @
|
152
|
+
token, token_generator_meta = @local_invalid_generator.generate(authenticated_identifier: @test_identifier)
|
153
153
|
iut.validate(authentication_token: token)
|
154
154
|
}
|
155
155
|
let!(:token_validity) { token_validation_result[0] }
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'rack'
|
3
3
|
require 'rack/test'
|
4
|
+
require 'webmock/rspec'
|
4
5
|
|
5
6
|
describe SoarAuthenticationToken::RackMiddleware do
|
6
7
|
include Rack::Test::Methods
|
@@ -38,7 +39,7 @@ describe SoarAuthenticationToken::RackMiddleware do
|
|
38
39
|
|
39
40
|
before :all do
|
40
41
|
@local_valid_generator, @valid_private_key, @valid_public_key = create_valid_token_generator
|
41
|
-
@local_invalid_generator, @
|
42
|
+
@local_invalid_generator, @invalid_private_key, @invalid_public_key = create_invalid_token_generator
|
42
43
|
@failure_response_json = [ { 'status' => 'fail', 'data' => {
|
43
44
|
'notifications' => ['Not authenticated']
|
44
45
|
}
|
@@ -58,7 +59,11 @@ describe SoarAuthenticationToken::RackMiddleware do
|
|
58
59
|
end
|
59
60
|
@iut_configuration = {
|
60
61
|
'provider' => 'SoarAuthenticationToken::RemoteTokenValidator',
|
61
|
-
'validator-url' => 'http://authentication-token-validator-service:9393/validate'
|
62
|
+
'validator-url' => 'http://authentication-token-validator-service:9393/validate',
|
63
|
+
'authentication_token' => {
|
64
|
+
'provider' => 'SoarAuthenticationToken::AuthorizationHeaderProvider',
|
65
|
+
'header_name' => 'HTTP_AUTHORIZATION'
|
66
|
+
}
|
62
67
|
}
|
63
68
|
@iut = SoarAuthenticationToken::RackMiddleware.new(@test_app, @iut_configuration, "test-service", nil)
|
64
69
|
end
|
@@ -80,7 +85,13 @@ describe SoarAuthenticationToken::RackMiddleware do
|
|
80
85
|
context "when called with a request environment" do
|
81
86
|
context 'with no authentication token' do
|
82
87
|
it "return with 401" do
|
83
|
-
|
88
|
+
stub_response_body = {'status' => 'success', 'data' => { 'token_validity' => false, 'token_meta' => nil, 'notifications' => ['none'] }}.to_json
|
89
|
+
stub_request(:post, "http://authentication-token-validator-service:9393/validate?flow_identifier").
|
90
|
+
with(body: "{\"authentication_token\":null,\"request_information\":{\"source_address\":\"1.1.1.1\",\"user_agent\":null,\"service\":\"test-service\",\"resource\":\"/\",\"method\":\"GET\",\"base_url\":\"http://service\",\"version\":\"7.0.0\"}}",
|
91
|
+
headers: {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Ruby'}).
|
92
|
+
to_return(status: 200, body: stub_response_body, headers: {})
|
93
|
+
|
94
|
+
opts = { 'REMOTE_ADDR' => '1.1.1.1', 'HTTP_AUTHORIZATION' => nil }
|
84
95
|
code, env, body = @iut.call Rack::MockRequest.env_for('http://service', opts)
|
85
96
|
expect([code, env, body]).to eq([401, {"Content-Type" => "application/json"}, @failure_response_json])
|
86
97
|
end
|
@@ -88,7 +99,13 @@ describe SoarAuthenticationToken::RackMiddleware do
|
|
88
99
|
|
89
100
|
context 'with an invalid authentication token' do
|
90
101
|
it "return with 401" do
|
91
|
-
|
102
|
+
stub_response_body = {'status' => 'success', 'data' => { 'token_validity' => false, 'token_meta' => nil, 'notifications' => ['none'] }}.to_json
|
103
|
+
stub_request(:post, "http://authentication-token-validator-service:9393/validate?flow_identifier").
|
104
|
+
with(body: "{\"authentication_token\":\"bad_token\",\"request_information\":{\"source_address\":\"1.1.1.1\",\"user_agent\":null,\"service\":\"test-service\",\"resource\":\"/\",\"method\":\"GET\",\"base_url\":\"http://service\",\"version\":\"7.0.0\"}}",
|
105
|
+
headers: {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Ruby'}).
|
106
|
+
to_return(status: 200, body: stub_response_body, headers: {})
|
107
|
+
|
108
|
+
opts = { 'REMOTE_ADDR' => '1.1.1.1', 'HTTP_AUTHORIZATION' => 'bad_token' }
|
92
109
|
code, env, body = @iut.call Rack::MockRequest.env_for('http://service', opts)
|
93
110
|
expect([code, env, body]).to eq([401, {"Content-Type" => "application/json"}, @failure_response_json])
|
94
111
|
end
|
@@ -96,19 +113,37 @@ describe SoarAuthenticationToken::RackMiddleware do
|
|
96
113
|
|
97
114
|
context 'with a valid authentiation token' do
|
98
115
|
it "pass requests to the application" do
|
99
|
-
|
116
|
+
stub_response_body = {'status' => 'success', 'data' => { 'token_validity' => true, 'token_meta' => { 'authenticated_identifier' => 'a@b.com' }, 'notifications' => ['none'] }}.to_json
|
117
|
+
stub_request(:post, "http://authentication-token-validator-service:9393/validate?flow_identifier").
|
118
|
+
with(body: "{\"authentication_token\":\"valid_token\",\"request_information\":{\"source_address\":\"1.1.1.1\",\"user_agent\":null,\"service\":\"test-service\",\"resource\":\"/\",\"method\":\"GET\",\"base_url\":\"http://service\",\"version\":\"7.0.0\"}}",
|
119
|
+
headers: {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Ruby'}).
|
120
|
+
to_return(status: 200, body: stub_response_body, headers: {})
|
121
|
+
|
122
|
+
opts = { 'REMOTE_ADDR' => '1.1.1.1', 'HTTP_AUTHORIZATION' => 'valid_token' }
|
100
123
|
code, env, body = @iut.call Rack::MockRequest.env_for('http://service', opts)
|
101
124
|
expect([code, env, body['message']]).to eq([200, {"Content-Type"=>"application/json"}, "tested with authenticated user a@b.com" ])
|
102
125
|
end
|
103
126
|
|
104
127
|
it "populate the 'user' key in the rack session with the authenticated user" do
|
105
|
-
|
128
|
+
stub_response_body = {'status' => 'success', 'data' => { 'token_validity' => true, 'token_meta' => { 'authenticated_identifier' => 'a@b.com' }, 'notifications' => ['none'] }}.to_json
|
129
|
+
stub_request(:post, "http://authentication-token-validator-service:9393/validate?flow_identifier").
|
130
|
+
with(body: "{\"authentication_token\":\"valid_token\",\"request_information\":{\"source_address\":\"1.1.1.1\",\"user_agent\":null,\"service\":\"test-service\",\"resource\":\"/\",\"method\":\"GET\",\"base_url\":\"http://service\",\"version\":\"7.0.0\"}}",
|
131
|
+
headers: {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Ruby'}).
|
132
|
+
to_return(status: 200, body: stub_response_body, headers: {})
|
133
|
+
|
134
|
+
opts = { 'REMOTE_ADDR' => '1.1.1.1', 'HTTP_AUTHORIZATION' => 'valid_token' }
|
106
135
|
code, env, body = @iut.call Rack::MockRequest.env_for('http://service', opts)
|
107
136
|
expect(body['user']).to eq('a@b.com')
|
108
137
|
end
|
109
138
|
|
110
139
|
it "populate the 'auth_token_meta' key in the rack session with the hash containing the token meta" do
|
111
|
-
|
140
|
+
stub_response_body = {'status' => 'success', 'data' => { 'token_validity' => true, 'token_meta' => { 'authenticated_identifier' => 'a@b.com' }, 'notifications' => ['none'] }}.to_json
|
141
|
+
stub_request(:post, "http://authentication-token-validator-service:9393/validate?flow_identifier").
|
142
|
+
with(body: "{\"authentication_token\":\"valid_token\",\"request_information\":{\"source_address\":\"1.1.1.1\",\"user_agent\":null,\"service\":\"test-service\",\"resource\":\"/\",\"method\":\"GET\",\"base_url\":\"http://service\",\"version\":\"7.0.0\"}}",
|
143
|
+
headers: {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Ruby'}).
|
144
|
+
to_return(status: 200, body: stub_response_body, headers: {})
|
145
|
+
|
146
|
+
opts = { 'REMOTE_ADDR' => '1.1.1.1', 'HTTP_AUTHORIZATION' => 'valid_token' }
|
112
147
|
code, env, body = @iut.call Rack::MockRequest.env_for('http://service', opts)
|
113
148
|
expect(body['auth_token_meta']['authenticated_identifier']).to eq('a@b.com')
|
114
149
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'yaml'
|
3
|
+
require 'webmock/rspec'
|
3
4
|
|
4
5
|
describe SoarAuthenticationToken::RemoteTokenValidator do
|
5
6
|
subject { SoarAuthenticationToken::RemoteTokenValidator }
|
@@ -36,67 +37,92 @@ describe SoarAuthenticationToken::RemoteTokenValidator do
|
|
36
37
|
describe "#validate" do
|
37
38
|
let!(:iut) { subject.new(@remote_validator_configuration) }
|
38
39
|
context 'given valid token' do
|
39
|
-
let!(:token_validation_result) {
|
40
|
-
token, token_generator_meta = @remote_generator.generate(authenticated_identifier: @test_identifier)
|
41
|
-
iut.validate(authentication_token: token, request_information: request_information_from_valid_source, flow_identifier: nil)
|
42
|
-
}
|
43
|
-
let!(:token_validity) { token_validation_result[0] }
|
44
|
-
let!(:token_meta) { token_validation_result[1] }
|
45
|
-
let!(:message) { token_validation_result[2] }
|
46
|
-
|
47
40
|
it 'should indicate valid if the token is valid' do
|
41
|
+
stub_response_body = {'status' => 'success', 'data' => { 'token_validity' => true, 'token_meta' => { 'authenticated_identifier' => @test_identifier }, 'notifications' => ['none'] }}.to_json
|
42
|
+
stub_request(:post, "http://authentication-token-validator-service:9393/validate?flow_identifier").
|
43
|
+
with(body: "{\"authentication_token\":\"valid_token\",\"request_information\":{\"source_address\":\"1.1.1.1\",\"user_agent\":\"some shiny browser\",\"service\":\"test-service\",\"resource\":\"/\"}}",
|
44
|
+
headers: {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Ruby'}).
|
45
|
+
to_return(status: 200, body: stub_response_body, headers: {})
|
46
|
+
|
47
|
+
token = 'valid_token'
|
48
|
+
token_validity, token_meta, message = iut.validate(authentication_token: token, request_information: request_information_from_valid_source, flow_identifier: nil)
|
49
|
+
|
48
50
|
expect(token_validity).to eq true
|
49
51
|
end
|
50
52
|
|
51
53
|
it 'should provide the authenticated_identifier if the token is valid' do
|
54
|
+
stub_response_body = {'status' => 'success', 'data' => { 'token_validity' => true, 'token_meta' => { 'authenticated_identifier' => @test_identifier }, 'notifications' => ['none'] }}.to_json
|
55
|
+
stub_request(:post, "http://authentication-token-validator-service:9393/validate?flow_identifier").
|
56
|
+
with(body: "{\"authentication_token\":\"valid_token\",\"request_information\":{\"source_address\":\"1.1.1.1\",\"user_agent\":\"some shiny browser\",\"service\":\"test-service\",\"resource\":\"/\"}}",
|
57
|
+
headers: {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Ruby'}).
|
58
|
+
to_return(status: 200, body: stub_response_body, headers: {})
|
59
|
+
|
60
|
+
token = 'valid_token'
|
61
|
+
token_validity, token_meta, message = iut.validate(authentication_token: token, request_information: request_information_from_valid_source, flow_identifier: nil)
|
62
|
+
|
52
63
|
expect(token_meta['authenticated_identifier']).to eq @test_identifier
|
53
64
|
end
|
54
65
|
end
|
55
66
|
|
56
67
|
context 'given invalid (generalized) token' do
|
57
|
-
let!(:token_validation_result) {
|
58
|
-
token, token_generator_meta = @local_invalid_generator.generate(authenticated_identifier: @test_identifier)
|
59
|
-
iut.validate(authentication_token: token, request_information: request_information_from_valid_source, flow_identifier: nil)
|
60
|
-
}
|
61
|
-
let!(:token_validity) { token_validation_result[0] }
|
62
|
-
let!(:token_meta) { token_validation_result[1] }
|
63
|
-
let!(:message) { token_validation_result[2] }
|
64
|
-
|
65
68
|
it 'indicate token is invalid' do
|
69
|
+
stub_response_body = {'status' => 'success', 'data' => { 'token_validity' => false, 'token_meta' => nil, 'notifications' => ['Token decode/verification failure'] }}.to_json
|
70
|
+
stub_request(:post, "http://authentication-token-validator-service:9393/validate?flow_identifier").
|
71
|
+
with(body: "{\"authentication_token\":\"invalid_token\",\"request_information\":{\"source_address\":\"1.1.1.1\",\"user_agent\":\"some shiny browser\",\"service\":\"test-service\",\"resource\":\"/\"}}",
|
72
|
+
headers: {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Ruby'}).
|
73
|
+
to_return(status: 200, body: stub_response_body, headers: {})
|
74
|
+
|
75
|
+
token = 'invalid_token'
|
76
|
+
token_validity, token_meta, message = iut.validate(authentication_token: token, request_information: request_information_from_valid_source, flow_identifier: nil)
|
77
|
+
|
66
78
|
expect(token_validity).to eq false
|
67
79
|
end
|
68
80
|
|
69
81
|
it 'does not provide the token meta' do
|
82
|
+
stub_response_body = {'status' => 'success', 'data' => { 'token_validity' => false, 'token_meta' => nil, 'notifications' => ['Token decode/verification failure'] }}.to_json
|
83
|
+
stub_request(:post, "http://authentication-token-validator-service:9393/validate?flow_identifier").
|
84
|
+
with(body: "{\"authentication_token\":\"invalid_token\",\"request_information\":{\"source_address\":\"1.1.1.1\",\"user_agent\":\"some shiny browser\",\"service\":\"test-service\",\"resource\":\"/\"}}",
|
85
|
+
headers: {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Ruby'}).
|
86
|
+
to_return(status: 200, body: stub_response_body, headers: {})
|
87
|
+
|
88
|
+
token = 'invalid_token'
|
89
|
+
token_validity, token_meta, message = iut.validate(authentication_token: token, request_information: request_information_from_valid_source, flow_identifier: nil)
|
90
|
+
|
70
91
|
expect(token_meta).to eq nil
|
71
92
|
end
|
72
93
|
|
73
94
|
it 'provides a message indicating the token is invalid' do
|
95
|
+
stub_response_body = {'status' => 'success', 'data' => { 'token_validity' => false, 'token_meta' => nil, 'notifications' => ['Token decode/verification failure'] }}.to_json
|
96
|
+
stub_request(:post, "http://authentication-token-validator-service:9393/validate?flow_identifier").
|
97
|
+
with(body: "{\"authentication_token\":\"invalid_token\",\"request_information\":{\"source_address\":\"1.1.1.1\",\"user_agent\":\"some shiny browser\",\"service\":\"test-service\",\"resource\":\"/\"}}",
|
98
|
+
headers: {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Ruby'}).
|
99
|
+
to_return(status: 200, body: stub_response_body, headers: {})
|
100
|
+
|
101
|
+
token = 'invalid_token'
|
102
|
+
token_validity, token_meta, message = iut.validate(authentication_token: token, request_information: request_information_from_valid_source, flow_identifier: nil)
|
103
|
+
|
74
104
|
expect(message).to match /Token decode\/verification failure/
|
75
105
|
end
|
76
106
|
end
|
77
107
|
|
78
108
|
context 'given invalid token validator url that will result in timeouts' do
|
79
|
-
let!(:invalid_validator_configuration) {{
|
80
|
-
'provider' => 'SoarAuthenticationToken::RemoteTokenValidator',
|
81
|
-
'validator-url' => 'http://auth-token-validator.auto-h.net/validate',
|
82
|
-
'generator-client-auth-token' => 'test_ecosystem_token_for_auth_token_aaapi_authenticator_service'
|
83
|
-
}}
|
84
|
-
let!(:iut) { subject.new(invalid_validator_configuration) }
|
85
|
-
let!(:valid_token) {
|
86
|
-
token, token_generator_meta = @remote_generator.generate(authenticated_identifier: @test_identifier)
|
87
|
-
token
|
88
|
-
}
|
89
109
|
it 'raise error after attempt that timeout has occured' do
|
110
|
+
stub_response_body = {'status' => 'success', 'data' => { 'token_validity' => false, 'token_meta' => nil, 'notifications' => ['Token decode/verification failure'] }}.to_json
|
111
|
+
stub_request(:post, "http://authentication-token-validator-service:9393/validate?flow_identifier").
|
112
|
+
to_timeout.times(2)
|
113
|
+
|
90
114
|
expect{
|
91
|
-
iut.validate(authentication_token:
|
115
|
+
iut.validate(authentication_token: 'some_token', request_information: {}, flow_identifier: nil)
|
92
116
|
}.to raise_error Timeout::Error
|
93
117
|
end
|
94
118
|
it 'by default attempts 2 times with 3 second timeout' do
|
95
|
-
|
119
|
+
stub_response_body = {'status' => 'success', 'data' => { 'token_validity' => false, 'token_meta' => nil, 'notifications' => ['Token decode/verification failure'] }}.to_json
|
120
|
+
stub_request(:post, "http://authentication-token-validator-service:9393/validate?flow_identifier").
|
121
|
+
to_timeout.times(2)
|
122
|
+
|
96
123
|
expect{
|
97
|
-
iut.validate(authentication_token:
|
124
|
+
iut.validate(authentication_token: 'some_token', request_information: {}, flow_identifier: nil)
|
98
125
|
}.to raise_error Timeout::Error
|
99
|
-
expect(Time.now - start_time).to be_within(1).of 6
|
100
126
|
end
|
101
127
|
end
|
102
128
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
+
require 'webmock/rspec'
|
2
3
|
|
3
4
|
describe SoarAuthenticationToken::TokenGenerator do
|
4
5
|
before :all do
|
@@ -59,18 +60,16 @@ describe SoarAuthenticationToken::TokenGenerator do
|
|
59
60
|
|
60
61
|
context "when generating a new token remotely" do
|
61
62
|
it 'should request the token from the configured remote service' do
|
63
|
+
stub_response_body = {'status' => 'success', 'data' => { 'token' => 'abc' }}.to_json
|
64
|
+
stub_request(:post, "http://authentication-token-generator-service:9393/generate?flow_identifier=test-flow-id").
|
65
|
+
with(body: "{\"authenticated_identifier\":\"a@b.co.za\"}",
|
66
|
+
headers: {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization'=>'test_ecosystem_token_for_auth_token_aaapi_authenticator_service', 'User-Agent'=>'Ruby'}).
|
67
|
+
to_return(status: 200, body: stub_response_body, headers: {})
|
68
|
+
|
62
69
|
@iut = SoarAuthenticationToken::TokenGenerator.new(@configuration_remote_generator)
|
63
70
|
@iut.inject_store_provider(@test_store)
|
64
|
-
|
65
71
|
token, token_generator_meta = @iut.generate(authenticated_identifier: @test_authenticated_identifier, flow_identifier: 'test-flow-id')
|
66
|
-
|
67
|
-
@validator = SoarAuthenticationToken::TokenValidator.new(@configuration_remote_validator)
|
68
|
-
@iut.inject_store_provider(@test_store)
|
69
|
-
token_validity, token_validator_meta, messages = @validator.validate(authentication_token: token, request_information: request_information_from_valid_source, flow_identifier: 'test-flow-id')
|
70
|
-
|
71
|
-
expect(token_validity).to eq(true)
|
72
|
-
expect(token_validator_meta['authenticated_identifier']).to eq(@test_authenticated_identifier)
|
73
|
-
expect(messages).to match(/Valid token/)
|
72
|
+
expect(token).to eq('abc')
|
74
73
|
end
|
75
74
|
end
|
76
75
|
|
@@ -82,16 +81,22 @@ describe SoarAuthenticationToken::TokenGenerator do
|
|
82
81
|
}}
|
83
82
|
let!(:iut) { SoarAuthenticationToken::TokenGenerator.new(invalid_generator_configuration) }
|
84
83
|
it 'raise error after attempt that timeout has occured' do
|
84
|
+
stub_request(:post, "http://auth-token-generator.auto-h.net/generate?flow_identifier=test-flow-id").
|
85
|
+
with(body: "{\"authenticated_identifier\":\"a@b.co.za\"}",
|
86
|
+
headers: {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization'=>'test_ecosystem_token_for_auth_token_aaapi_authenticator_service', 'User-Agent'=>'Ruby'}).
|
87
|
+
to_timeout.times(2)
|
85
88
|
expect{
|
86
89
|
iut.generate(authenticated_identifier: @test_authenticated_identifier, flow_identifier: 'test-flow-id')
|
87
90
|
}.to raise_error Timeout::Error
|
88
91
|
end
|
89
92
|
it 'by default attempts 2 times with 3 second timeout' do
|
90
|
-
|
93
|
+
stub_request(:post, "http://auth-token-generator.auto-h.net/generate?flow_identifier=test-flow-id").
|
94
|
+
with(body: "{\"authenticated_identifier\":\"a@b.co.za\"}",
|
95
|
+
headers: {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization'=>'test_ecosystem_token_for_auth_token_aaapi_authenticator_service', 'User-Agent'=>'Ruby'}).
|
96
|
+
to_timeout.times(2)
|
91
97
|
expect{
|
92
98
|
iut.generate(authenticated_identifier: @test_authenticated_identifier, flow_identifier: 'test-flow-id')
|
93
99
|
}.to raise_error Timeout::Error
|
94
|
-
expect(Time.now - start_time).to be_within(1).of 6
|
95
100
|
end
|
96
101
|
end
|
97
102
|
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:
|
4
|
+
version: 7.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-
|
11
|
+
date: 2017-07-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: soar_xt
|
@@ -78,6 +78,26 @@ dependencies:
|
|
78
78
|
- - "~>"
|
79
79
|
- !ruby/object:Gem::Version
|
80
80
|
version: 0.0.2
|
81
|
+
- !ruby/object:Gem::Dependency
|
82
|
+
name: http-cookie
|
83
|
+
requirement: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - "~>"
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '1.0'
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: 1.0.3
|
91
|
+
type: :runtime
|
92
|
+
prerelease: false
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - "~>"
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '1.0'
|
98
|
+
- - ">="
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: 1.0.3
|
81
101
|
- !ruby/object:Gem::Dependency
|
82
102
|
name: auth_token_store_provider
|
83
103
|
requirement: !ruby/object:Gem::Requirement
|
@@ -196,6 +216,34 @@ dependencies:
|
|
196
216
|
- - "~>"
|
197
217
|
- !ruby/object:Gem::Version
|
198
218
|
version: '0'
|
219
|
+
- !ruby/object:Gem::Dependency
|
220
|
+
name: webmock
|
221
|
+
requirement: !ruby/object:Gem::Requirement
|
222
|
+
requirements:
|
223
|
+
- - "~>"
|
224
|
+
- !ruby/object:Gem::Version
|
225
|
+
version: '3.0'
|
226
|
+
type: :development
|
227
|
+
prerelease: false
|
228
|
+
version_requirements: !ruby/object:Gem::Requirement
|
229
|
+
requirements:
|
230
|
+
- - "~>"
|
231
|
+
- !ruby/object:Gem::Version
|
232
|
+
version: '3.0'
|
233
|
+
- !ruby/object:Gem::Dependency
|
234
|
+
name: byebug
|
235
|
+
requirement: !ruby/object:Gem::Requirement
|
236
|
+
requirements:
|
237
|
+
- - ">="
|
238
|
+
- !ruby/object:Gem::Version
|
239
|
+
version: '0'
|
240
|
+
type: :development
|
241
|
+
prerelease: false
|
242
|
+
version_requirements: !ruby/object:Gem::Requirement
|
243
|
+
requirements:
|
244
|
+
- - ">="
|
245
|
+
- !ruby/object:Gem::Version
|
246
|
+
version: '0'
|
199
247
|
description: Interface to the authentication token service
|
200
248
|
email:
|
201
249
|
- barney.de.villiers@hetzner.co.za
|
@@ -208,7 +256,6 @@ extensions: []
|
|
208
256
|
extra_rdoc_files: []
|
209
257
|
files:
|
210
258
|
- ".gitignore"
|
211
|
-
- ".gitmodules"
|
212
259
|
- ".rspec"
|
213
260
|
- ".ruby-gemset"
|
214
261
|
- ".ruby-version"
|
@@ -225,6 +272,9 @@ files:
|
|
225
272
|
- lib/soar_authentication_token.rb
|
226
273
|
- lib/soar_authentication_token/config_rotator.rb
|
227
274
|
- lib/soar_authentication_token/keypair_generator.rb
|
275
|
+
- lib/soar_authentication_token/providers/authorization_header_provider.rb
|
276
|
+
- lib/soar_authentication_token/providers/cascade_provider.rb
|
277
|
+
- lib/soar_authentication_token/providers/cookie_provider.rb
|
228
278
|
- lib/soar_authentication_token/providers/jwt_token_generator.rb
|
229
279
|
- lib/soar_authentication_token/providers/jwt_token_validator.rb
|
230
280
|
- lib/soar_authentication_token/providers/remote_token_generator.rb
|
@@ -232,6 +282,7 @@ files:
|
|
232
282
|
- lib/soar_authentication_token/providers/static_token_validator.rb
|
233
283
|
- lib/soar_authentication_token/rack_middleware.rb
|
234
284
|
- lib/soar_authentication_token/token_generator.rb
|
285
|
+
- lib/soar_authentication_token/token_provider.rb
|
235
286
|
- lib/soar_authentication_token/token_validator.rb
|
236
287
|
- lib/soar_authentication_token/version.rb
|
237
288
|
- retry.sh
|
@@ -244,7 +295,7 @@ files:
|
|
244
295
|
- spec/config_rotator_spec.rb
|
245
296
|
- spec/jwt_token_validator_spec.rb
|
246
297
|
- spec/keypair_generator_spec.rb
|
247
|
-
- spec/
|
298
|
+
- spec/rack_middleware/authorization_header_spec.rb
|
248
299
|
- spec/remote_token_validator_spec.rb
|
249
300
|
- spec/spec_helper.rb
|
250
301
|
- spec/static_token_validator_spec.rb
|
@@ -278,7 +329,7 @@ test_files:
|
|
278
329
|
- spec/config_rotator_spec.rb
|
279
330
|
- spec/jwt_token_validator_spec.rb
|
280
331
|
- spec/keypair_generator_spec.rb
|
281
|
-
- spec/
|
332
|
+
- spec/rack_middleware/authorization_header_spec.rb
|
282
333
|
- spec/remote_token_validator_spec.rb
|
283
334
|
- spec/spec_helper.rb
|
284
335
|
- spec/static_token_validator_spec.rb
|
data/.gitmodules
DELETED
@@ -1,12 +0,0 @@
|
|
1
|
-
[submodule "authentication-token-generator-service"]
|
2
|
-
path = authentication-token-generator-service
|
3
|
-
url = git@gitlab.host-h.net:hetznerZA/authentication-token-generator-service.git
|
4
|
-
branch = master
|
5
|
-
[submodule "authentication-token-validator-service"]
|
6
|
-
path = authentication-token-validator-service
|
7
|
-
url = git@gitlab.host-h.net:hetznerZA/authentication-token-validator-service.git
|
8
|
-
branch = master
|
9
|
-
[submodule "authentication-token-store"]
|
10
|
-
path = authentication-token-store
|
11
|
-
url = git@gitlab.host-h.net:hetznerZA/authentication-token-store.git
|
12
|
-
branch = master
|