soar_authentication_token 6.1.1 → 7.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|