osso 0.0.5.pre.theta → 0.0.7

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.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/.buildkite/pipeline.yml +6 -4
  3. data/.github/dependabot.yml +8 -0
  4. data/.github/workflows/automerge.yml +19 -0
  5. data/.rubocop.yml +4 -1
  6. data/Gemfile +2 -2
  7. data/Gemfile.lock +58 -37
  8. data/LICENSE +21 -23
  9. data/Rakefile +2 -0
  10. data/bin/annotate +3 -1
  11. data/db/schema.rb +41 -3
  12. data/lib/osso.rb +0 -1
  13. data/lib/osso/db/migrate/20200929154117_add_users_count_to_identity_providers_and_enterprise_accounts.rb +6 -0
  14. data/lib/osso/db/migrate/20201023142158_add_rodauth_tables.rb +47 -0
  15. data/lib/osso/db/migrate/20201105122026_add_token_index_to_access_tokens.rb +5 -0
  16. data/lib/osso/db/migrate/20201106154936_add_requested_to_authorization_codes_and_access_tokens.rb +6 -0
  17. data/lib/osso/db/migrate/20201109160851_add_sso_issuer_to_identity_providers.rb +12 -0
  18. data/lib/osso/db/migrate/20201110190754_remove_oauth_client_id_from_enterprise_accounts.rb +9 -0
  19. data/lib/osso/db/migrate/20201112160120_add_ping_to_identity_provider_service_enum.rb +28 -0
  20. data/lib/osso/db/migrate/20201125143501_add_salesforce_to_provider_service_enum.rb +28 -0
  21. data/lib/osso/error/account_configuration_error.rb +1 -0
  22. data/lib/osso/error/oauth_error.rb +6 -3
  23. data/lib/osso/graphql/mutation.rb +2 -0
  24. data/lib/osso/graphql/mutations.rb +2 -0
  25. data/lib/osso/graphql/mutations/create_enterprise_account.rb +0 -7
  26. data/lib/osso/graphql/mutations/create_identity_provider.rb +7 -6
  27. data/lib/osso/graphql/mutations/delete_identity_provider.rb +24 -0
  28. data/lib/osso/graphql/mutations/invite_admin_user.rb +43 -0
  29. data/lib/osso/graphql/query.rb +8 -0
  30. data/lib/osso/graphql/resolvers/enterprise_accounts.rb +3 -3
  31. data/lib/osso/graphql/types.rb +2 -2
  32. data/lib/osso/graphql/types/admin_user.rb +9 -0
  33. data/lib/osso/graphql/types/base_object.rb +1 -1
  34. data/lib/osso/graphql/types/enterprise_account.rb +1 -0
  35. data/lib/osso/graphql/types/identity_provider.rb +2 -0
  36. data/lib/osso/graphql/types/identity_provider_service.rb +3 -1
  37. data/lib/osso/lib/app_config.rb +1 -1
  38. data/lib/osso/lib/route_map.rb +0 -16
  39. data/lib/osso/lib/saml_handler.rb +5 -0
  40. data/lib/osso/models/access_token.rb +4 -2
  41. data/lib/osso/models/account.rb +34 -0
  42. data/lib/osso/models/authorization_code.rb +2 -1
  43. data/lib/osso/models/enterprise_account.rb +3 -1
  44. data/lib/osso/models/identity_provider.rb +19 -5
  45. data/lib/osso/models/models.rb +1 -0
  46. data/lib/osso/models/oauth_client.rb +0 -1
  47. data/lib/osso/models/user.rb +2 -2
  48. data/lib/osso/routes/admin.rb +39 -33
  49. data/lib/osso/routes/auth.rb +9 -9
  50. data/lib/osso/routes/oauth.rb +35 -17
  51. data/lib/osso/version.rb +1 -1
  52. data/lib/osso/views/admin.erb +5 -0
  53. data/lib/osso/views/error.erb +1 -0
  54. data/lib/osso/views/layout.erb +0 -0
  55. data/lib/osso/views/multiple_providers.erb +1 -0
  56. data/lib/osso/views/welcome.erb +0 -0
  57. data/lib/tasks/bootstrap.rake +25 -4
  58. data/osso-rb.gemspec +5 -0
  59. data/spec/factories/account.rb +24 -0
  60. data/spec/factories/enterprise_account.rb +11 -3
  61. data/spec/factories/identity_providers.rb +10 -2
  62. data/spec/factories/user.rb +4 -0
  63. data/spec/graphql/mutations/configure_identity_provider_spec.rb +1 -1
  64. data/spec/graphql/mutations/create_enterprise_account_spec.rb +0 -14
  65. data/spec/graphql/mutations/create_identity_provider_spec.rb +59 -8
  66. data/spec/graphql/query/identity_provider_spec.rb +2 -2
  67. data/spec/models/enterprise_account_spec.rb +18 -0
  68. data/spec/models/identity_provider_spec.rb +24 -3
  69. data/spec/routes/admin_spec.rb +7 -41
  70. data/spec/routes/auth_spec.rb +17 -18
  71. data/spec/routes/oauth_spec.rb +88 -5
  72. data/spec/spec_helper.rb +3 -3
  73. data/spec/support/views/layout.erb +1 -0
  74. data/spec/support/views/multiple_providers.erb +1 -0
  75. metadata +107 -7
  76. data/lib/osso/helpers/auth.rb +0 -94
  77. data/lib/osso/helpers/helpers.rb +0 -8
  78. data/spec/helpers/auth_spec.rb +0 -269
