osso 0.0.3.2 → 0.0.3.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.
- checksums.yaml +4 -4
- data/.buildkite/pipeline.yml +4 -1
- data/.rubocop.yml +1 -2
- data/Gemfile.lock +3 -1
- data/bin/console +4 -3
- data/config/database.yml +2 -2
- data/db/schema.rb +133 -1
- data/lib/osso.rb +2 -0
- data/lib/osso/db/migrate/20200328143305_create_identity_providers.rb +12 -0
- data/lib/osso/db/migrate/20200411184535_add_provider_id_to_users.rb +2 -2
- data/lib/osso/db/migrate/20200411192645_create_enterprise_accounts.rb +1 -1
- data/lib/osso/db/migrate/20200502135008_add_oauth_client_id_to_enterprise_accounts_and_identity_providers.rb +6 -0
- data/lib/osso/db/migrate/20200714223226_add_identity_provider_service_enum.rb +17 -0
- data/lib/osso/db/migrate/20200715154211_rename_idp_fields_on_identity_provider_to_sso.rb +6 -0
- data/lib/osso/db/migrate/20200715205801_add_name_to_enterprise_account.rb +5 -0
- data/lib/osso/graphql/mutation.rb +10 -5
- data/lib/osso/graphql/mutations.rb +5 -2
- data/lib/osso/graphql/mutations/base_mutation.rb +35 -14
- data/lib/osso/graphql/mutations/configure_identity_provider.rb +31 -21
- data/lib/osso/graphql/mutations/create_enterprise_account.rb +25 -0
- data/lib/osso/graphql/mutations/create_identity_provider.rb +22 -16
- data/lib/osso/graphql/mutations/set_identity_provider.rb +27 -0
- data/lib/osso/graphql/query.rb +19 -22
- data/lib/osso/graphql/resolvers.rb +5 -1
- data/lib/osso/graphql/resolvers/enterprise_account.rb +16 -12
- data/lib/osso/graphql/resolvers/enterprise_accounts.rb +10 -6
- data/lib/osso/graphql/resolvers/oauth_clients.rb +9 -5
- data/lib/osso/graphql/schema.rb +27 -19
- data/lib/osso/graphql/types.rb +4 -1
- data/lib/osso/graphql/types/base_enum.rb +6 -2
- data/lib/osso/graphql/types/base_input_object.rb +10 -0
- data/lib/osso/graphql/types/base_object.rb +6 -2
- data/lib/osso/graphql/types/enterprise_account.rb +22 -18
- data/lib/osso/graphql/types/identity_provider.rb +26 -25
- data/lib/osso/graphql/types/identity_provider_service.rb +8 -4
- data/lib/osso/graphql/types/oauth_client.rb +13 -9
- data/lib/osso/graphql/types/user.rb +10 -5
- data/lib/osso/helpers/auth.rb +5 -3
- data/lib/osso/lib/app_config.rb +1 -1
- data/lib/osso/lib/route_map.rb +28 -0
- data/lib/osso/models/enterprise_account.rb +4 -4
- data/lib/osso/models/identity_provider.rb +48 -0
- data/lib/osso/models/models.rb +1 -1
- data/lib/osso/models/oauth_client.rb +2 -2
- data/lib/osso/models/saml_provider.rb +13 -16
- data/lib/osso/models/saml_providers/azure_saml_provider.rb +2 -2
- data/lib/osso/models/saml_providers/okta_saml_provider.rb +1 -1
- data/lib/osso/models/user.rb +3 -3
- data/lib/osso/routes/admin.rb +18 -15
- data/lib/osso/routes/auth.rb +30 -27
- data/lib/osso/routes/oauth.rb +50 -45
- data/lib/osso/version.rb +1 -1
- data/osso-rb.gemspec +3 -3
- data/spec/factories/enterprise_account.rb +5 -4
- data/spec/factories/identity_providers.rb +49 -0
- data/spec/factories/user.rb +1 -1
- data/spec/graphql/mutations/configure_identity_provider_spec.rb +75 -0
- data/spec/graphql/mutations/create_enterprise_account_spec.rb +68 -0
- data/spec/graphql/mutations/create_identity_provider_spec.rb +104 -0
- data/spec/graphql/query/enterprise_account_spec.rb +68 -0
- data/spec/graphql/query/enterprise_accounts_spec.rb +44 -0
- data/spec/graphql/query/identity_provider_spec.rb +65 -0
- data/spec/graphql/query/oauth_clients_account_spec.rb +48 -0
- data/spec/models/azure_saml_provider_spec.rb +14 -14
- data/spec/models/identity_provider_spec.rb +17 -0
- data/spec/models/okta_saml_provider_spec.rb +15 -15
- data/spec/routes/admin_spec.rb +2 -0
- data/spec/routes/auth_spec.rb +9 -9
- data/spec/routes/oauth_spec.rb +1 -1
- data/spec/spec_helper.rb +4 -5
- data/spec/support/spec_app.rb +9 -0
- data/spec/support/views/admin.erb +5 -0
- metadata +37 -12
- data/lib/osso/db/migrate/20200411144528_create_saml_providers.rb +0 -13
- data/lib/osso/db/migrate/20200413153029_add_oauth_client_reference_to_saml_providers.rb +0 -5
- data/lib/osso/db/migrate/20200501203026_drop_null_constraints_from_saml_provider.rb +0 -7
- data/lib/osso/db/migrate/20200501204047_drop_acs_url.rb +0 -5
- data/lib/osso/db/migrate/20200502135008_add_oauth_client_id_to_enterprise_account.rb +0 -5
- data/lib/osso/db/migrate/20200601131227_drop_null_constraint_from_saml_providers_provider.rb +0 -7
- data/lib/osso/db/schema.rb +0 -132
- data/lib/osso/graphql/mutations/set_saml_provider.rb +0 -23
- data/spec/factories/saml_providers.rb +0 -46
- data/spec/models/saml_provider_spec.rb +0 -31
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Osso::GraphQL::Schema do
|
6
|
+
describe 'EnterpriseAccount' do
|
7
|
+
let(:domain) { Faker::Internet.domain_name }
|
8
|
+
let(:variables) { { domain: domain } }
|
9
|
+
let(:query) do
|
10
|
+
<<~GRAPHQL
|
11
|
+
query EnterpriseAccount($domain: String!) {
|
12
|
+
enterpriseAccount(domain: $domain) {
|
13
|
+
domain
|
14
|
+
id
|
15
|
+
identityProviders {
|
16
|
+
id
|
17
|
+
service
|
18
|
+
domain
|
19
|
+
acsUrl
|
20
|
+
ssoCert
|
21
|
+
ssoUrl
|
22
|
+
configured
|
23
|
+
}
|
24
|
+
name
|
25
|
+
status
|
26
|
+
}
|
27
|
+
}
|
28
|
+
GRAPHQL
|
29
|
+
end
|
30
|
+
|
31
|
+
before do
|
32
|
+
create(:enterprise_account)
|
33
|
+
create(:enterprise_account, domain: domain)
|
34
|
+
end
|
35
|
+
|
36
|
+
subject do
|
37
|
+
described_class.execute(
|
38
|
+
query,
|
39
|
+
variables: variables,
|
40
|
+
context: { scope: current_scope },
|
41
|
+
)
|
42
|
+
end
|
43
|
+
|
44
|
+
describe 'for an admin user' do
|
45
|
+
let(:current_scope) { :admin }
|
46
|
+
it 'returns Enterprise Account for domain' do
|
47
|
+
expect(subject['errors']).to be_nil
|
48
|
+
expect(subject.dig('data', 'enterpriseAccount', 'domain')).to eq(domain)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe 'for an email scoped user' do
|
53
|
+
let(:current_scope) { domain }
|
54
|
+
it 'returns Enterprise Account for domain' do
|
55
|
+
expect(subject['errors']).to be_nil
|
56
|
+
expect(subject.dig('data', 'enterpriseAccount', 'domain')).to eq(domain)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe 'for the wrong email scoped user' do
|
61
|
+
let(:current_scope) { 'bar.com' }
|
62
|
+
it 'returns Enterprise Account for domain' do
|
63
|
+
expect(subject['errors']).to be_nil
|
64
|
+
expect(subject.dig('data', 'enterpriseAccount')).to be_nil
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Osso::GraphQL::Schema do
|
6
|
+
describe 'EnterpriseAccounts' do
|
7
|
+
describe 'for an admin user' do
|
8
|
+
let(:current_scope) { :admin }
|
9
|
+
|
10
|
+
it 'returns Enterprise Accounts' do
|
11
|
+
create_list(:enterprise_account, 2)
|
12
|
+
|
13
|
+
query = <<~GRAPHQL
|
14
|
+
query EnterpriseAccounts {
|
15
|
+
enterpriseAccounts {
|
16
|
+
domain
|
17
|
+
id
|
18
|
+
identityProviders {
|
19
|
+
id
|
20
|
+
service
|
21
|
+
domain
|
22
|
+
acsUrl
|
23
|
+
ssoCert
|
24
|
+
ssoUrl
|
25
|
+
configured
|
26
|
+
}
|
27
|
+
name
|
28
|
+
status
|
29
|
+
}
|
30
|
+
}
|
31
|
+
GRAPHQL
|
32
|
+
|
33
|
+
response = described_class.execute(
|
34
|
+
query,
|
35
|
+
variables: nil,
|
36
|
+
context: { scope: current_scope },
|
37
|
+
)
|
38
|
+
|
39
|
+
expect(response['errors']).to be_nil
|
40
|
+
expect(response.dig('data', 'enterpriseAccounts').count).to eq(2)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Osso::GraphQL::Schema do
|
6
|
+
describe 'Identity Provider' do
|
7
|
+
let(:id) { Faker::Internet.uuid }
|
8
|
+
let(:domain) { Faker::Internet.domain_name }
|
9
|
+
let(:variables) { { id: id } }
|
10
|
+
let(:query) do
|
11
|
+
<<~GRAPHQL
|
12
|
+
query IdentityProvider($id: ID!) {
|
13
|
+
identityProvider(id: $id) {
|
14
|
+
id
|
15
|
+
service
|
16
|
+
domain
|
17
|
+
acsUrl
|
18
|
+
ssoCert
|
19
|
+
ssoUrl
|
20
|
+
configured
|
21
|
+
}
|
22
|
+
}
|
23
|
+
GRAPHQL
|
24
|
+
end
|
25
|
+
|
26
|
+
before do
|
27
|
+
create(:identity_provider)
|
28
|
+
create(:identity_provider, id: id, domain: domain)
|
29
|
+
end
|
30
|
+
|
31
|
+
subject do
|
32
|
+
described_class.execute(
|
33
|
+
query,
|
34
|
+
variables: variables,
|
35
|
+
context: { scope: current_scope },
|
36
|
+
)
|
37
|
+
end
|
38
|
+
|
39
|
+
describe 'for an admin user' do
|
40
|
+
let(:current_scope) { :admin }
|
41
|
+
it 'returns Identity Provider for id' do
|
42
|
+
expect(subject['errors']).to be_nil
|
43
|
+
expect(subject.dig('data', 'identityProvider', 'id')).to eq(id)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe 'for an email scoped user' do
|
48
|
+
let(:current_scope) { domain }
|
49
|
+
|
50
|
+
it 'returns Enterprise Account for domain' do
|
51
|
+
expect(subject['errors']).to be_nil
|
52
|
+
expect(subject.dig('data', 'identityProvider', 'domain')).to eq(domain)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe 'for the wrong email scoped user' do
|
57
|
+
let(:current_scope) { 'bar.com' }
|
58
|
+
|
59
|
+
it 'returns Enterprise Account for domain' do
|
60
|
+
expect(subject['errors']).to_not be_empty
|
61
|
+
expect(subject.dig('data', 'enterpriseAccount')).to be_nil
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Osso::GraphQL::Schema do
|
6
|
+
describe 'OAuthClients' do
|
7
|
+
let(:query) do
|
8
|
+
<<~GRAPHQL
|
9
|
+
query OAuthClients {
|
10
|
+
oauthClients {
|
11
|
+
name
|
12
|
+
id
|
13
|
+
}
|
14
|
+
}
|
15
|
+
GRAPHQL
|
16
|
+
end
|
17
|
+
|
18
|
+
before do
|
19
|
+
create_list(:oauth_client, 2)
|
20
|
+
end
|
21
|
+
|
22
|
+
subject do
|
23
|
+
described_class.execute(
|
24
|
+
query,
|
25
|
+
variables: nil,
|
26
|
+
context: { scope: current_scope },
|
27
|
+
)
|
28
|
+
end
|
29
|
+
|
30
|
+
describe 'for an admin user' do
|
31
|
+
let(:current_scope) { :admin }
|
32
|
+
|
33
|
+
it 'returns Oauth Clients' do
|
34
|
+
expect(subject['errors']).to be_nil
|
35
|
+
expect(subject.dig('data', 'oauthClients').count).to eq(2)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe 'for an email scoped user' do
|
40
|
+
let(:current_scope) { 'foo.com' }
|
41
|
+
|
42
|
+
it 'returns Oauth Clients' do
|
43
|
+
expect(subject['errors']).to be_nil
|
44
|
+
expect(subject.dig('data', 'oauthClients')).to be_nil
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -2,18 +2,18 @@
|
|
2
2
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
|
-
describe Osso::Models::AzureSamlProvider do
|
6
|
-
|
5
|
+
# describe Osso::Models::AzureSamlProvider do
|
6
|
+
# subject { create(:azure_identity_provider) }
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
end
|
8
|
+
# describe '#saml_options' do
|
9
|
+
# it 'returns the required args' do
|
10
|
+
# expect(subject.saml_options).
|
11
|
+
# to match(
|
12
|
+
# domain: subject.domain,
|
13
|
+
# idp_cert: subject.idp_cert,
|
14
|
+
# idp_sso_target_url: subject.idp_sso_target_url,
|
15
|
+
# issuer: "id:#{subject.id}",
|
16
|
+
# )
|
17
|
+
# end
|
18
|
+
# end
|
19
|
+
# end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Osso::Models::IdentityProvider do
|
6
|
+
subject { create(:okta_identity_provider) }
|
7
|
+
|
8
|
+
describe '#assertion_consumer_service_url' do
|
9
|
+
it 'returns the expected URI' do
|
10
|
+
ENV['BASE_URL'] = 'https://example.com'
|
11
|
+
|
12
|
+
expect(subject.assertion_consumer_service_url).to eq(
|
13
|
+
"https://example.com/auth/saml/#{subject.id}/callback",
|
14
|
+
)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -2,19 +2,19 @@
|
|
2
2
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
|
-
describe Osso::Models::OktaSamlProvider do
|
6
|
-
|
5
|
+
# describe Osso::Models::OktaSamlProvider do
|
6
|
+
# subject { create(:okta_identity_provider) }
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
end
|
8
|
+
# describe '#saml_options' do
|
9
|
+
# it 'returns the required args' do
|
10
|
+
# expect(subject.saml_options).
|
11
|
+
# to match(
|
12
|
+
# domain: subject.domain,
|
13
|
+
# idp_cert: subject.idp_cert,
|
14
|
+
# idp_sso_target_url: subject.idp_sso_target_url,
|
15
|
+
# issuer: subject.id,
|
16
|
+
# name_identifier_format: described_class::NAME_FORMAT,
|
17
|
+
# )
|
18
|
+
# end
|
19
|
+
# end
|
20
|
+
# end
|
data/spec/routes/admin_spec.rb
CHANGED
data/spec/routes/auth_spec.rb
CHANGED
@@ -6,7 +6,7 @@ describe Osso::Auth do
|
|
6
6
|
describe 'post /auth/saml/:uuid/callback' do
|
7
7
|
describe 'for an Okta SAML provider' do
|
8
8
|
let(:enterprise) { create(:enterprise_with_okta) }
|
9
|
-
let(:okta_provider) { enterprise.
|
9
|
+
let(:okta_provider) { enterprise.identity_providers.first }
|
10
10
|
|
11
11
|
describe "on the user's first authentication" do
|
12
12
|
it 'creates a user' do
|
@@ -18,7 +18,7 @@ describe Osso::Auth do
|
|
18
18
|
nil,
|
19
19
|
{
|
20
20
|
'omniauth.auth' => OmniAuth.config.mock_auth[:saml],
|
21
|
-
'
|
21
|
+
'identity_provider' => okta_provider,
|
22
22
|
},
|
23
23
|
)
|
24
24
|
end.to change { Osso::Models::User.count }.by(1)
|
@@ -33,7 +33,7 @@ describe Osso::Auth do
|
|
33
33
|
nil,
|
34
34
|
{
|
35
35
|
'omniauth.auth' => OmniAuth.config.mock_auth[:saml],
|
36
|
-
'
|
36
|
+
'identity_provider' => okta_provider,
|
37
37
|
},
|
38
38
|
)
|
39
39
|
end.to change { Osso::Models::AuthorizationCode.count }.by(1)
|
@@ -42,8 +42,8 @@ describe Osso::Auth do
|
|
42
42
|
|
43
43
|
describe 'on subsequent authentications' do
|
44
44
|
let!(:enterprise) { create(:enterprise_with_okta) }
|
45
|
-
let!(:okta_provider) { enterprise.
|
46
|
-
let(:user) { create(:user,
|
45
|
+
let!(:okta_provider) { enterprise.identity_providers.first }
|
46
|
+
let(:user) { create(:user, identity_provider_id: okta_provider.id) }
|
47
47
|
|
48
48
|
before do
|
49
49
|
mock_saml_omniauth(email: user.email, id: user.idp_id)
|
@@ -56,7 +56,7 @@ describe Osso::Auth do
|
|
56
56
|
nil,
|
57
57
|
{
|
58
58
|
'omniauth.auth' => OmniAuth.config.mock_auth[:saml],
|
59
|
-
'
|
59
|
+
'identity_provider' => okta_provider,
|
60
60
|
},
|
61
61
|
)
|
62
62
|
end.to_not(change { Osso::Models::User.count })
|
@@ -78,7 +78,7 @@ describe Osso::Auth do
|
|
78
78
|
nil,
|
79
79
|
{
|
80
80
|
'omniauth.auth' => OmniAuth.config.mock_auth[:saml],
|
81
|
-
'
|
81
|
+
'identity_provider' => azure_provider,
|
82
82
|
},
|
83
83
|
)
|
84
84
|
end.to change { Osso::Models::User.count }.by(1)
|
@@ -88,7 +88,7 @@ describe Osso::Auth do
|
|
88
88
|
describe 'on subsequent authentications' do
|
89
89
|
let!(:enterprise) { create(:enterprise_with_azure) }
|
90
90
|
let!(:azure_provider) { enterprise.provider }
|
91
|
-
let(:user) { create(:user,
|
91
|
+
let(:user) { create(:user, identity_provider_id: azure_provider.id) }
|
92
92
|
|
93
93
|
before do
|
94
94
|
mock_saml_omniauth(email: user.email, id: user.idp_id)
|
@@ -101,7 +101,7 @@ describe Osso::Auth do
|
|
101
101
|
nil,
|
102
102
|
{
|
103
103
|
'omniauth.auth' => OmniAuth.config.mock_auth[:saml],
|
104
|
-
'
|
104
|
+
'identity_provider' => azure_provider,
|
105
105
|
},
|
106
106
|
)
|
107
107
|
end.to_not(change { Osso::Models::User.count })
|
data/spec/routes/oauth_spec.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
@@ -11,18 +11,17 @@ require 'webmock/rspec'
|
|
11
11
|
|
12
12
|
ENV['RACK_ENV'] = 'test'
|
13
13
|
ENV['SESSION_SECRET'] = 'supersecret'
|
14
|
+
ENV['BASE_URL'] = 'https://example.com'
|
14
15
|
|
15
16
|
require File.expand_path '../lib/osso.rb', __dir__
|
16
17
|
|
18
|
+
require File.expand_path 'support/spec_app', __dir__
|
19
|
+
|
17
20
|
module RSpecMixin
|
18
21
|
include Rack::Test::Methods
|
19
22
|
|
20
23
|
def app
|
21
|
-
|
22
|
-
'/admin' => Osso::Admin,
|
23
|
-
'/auth' => Osso::Auth,
|
24
|
-
'/oauth' => Osso::Oauth,
|
25
|
-
)
|
24
|
+
SpecApp
|
26
25
|
end
|
27
26
|
|
28
27
|
def mock_saml_omniauth(email: 'user@enterprise.com', id: SecureRandom.uuid)
|