holistic_auth 0.9.8
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 +7 -0
- data/.gitignore +15 -0
- data/.rspec +2 -0
- data/.rubocop.yml +62 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +22 -0
- data/Gemfile +21 -0
- data/LICENSE.txt +22 -0
- data/README.md +42 -0
- data/Rakefile +18 -0
- data/holistic_auth.gemspec +30 -0
- data/lib/holistic_auth.rb +17 -0
- data/lib/holistic_auth/client_token_issuer.rb +106 -0
- data/lib/holistic_auth/configuration.rb +67 -0
- data/lib/holistic_auth/end_point_listener.rb +35 -0
- data/lib/holistic_auth/errors.rb +4 -0
- data/lib/holistic_auth/orm_handlers/active_record.rb +56 -0
- data/lib/holistic_auth/providers/generic_provider.rb +100 -0
- data/lib/holistic_auth/providers/google.rb +82 -0
- data/lib/holistic_auth/providers/ms_graph.rb +93 -0
- data/lib/holistic_auth/providers/outlook.rb +38 -0
- data/lib/holistic_auth/providers/stub.rb +60 -0
- data/lib/holistic_auth/version.rb +3 -0
- data/spec/holistic_auth/client_token_issuer_spec.rb +46 -0
- data/spec/holistic_auth/end_point_listener_spec.rb +96 -0
- data/spec/holistic_auth/provider_spec.rb +122 -0
- data/spec/spec_helper.rb +31 -0
- metadata +187 -0
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe HolisticAuth::ClientTokenIssuer do
|
4
|
+
before :all do
|
5
|
+
HolisticAuth.configure do |config|
|
6
|
+
# config.add_secrets :google,
|
7
|
+
# client_id: Rails.application.secrets.google_oauth2['client_id'],
|
8
|
+
# client_secret: Rails.application.secrets.google_oauth2['client_secret']
|
9
|
+
#
|
10
|
+
# config.add_secrets :ms_graph,
|
11
|
+
# tenant_id: Rails.application.secrets.ms_graph_oauth2['tenant_id'],
|
12
|
+
# client_id: Rails.application.secrets.ms_graph_oauth2['client_id'],
|
13
|
+
# client_secret: Rails.application.secrets.ms_graph_oauth2['client_secret']
|
14
|
+
config.valid_applications = %i(ios_v1 ember_v1)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should exchange client-provided credentials for auth codes'
|
19
|
+
it 'should gracefully handle and return error condition if client-provided credentials are invalid'
|
20
|
+
it 'should verify that the tokens belong to the provided email before returning them'
|
21
|
+
it 'should generate our own set of tokens for the client if the provided ones exchanged successfully'
|
22
|
+
|
23
|
+
it 'should all integrate to follow a standard flow to auth the api client'
|
24
|
+
|
25
|
+
it 'should gracefully not allow unsupported providers' do
|
26
|
+
expect do
|
27
|
+
HolisticAuth::ClientTokenIssuer.new(provider: :some_fake_provider)
|
28
|
+
end.to raise_error(ArgumentError)
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should allow supported providers' do
|
32
|
+
expect do
|
33
|
+
HolisticAuth::ClientTokenIssuer.new(provider: :google)
|
34
|
+
end.not_to raise_error
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should correctly handle client information provided as a parameter' do
|
38
|
+
pending
|
39
|
+
ace = HolisticAuth::ClientTokenIssuer.new(provider: :google, client_id: 'new_id', client_secret: 'new_secret')
|
40
|
+
|
41
|
+
stub_request(:post, ace.site_token_url).
|
42
|
+
with(body: @test_env.merge(client_id: 'new_id', client_secret: 'new_secret'),
|
43
|
+
headers: @req_headers).
|
44
|
+
to_return(@req_response)
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe HolisticAuth::EndPointListener do
|
4
|
+
before :each do
|
5
|
+
@stub_provider = HolisticAuth::Providers::Stub.new(
|
6
|
+
client_id: 'cl_id',
|
7
|
+
client_secret: 'cl_sec',
|
8
|
+
site: 'https://example.org',
|
9
|
+
token_url: '/extoken',
|
10
|
+
api_key: 'api_key',
|
11
|
+
user_info_url: 'http://example.org/info',
|
12
|
+
)
|
13
|
+
@creds_hash = {
|
14
|
+
auth_code: '4/auth_code',
|
15
|
+
provider: @stub_provider,
|
16
|
+
}
|
17
|
+
end
|
18
|
+
it 'should accept valid-looking credentials from the client' do
|
19
|
+
listener = HolisticAuth::EndPointListener.new(@creds_hash)
|
20
|
+
expect(listener.valid?).to be_truthy
|
21
|
+
end
|
22
|
+
|
23
|
+
# These tests extend on the test above.
|
24
|
+
# Given the test above handles the happy path, everything below are sad path tests
|
25
|
+
|
26
|
+
it 'should return an error to the client if the credentials were invalid' do
|
27
|
+
bad_creds_hash = {
|
28
|
+
a: 'b',
|
29
|
+
c: 'd',
|
30
|
+
}
|
31
|
+
listener = HolisticAuth::EndPointListener.new(bad_creds_hash)
|
32
|
+
expect(listener.valid?).to be_falsey
|
33
|
+
end
|
34
|
+
it 'should return an error unless all three fields are provided' do
|
35
|
+
listener2 = HolisticAuth::EndPointListener.new(@creds_hash.dup.tap { |hs| hs.delete(:auth_code) }) # remove ac
|
36
|
+
listener3 = HolisticAuth::EndPointListener.new(@creds_hash.dup.tap { |hs| hs.delete(:provider) }) # remove prov
|
37
|
+
|
38
|
+
expect(listener2.valid?).to be_falsey
|
39
|
+
expect(listener3.valid?).to be_falsey
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'should reject invalid providers' do
|
43
|
+
bad_provider_1 = Hash.new(
|
44
|
+
client_id: 'cl_id',
|
45
|
+
client_secret: 'cl_sec',
|
46
|
+
site: 'https://example.org',
|
47
|
+
token_url: '/extoken',
|
48
|
+
api_key: 'api_key',
|
49
|
+
user_info_url: 'http://example.org/info',
|
50
|
+
)
|
51
|
+
|
52
|
+
bad_provider_hash1 = @creds_hash.merge(provider: bad_provider_1)
|
53
|
+
|
54
|
+
listener1 = HolisticAuth::EndPointListener.new(bad_provider_hash1)
|
55
|
+
|
56
|
+
expect(listener1.valid?).to be_falsey
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'should accept valid providers' do
|
60
|
+
provider_1 = HolisticAuth::Providers::Stub.new(
|
61
|
+
client_id: 'cl_id',
|
62
|
+
client_secret: 'cl_sec',
|
63
|
+
site: 'https://example.org',
|
64
|
+
token_url: '/extoken',
|
65
|
+
api_key: 'api_key',
|
66
|
+
user_info_url: 'http://example.org/info',
|
67
|
+
)
|
68
|
+
provider_2 = HolisticAuth::Providers::Google.new(
|
69
|
+
client_id: 'cl_id',
|
70
|
+
client_secret: 'cl_sec',
|
71
|
+
site: 'https://example.org',
|
72
|
+
token_url: '/extoken',
|
73
|
+
api_key: 'api_key',
|
74
|
+
user_info_url: 'http://example.org/info',
|
75
|
+
)
|
76
|
+
|
77
|
+
provider_hash1 = @creds_hash.merge(provider: provider_1)
|
78
|
+
provider_hash2 = @creds_hash.merge(provider: provider_2)
|
79
|
+
|
80
|
+
listener1 = HolisticAuth::EndPointListener.new(provider_hash1)
|
81
|
+
listener2 = HolisticAuth::EndPointListener.new(provider_hash2)
|
82
|
+
|
83
|
+
expect(listener1.valid?).to be_truthy
|
84
|
+
expect(listener2.valid?).to be_truthy
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'should return a human-readable list of errors if there are any' do
|
88
|
+
listener = HolisticAuth::EndPointListener.new({})
|
89
|
+
listener.valid?
|
90
|
+
expect(listener.errors).to eq [
|
91
|
+
'A required param is missing',
|
92
|
+
'"provider" field missing',
|
93
|
+
'"auth_code" field missing',
|
94
|
+
]
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
describe 'Providers' do
|
5
|
+
before :all do
|
6
|
+
@secrets = {
|
7
|
+
client_id: (0...50).map { ('a'..'z').to_a[rand(26)] }.join,
|
8
|
+
client_secret: (0...50).map { ('a'..'z').to_a[rand(26)] }.join,
|
9
|
+
tenant_id: (0...50).map { ('a'..'z').to_a[rand(26)] }.join,
|
10
|
+
}
|
11
|
+
|
12
|
+
HolisticAuth.configure do |config|
|
13
|
+
config.add_secrets :google,
|
14
|
+
client_id: @secrets[:client_id],
|
15
|
+
client_secret: @secrets[:client_secret]
|
16
|
+
end
|
17
|
+
@token_hash = {
|
18
|
+
access_token: 'ya29.token',
|
19
|
+
refresh_token: '1/refresh',
|
20
|
+
expires_in: 3600,
|
21
|
+
token_type: 'Bearer',
|
22
|
+
}
|
23
|
+
@test_env = {
|
24
|
+
client_id: @secrets[:client_id],
|
25
|
+
client_secret: @secrets[:client_secret],
|
26
|
+
code: '4/code',
|
27
|
+
grant_type: 'authorization_code',
|
28
|
+
redirect_uri: 'http://localhost:4200',
|
29
|
+
}
|
30
|
+
|
31
|
+
@req_headers = {
|
32
|
+
accept: '*/*',
|
33
|
+
content_type: 'application/x-www-form-urlencoded',
|
34
|
+
}
|
35
|
+
|
36
|
+
@req_response = {
|
37
|
+
status: 200,
|
38
|
+
body: @token_hash.to_json,
|
39
|
+
headers: { content_type: 'application/json' },
|
40
|
+
}
|
41
|
+
|
42
|
+
@stub_provider = HolisticAuth::Providers::Stub.new(
|
43
|
+
client_id: @secrets[:client_id],
|
44
|
+
client_secret: @secrets[:client_secret],
|
45
|
+
site: 'https://example.org',
|
46
|
+
token_url: '/extoken',
|
47
|
+
api_key: 'api_key',
|
48
|
+
user_info_url: 'http://example.org/info',
|
49
|
+
)
|
50
|
+
@google_provider = HolisticAuth::Providers::Google.new(
|
51
|
+
client_id: @secrets[:client_id],
|
52
|
+
client_secret: @secrets[:client_secret],
|
53
|
+
site: 'https://example.org',
|
54
|
+
token_url: '/extoken',
|
55
|
+
api_key: 'api_key',
|
56
|
+
user_info_url: 'http://example.org/info',
|
57
|
+
)
|
58
|
+
end
|
59
|
+
|
60
|
+
describe 'exchange' do
|
61
|
+
it 'should correctly process a generic (stub) token' do
|
62
|
+
stub_request(:post, @stub_provider.site_token_url).
|
63
|
+
with(body: @test_env,
|
64
|
+
headers: @req_headers).
|
65
|
+
to_return(@req_response)
|
66
|
+
|
67
|
+
result = @stub_provider.exchange(@test_env[:code], @test_env[:redirect_uri])
|
68
|
+
|
69
|
+
expect(result.token).to eq @token_hash[:access_token]
|
70
|
+
expect(result.refresh_token).to eq @token_hash[:refresh_token]
|
71
|
+
expect(result.expires_in).to eq @token_hash[:expires_in]
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'should correctly process a google token' do
|
75
|
+
stub_request(:post, @google_provider.site_token_url).
|
76
|
+
with(body: @test_env,
|
77
|
+
headers: @req_headers).
|
78
|
+
to_return(@req_response)
|
79
|
+
|
80
|
+
result = @google_provider.exchange(@test_env[:code], @test_env[:redirect_uri])
|
81
|
+
|
82
|
+
expect(result.token).to eq @token_hash[:access_token]
|
83
|
+
expect(result.refresh_token).to eq @token_hash[:refresh_token]
|
84
|
+
expect(result.expires_in).to eq @token_hash[:expires_in]
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'should return an AccessToken for each provider' do
|
88
|
+
klass = OAuth2::AccessToken
|
89
|
+
|
90
|
+
HolisticAuth.configuration.providers.each do |provider_name|
|
91
|
+
provider = HolisticAuth.configuration.provider(provider_name)
|
92
|
+
expect(provider).to be_kind_of HolisticAuth::Providers::GenericProvider
|
93
|
+
|
94
|
+
provider.add_secrets(@secrets.dup)
|
95
|
+
expect(provider.client_id).to eq @secrets[:client_id]
|
96
|
+
expect(provider.client_secret).to eq @secrets[:client_secret]
|
97
|
+
|
98
|
+
stub_request(:post, provider.site_token_url).
|
99
|
+
with(body: @test_env,
|
100
|
+
headers: @req_headers).
|
101
|
+
to_return(@req_response)
|
102
|
+
|
103
|
+
expect(provider.exchange(@test_env[:code], @test_env[:redirect_uri])).to be_kind_of klass
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
describe 'retreive_user_info' do
|
109
|
+
it 'should error for the generic provider' do
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'should return a hash with all the expected fields' do
|
113
|
+
{
|
114
|
+
email_verified: true,
|
115
|
+
email: 'a@b.c',
|
116
|
+
given_name: 'first',
|
117
|
+
family_name: 'last',
|
118
|
+
profile: 'xyz',
|
119
|
+
}.with_indifferent_access
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
Bundler.setup
|
3
|
+
|
4
|
+
if RUBY_VERSION >= '1.9'
|
5
|
+
require 'simplecov'
|
6
|
+
require 'coveralls'
|
7
|
+
|
8
|
+
SimpleCov.formatters = [
|
9
|
+
SimpleCov::Formatter::HTMLFormatter,
|
10
|
+
Coveralls::SimpleCov::Formatter,
|
11
|
+
]
|
12
|
+
|
13
|
+
SimpleCov.start do
|
14
|
+
minimum_coverage(76)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
require 'rspec'
|
19
|
+
require 'rack/test'
|
20
|
+
require 'webmock/rspec'
|
21
|
+
require 'holistic_auth' # and any other gems you need
|
22
|
+
|
23
|
+
RSpec.configure do |config|
|
24
|
+
config.expect_with :rspec do |c|
|
25
|
+
c.syntax = :expect
|
26
|
+
end
|
27
|
+
config.include Rack::Test::Methods
|
28
|
+
config.include WebMock::API
|
29
|
+
|
30
|
+
# some (optional) config here
|
31
|
+
end
|
metadata
ADDED
@@ -0,0 +1,187 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: holistic_auth
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.9.8
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Alexander Bradner
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-03-09 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: oauth2
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: doorkeeper
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2.0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: activesupport
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '4.2'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '4.2'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: activerecord
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '4.2'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '4.2'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: bundler
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '1.7'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1.7'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rake
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '10.0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '10.0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rspec
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '3'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '3'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rubocop
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
description:
|
126
|
+
email:
|
127
|
+
- alex@bradner.net
|
128
|
+
executables: []
|
129
|
+
extensions: []
|
130
|
+
extra_rdoc_files: []
|
131
|
+
files:
|
132
|
+
- ".gitignore"
|
133
|
+
- ".rspec"
|
134
|
+
- ".rubocop.yml"
|
135
|
+
- ".ruby-gemset"
|
136
|
+
- ".ruby-version"
|
137
|
+
- ".travis.yml"
|
138
|
+
- Gemfile
|
139
|
+
- LICENSE.txt
|
140
|
+
- README.md
|
141
|
+
- Rakefile
|
142
|
+
- holistic_auth.gemspec
|
143
|
+
- lib/holistic_auth.rb
|
144
|
+
- lib/holistic_auth/client_token_issuer.rb
|
145
|
+
- lib/holistic_auth/configuration.rb
|
146
|
+
- lib/holistic_auth/end_point_listener.rb
|
147
|
+
- lib/holistic_auth/errors.rb
|
148
|
+
- lib/holistic_auth/orm_handlers/active_record.rb
|
149
|
+
- lib/holistic_auth/providers/generic_provider.rb
|
150
|
+
- lib/holistic_auth/providers/google.rb
|
151
|
+
- lib/holistic_auth/providers/ms_graph.rb
|
152
|
+
- lib/holistic_auth/providers/outlook.rb
|
153
|
+
- lib/holistic_auth/providers/stub.rb
|
154
|
+
- lib/holistic_auth/version.rb
|
155
|
+
- spec/holistic_auth/client_token_issuer_spec.rb
|
156
|
+
- spec/holistic_auth/end_point_listener_spec.rb
|
157
|
+
- spec/holistic_auth/provider_spec.rb
|
158
|
+
- spec/spec_helper.rb
|
159
|
+
homepage: https://github.com/abradner/holistic_auth
|
160
|
+
licenses:
|
161
|
+
- MIT
|
162
|
+
metadata: {}
|
163
|
+
post_install_message:
|
164
|
+
rdoc_options: []
|
165
|
+
require_paths:
|
166
|
+
- lib
|
167
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
168
|
+
requirements:
|
169
|
+
- - ">="
|
170
|
+
- !ruby/object:Gem::Version
|
171
|
+
version: '0'
|
172
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
173
|
+
requirements:
|
174
|
+
- - ">="
|
175
|
+
- !ruby/object:Gem::Version
|
176
|
+
version: '0'
|
177
|
+
requirements: []
|
178
|
+
rubyforge_project:
|
179
|
+
rubygems_version: 2.4.8
|
180
|
+
signing_key:
|
181
|
+
specification_version: 4
|
182
|
+
summary: Single-Sign-On for the front and rails backend of a Single-Page-App
|
183
|
+
test_files:
|
184
|
+
- spec/holistic_auth/client_token_issuer_spec.rb
|
185
|
+
- spec/holistic_auth/end_point_listener_spec.rb
|
186
|
+
- spec/holistic_auth/provider_spec.rb
|
187
|
+
- spec/spec_helper.rb
|