@@ -1,94 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Osso
4
- module Helpers
5
- module Auth
6
- END_USER_SCOPE = 'end-user'
7
- INTERNAL_SCOPE = 'internal'
8
- ADMIN_SCOPE = 'admin'
9
-
10
- attr_accessor :current_user
11
-
12
- def token_protected!
13
- decode(token)
14
- rescue JWT::DecodeError
15
- halt 401
16
- end
17
-
18
- def enterprise_protected!(domain = nil)
19
- return if admin_authorized?
20
- return if internal_authorized?
21
- return if enterprise_authorized?(domain)
22
-
23
- halt 401 if request.post?
24
-
25
- redirect ENV['JWT_URL']
26
- end
27
-
28
- def internal_protected!
29
- return if admin_authorized?
30
- return if internal_authorized?
31
-
32
- redirect ENV['JWT_URL']
33
- end
34
-
35
- def admin_protected!
36
- return true if admin_authorized?
37
-
38
- redirect ENV['JWT_URL']
39
- end
40
-
41
- private
42
-
43
- def enterprise_authorized?(domain)
44
- decode(token)
45
-
46
- @current_user[:scope] == END_USER_SCOPE &&
47
- @current_user[:email].split('@')[1] == domain
48
- rescue JWT::DecodeError
49
- false
50
- end
51
-
52
- def internal_authorized?
53
- decode(token)
54
-
55
- @current_user[:scope] == INTERNAL_SCOPE
56
- rescue JWT::DecodeError
57
- false
58
- end
59
-
60
- def admin_authorized?
61
- decode(token)
62
-
63
- @current_user[:scope] == ADMIN_SCOPE
64
- rescue JWT::DecodeError
65
- false
66
- end
67
-
68
- def token
69
- session['admin_token'] || request.env['HTTP_AUTHORIZATION'] || request.params['admin_token']
70
- end
71
-
72
- def chomp_token
73
- return unless request['admin_token'].present?
74
-
75
- session['admin_token'] = request['admin_token']
76
-
77
- return if request.post?
78
-
79
- redirect request.path
80
- end
81
-
82
- def decode(token)
83
- payload, _args = JWT.decode(
84
- token,
85
- ENV['JWT_HMAC_SECRET'],
86
- true,
87
- { algorithm: 'HS256' },
88
- )
89
-
90
- @current_user = payload.symbolize_keys
91
- end
92
- end
93
- end
94
- end
@@ -1,8 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Osso
4
- module Helpers
5
- end
6
- end
7
-
8
- require_relative 'auth'
@@ -1,269 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
-
5
- describe Osso::Helpers::Auth do
6
- before do
7
- ENV['JWT_HMAC_SECRET'] = 'super-secret'
8
- end
9
-
10
- subject(:app) do
11
- Class.new {
12
- include Osso::Helpers::Auth
13
- }
14
- end
15
-
16
- describe 'with the token as a header' do
17
- before do
18
- allow_any_instance_of(subject).to receive(:request) do
19
- double('Request', env: { 'HTTP_AUTHORIZATION' => token }, post?: false)
20
- end
21
-
22
- allow_any_instance_of(subject).to receive(:session) do
23
- {
24
- admin_token: nil
25
- }
26
- end
27
-
28
- allow_any_instance_of(subject).to receive(:redirect) do
29
- false
30
- end
31
- end
32
-
33
- describe 'with an admin token' do
34
- let(:token) { encode({ scope: 'admin' }) }
35
-
36
- it 'allows #token_protected! methods' do
37
- expect(subject.new.token_protected!).to_not be(false)
38
- end
39
-
40
- it 'allows #enterprise_protected! methods' do
41
- expect(subject.new.enterprise_protected!).to_not be(false)
42
- end
43
-
44
- it 'allows #internal_protected! methods' do
45
- expect(subject.new.internal_protected!).to_not be(false)
46
- end
47
-
48
- it 'allows #admin_protected! methods' do
49
- expect(subject.new.admin_protected!).to_not be(false)
50
- end
51
- end
52
-
53
- describe 'with an internal token' do
54
- let(:token) { encode({ scope: 'internal' }) }
55
-
56
- it 'allows #token_protected! methods' do
57
- expect(subject.new.token_protected!).to_not be(false)
58
- end
59
-
60
- it 'allows #enterprise_protected! methods' do
61
- expect(subject.new.enterprise_protected!).to_not be(false)
62
- end
63
-
64
- it 'allows #internal_protected! methods' do
65
- expect(subject.new.internal_protected!).to_not be(false)
66
- end
67
-
68
- it 'allows #admin_protected! methods' do
69
- expect(subject.new.admin_protected!).to be(false)
70
- end
71
- end
72
-
73
- describe 'with an end-user token' do
74
- let(:token) { encode({ scope: 'end-user', email: 'user@example.com' }) }
75
-
76
- it 'allows #token_protected! methods' do
77
- expect(subject.new.token_protected!).to_not be(false)
78
- end
79
-
80
- it 'allows #enterprise_protected! methods for the scoped domain' do
81
- expect(subject.new.enterprise_protected!('example.com')).to_not be(false)
82
- end
83
-
84
- it 'halts #enterprise_protected! methods for the wrong scoped domain' do
85
- expect(subject.new.enterprise_protected!('foo.com')).to be(false)
86
- end
87
-
88
- it 'halts #internal_protected! methods' do
89
- expect(subject.new.internal_protected!).to be(false)
90
- end
91
-
92
- it 'halts #admin_protected! methods' do
93
- expect(subject.new.admin_protected!).to be(false)
94
- end
95
- end
96
- end
97
-
98
- describe 'with the token as a parameter' do
99
- before do
100
- allow_any_instance_of(subject).to receive(:request) do
101
- double('Request', env: {}, params: { 'admin_token' => token }, post?: false)
102
- end
103
-
104
- allow_any_instance_of(subject).to receive(:session) do
105
- {
106
- admin_token: nil
107
- }
108
- end
109
-
110
- allow_any_instance_of(subject).to receive(:redirect) do
111
- false
112
- end
113
- end
114
-
115
- describe 'with an admin token' do
116
- let(:token) { encode({ scope: 'admin' }) }
117
-
118
- it 'allows #token_protected! methods' do
119
- expect(subject.new.token_protected!).to_not be(false)
120
- end
121
-
122
- it 'allows #enterprise_protected! methods' do
123
- expect(subject.new.enterprise_protected!).to_not be(false)
124
- end
125
-
126
- it 'allows #internal_protected! methods' do
127
- expect(subject.new.internal_protected!).to_not be(false)
128
- end
129
-
130
- it 'allows #admin_protected! methods' do
131
- expect(subject.new.admin_protected!).to_not be(false)
132
- end
133
- end
134
-
135
- describe 'with an internal token' do
136
- let(:token) { encode({ scope: 'internal' }) }
137
-
138
- it 'allows #token_protected! methods' do
139
- expect(subject.new.token_protected!).to_not be(false)
140
- end
141
-
142
- it 'allows #enterprise_protected! methods' do
143
- expect(subject.new.enterprise_protected!).to_not be(false)
144
- end
145
-
146
- it 'allows #internal_protected! methods' do
147
- expect(subject.new.internal_protected!).to_not be(false)
148
- end
149
-
150
- it 'allows #admin_protected! methods' do
151
- expect(subject.new.admin_protected!).to be(false)
152
- end
153
- end
154
-
155
- describe 'with an end-user token' do
156
- let(:token) { encode({ scope: 'end-user', email: 'user@example.com' }) }
157
-
158
- it 'allows #token_protected! methods' do
159
- expect(subject.new.token_protected!).to_not be(false)
160
- end
161
-
162
- it 'allows #enterprise_protected! methods for the scoped domain' do
163
- expect(subject.new.enterprise_protected!('example.com')).to_not be(false)
164
- end
165
-
166
- it 'halts #enterprise_protected! methods for the wrong scoped domain' do
167
- expect(subject.new.enterprise_protected!('foo.com')).to be(false)
168
- end
169
-
170
- it 'halts #internal_protected! methods' do
171
- expect(subject.new.internal_protected!).to be(false)
172
- end
173
-
174
- it 'halts #admin_protected! methods' do
175
- expect(subject.new.admin_protected!).to be(false)
176
- end
177
- end
178
- end
179
-
180
- describe 'with the token in session' do
181
- before do
182
- allow_any_instance_of(subject).to receive(:request) do
183
- double('Request', env: {}, params: {}, post?: false)
184
- end
185
-
186
- allow_any_instance_of(subject).to receive(:redirect) do
187
- false
188
- end
189
-
190
- allow_any_instance_of(subject).to receive(:session).and_return(
191
- {admin_token: token}.with_indifferent_access
192
- )
193
-
194
- end
195
-
196
- describe 'with an admin token' do
197
- let(:token) { encode({ scope: 'admin' }) }
198
-
199
-
200
- it 'allows #token_protected! methods' do
201
- expect(subject.new.token_protected!).to_not be(false)
202
- end
203
-
204
- it 'allows #enterprise_protected! methods' do
205
- expect(subject.new.enterprise_protected!).to_not be(false)
206
- end
207
-
208
- it 'allows #internal_protected! methods' do
209
- expect(subject.new.internal_protected!).to_not be(false)
210
- end
211
-
212
- it 'allows #admin_protected! methods' do
213
- expect(subject.new.admin_protected!).to_not be(false)
214
- end
215
- end
216
-
217
- describe 'with an internal token' do
218
- let(:token) { encode({ scope: 'internal' }) }
219
-
220
- it 'allows #token_protected! methods' do
221
- expect(subject.new.token_protected!).to_not be(false)
222
- end
223
-
224
- it 'allows #enterprise_protected! methods' do
225
- expect(subject.new.enterprise_protected!).to_not be(false)
226
- end
227
-
228
- it 'allows #internal_protected! methods' do
229
- expect(subject.new.internal_protected!).to_not be(false)
230
- end
231
-
232
- it 'allows #admin_protected! methods' do
233
- expect(subject.new.admin_protected!).to be(false)
234
- end
235
- end
236
-
237
- describe 'with an end-user token' do
238
- let(:token) { encode({ scope: 'end-user', email: 'user@example.com' }) }
239
-
240
- it 'allows #token_protected! methods' do
241
- expect(subject.new.token_protected!).to_not be(false)
242
- end
243
-
244
- it 'allows #enterprise_protected! methods for the scoped domain' do
245
- expect(subject.new.enterprise_protected!('example.com')).to_not be(false)
246
- end
247
-
248
- it 'halts #enterprise_protected! methods for the wrong scoped domain' do
249
- expect(subject.new.enterprise_protected!('foo.com')).to be(false)
250
- end
251
-
252
- it 'halts #internal_protected! methods' do
253
- expect(subject.new.internal_protected!).to be(false)
254
- end
255
-
256
- it 'halts #admin_protected! methods' do
257
- expect(subject.new.admin_protected!).to be(false)
258
- end
259
- end
260
- end
261
-
262
- def encode(payload)
263
- JWT.encode(
264
- payload,
265
- ENV['JWT_HMAC_SECRET'],
266
- 'HS256',
267
- )
268
- end
269
- end