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.
@@ -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