holistic_auth 0.9.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3 @@
1
+ module HolisticAuth
2
+ VERSION = '0.9.8'.freeze
3
+ end
@@ -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
@@ -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