osso 0.0.3.7 → 0.0.3.12
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 +5 -3
- data/Gemfile.lock +5 -1
- data/bin/annotate +1 -0
- data/db/schema.rb +11 -54
- data/lib/osso/db/migrate/20200714223226_add_identity_provider_service_enum.rb +1 -1
- data/lib/osso/db/migrate/20200722230116_add_identity_provider_status_enum_and_use_on_identity_providers.rb +15 -0
- data/lib/osso/db/migrate/20200723153750_add_missing_timestamps.rb +35 -0
- data/lib/osso/db/migrate/20200723162228_drop_unneeded_tables.rb +9 -0
- data/lib/osso/graphql/mutation.rb +7 -1
- data/lib/osso/graphql/mutations.rb +7 -1
- data/lib/osso/graphql/mutations/add_redirect_uris_to_oauth_client.rb +39 -0
- data/lib/osso/graphql/mutations/configure_identity_provider.rb +1 -1
- data/lib/osso/graphql/mutations/create_oauth_client.rb +30 -0
- data/lib/osso/graphql/mutations/delete_enterprise_account.rb +34 -0
- data/lib/osso/graphql/mutations/delete_oauth_client.rb +30 -0
- data/lib/osso/graphql/mutations/delete_redirect_uri.rb +38 -0
- data/lib/osso/graphql/mutations/mark_redirect_uri_primary.rb +34 -0
- data/lib/osso/graphql/mutations/regenerate_oauth_credentials.rb +31 -0
- data/lib/osso/graphql/query.rb +15 -2
- data/lib/osso/graphql/resolvers/enterprise_accounts.rb +12 -4
- data/lib/osso/graphql/resolvers/oauth_clients.rb +1 -1
- data/lib/osso/graphql/types.rb +3 -0
- data/lib/osso/graphql/types/base_connection.rb +15 -0
- data/lib/osso/graphql/types/base_object.rb +4 -0
- data/lib/osso/graphql/types/identity_provider.rb +1 -5
- data/lib/osso/graphql/types/identity_provider_status.rb +14 -0
- data/lib/osso/graphql/types/oauth_client.rb +14 -1
- data/lib/osso/graphql/types/redirect_uri.rb +23 -0
- data/lib/osso/helpers/auth.rb +13 -12
- data/lib/osso/models/access_token.rb +18 -0
- data/lib/osso/models/authorization_code.rb +20 -0
- data/lib/osso/models/enterprise_account.rb +20 -0
- data/lib/osso/models/identity_provider.rb +29 -0
- data/lib/osso/models/models.rb +2 -0
- data/lib/osso/models/oauth_client.rb +20 -10
- data/lib/osso/models/redirect_uri.rb +17 -0
- data/lib/osso/models/user.rb +22 -0
- data/lib/osso/routes/admin.rb +6 -0
- data/lib/osso/routes/auth.rb +1 -1
- data/lib/osso/version.rb +1 -1
- data/osso-rb.gemspec +1 -0
- data/spec/factories/identity_providers.rb +22 -0
- data/spec/graphql/mutations/configure_identity_provider_spec.rb +3 -3
- data/spec/graphql/mutations/create_oauth_client_spec.rb +55 -0
- data/spec/graphql/mutations/delete_enterprise_account_spec.rb +63 -0
- data/spec/graphql/mutations/delete_oauth_client_spec.rb +51 -0
- data/spec/graphql/query/enterprise_account_spec.rb +1 -1
- data/spec/graphql/query/enterprise_accounts_spec.rb +32 -18
- data/spec/graphql/query/identity_provider_spec.rb +2 -2
- data/spec/graphql/query/{oauth_clients_account_spec.rb → oauth_clients_spec.rb} +2 -0
- data/spec/routes/auth_spec.rb +25 -0
- metadata +35 -8
- data/lib/osso/db/migrate/20200328143303_create_oauth_tables.rb +0 -57
- data/lib/osso/graphql/mutations/set_identity_provider.rb +0 -27
- data/lib/osso/models/saml_provider.rb +0 -49
- data/lib/osso/models/saml_providers/azure_saml_provider.rb +0 -22
- data/lib/osso/models/saml_providers/okta_saml_provider.rb +0 -23
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Osso
|
4
|
+
module GraphQL
|
5
|
+
module Mutations
|
6
|
+
class MarkRedirectUriPrimary < BaseMutation
|
7
|
+
null false
|
8
|
+
|
9
|
+
argument :id, ID, required: true
|
10
|
+
|
11
|
+
field :oauth_client, Types::OauthClient, null: true
|
12
|
+
field :errors, [String], null: false
|
13
|
+
|
14
|
+
def resolve(id:)
|
15
|
+
redirect_uri = Osso::Models::RedirectUri.find(id)
|
16
|
+
oauth_client = redirect_uri.oauth_client
|
17
|
+
|
18
|
+
oauth_client.redirect_uris.update(primary: false)
|
19
|
+
redirect_uri.update(primary: true)
|
20
|
+
|
21
|
+
response_data(oauth_client: oauth_client.reload)
|
22
|
+
rescue StandardError => e
|
23
|
+
response_error(errors: e.message)
|
24
|
+
end
|
25
|
+
|
26
|
+
def ready?(*)
|
27
|
+
return true if context[:scope] == :admin
|
28
|
+
|
29
|
+
raise ::GraphQL::ExecutionError, 'Only admin users may mutate OauthClients'
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Osso
|
4
|
+
module GraphQL
|
5
|
+
module Mutations
|
6
|
+
class RegenerateOauthCredentials < BaseMutation
|
7
|
+
null false
|
8
|
+
|
9
|
+
argument :id, ID, required: true
|
10
|
+
|
11
|
+
field :oauth_client, Types::OauthClient, null: false
|
12
|
+
field :errors, [String], null: false
|
13
|
+
|
14
|
+
def resolve(id:)
|
15
|
+
oauth_client = Osso::Models::OauthClient.find(id)
|
16
|
+
oauth_client.generate_secrets
|
17
|
+
|
18
|
+
return response_data(oauth_client: oauth_client) if oauth_client.save
|
19
|
+
|
20
|
+
response_error(errors: oauth_client.errors.full_messages)
|
21
|
+
end
|
22
|
+
|
23
|
+
def ready?(*)
|
24
|
+
return true if context[:scope] == :admin
|
25
|
+
|
26
|
+
raise ::GraphQL::ExecutionError, 'Only admin users may mutate OauthClients'
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/osso/graphql/query.rb
CHANGED
@@ -4,13 +4,17 @@ module Osso
|
|
4
4
|
module GraphQL
|
5
5
|
module Types
|
6
6
|
class QueryType < ::GraphQL::Schema::Object
|
7
|
-
field :enterprise_accounts, null: true, resolver: Resolvers::EnterpriseAccounts
|
8
|
-
|
7
|
+
field :enterprise_accounts, null: true, resolver: Resolvers::EnterpriseAccounts do
|
8
|
+
argument :sort_column, String, required: false
|
9
|
+
argument :sort_order, String, required: false
|
10
|
+
end
|
9
11
|
|
10
12
|
field :enterprise_account, null: true, resolver: Resolvers::EnterpriseAccount do
|
11
13
|
argument :domain, String, required: true
|
12
14
|
end
|
13
15
|
|
16
|
+
field :oauth_clients, null: true, resolver: Resolvers::OAuthClients
|
17
|
+
|
14
18
|
field(
|
15
19
|
:identity_provider,
|
16
20
|
Types::IdentityProvider,
|
@@ -19,6 +23,15 @@ module Osso
|
|
19
23
|
) do
|
20
24
|
argument :id, ID, required: true
|
21
25
|
end
|
26
|
+
|
27
|
+
field(
|
28
|
+
:oauth_client,
|
29
|
+
Types::OauthClient,
|
30
|
+
null: true,
|
31
|
+
resolve: ->(_obj, args, _context) { Osso::Models::OauthClient.find(args[:id]) },
|
32
|
+
) do
|
33
|
+
argument :id, ID, required: true
|
34
|
+
end
|
22
35
|
end
|
23
36
|
end
|
24
37
|
end
|
@@ -4,12 +4,20 @@ module Osso
|
|
4
4
|
module GraphQL
|
5
5
|
module Resolvers
|
6
6
|
class EnterpriseAccounts < ::GraphQL::Schema::Resolver
|
7
|
-
type
|
7
|
+
type Types::EnterpriseAccount.connection_type, null: true
|
8
8
|
|
9
|
-
def resolve
|
10
|
-
return Osso::Models::EnterpriseAccount.
|
9
|
+
def resolve(sort_column: nil, sort_order: nil)
|
10
|
+
return Array(Osso::Models::EnterpriseAccount.find_by(domain: context[:scope])) if context[:scope] != :admin
|
11
11
|
|
12
|
-
|
12
|
+
accounts = Osso::Models::EnterpriseAccount
|
13
|
+
|
14
|
+
accounts = accounts.order(sort_column => sort_order_sym(sort_order)) if sort_column && sort_order
|
15
|
+
|
16
|
+
accounts.all
|
17
|
+
end
|
18
|
+
|
19
|
+
def sort_order_sym(order_string)
|
20
|
+
order_string == 'ascend' ? :asc : :desc
|
13
21
|
end
|
14
22
|
end
|
15
23
|
end
|
data/lib/osso/graphql/types.rb
CHANGED
@@ -5,11 +5,14 @@ module Osso
|
|
5
5
|
end
|
6
6
|
end
|
7
7
|
|
8
|
+
require_relative 'types/base_connection'
|
8
9
|
require_relative 'types/base_object'
|
9
10
|
require_relative 'types/base_enum'
|
10
11
|
require_relative 'types/base_input_object'
|
11
12
|
require_relative 'types/identity_provider_service'
|
13
|
+
require_relative 'types/identity_provider_status'
|
12
14
|
require_relative 'types/identity_provider'
|
13
15
|
require_relative 'types/enterprise_account'
|
16
|
+
require_relative 'types/redirect_uri'
|
14
17
|
require_relative 'types/oauth_client'
|
15
18
|
require_relative 'types/user'
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Osso
|
4
|
+
module GraphQL
|
5
|
+
module Types
|
6
|
+
class BaseConnection < ::GraphQL::Types::Relay::BaseConnection
|
7
|
+
field :total_count, Integer, null: false
|
8
|
+
|
9
|
+
def total_count
|
10
|
+
object.items&.count
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -6,6 +6,10 @@ module Osso
|
|
6
6
|
module GraphQL
|
7
7
|
module Types
|
8
8
|
class BaseObject < ::GraphQL::Schema::Object
|
9
|
+
connection_type_class GraphQL::Types::BaseConnection
|
10
|
+
|
11
|
+
field :created_at, ::GraphQL::Types::ISO8601DateTime, null: false
|
12
|
+
field :updated_at, ::GraphQL::Types::ISO8601DateTime, null: false
|
9
13
|
end
|
10
14
|
end
|
11
15
|
end
|
@@ -17,13 +17,9 @@ module Osso
|
|
17
17
|
field :acs_url, String, null: false
|
18
18
|
field :sso_url, String, null: true
|
19
19
|
field :sso_cert, String, null: true
|
20
|
-
field :
|
20
|
+
field :status, Types::IdentityProviderStatus, null: false
|
21
21
|
field :documentation_pdf_url, String, null: true
|
22
22
|
|
23
|
-
def configured
|
24
|
-
!!(@object.sso_url && @object.sso_cert)
|
25
|
-
end
|
26
|
-
|
27
23
|
def documentation_pdf_url
|
28
24
|
ENV['BASE_URL'] + '/identity_provider/documentation/' + @object.id
|
29
25
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Osso
|
4
|
+
module GraphQL
|
5
|
+
module Types
|
6
|
+
class IdentityProviderStatus < BaseEnum
|
7
|
+
value('Pending', value: 'PENDING')
|
8
|
+
value('Configured', value: 'CONFIGURED')
|
9
|
+
value('Active', value: 'ACTIVE')
|
10
|
+
value('Error', value: 'ERROR')
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -5,7 +5,7 @@ require 'graphql'
|
|
5
5
|
module Osso
|
6
6
|
module GraphQL
|
7
7
|
module Types
|
8
|
-
class
|
8
|
+
class OauthClient < Types::BaseObject
|
9
9
|
description 'An OAuth client used to consume Osso SAML users'
|
10
10
|
implements ::GraphQL::Types::Relay::Node
|
11
11
|
|
@@ -14,6 +14,19 @@ module Osso
|
|
14
14
|
field :name, String, null: false
|
15
15
|
field :client_id, String, null: false
|
16
16
|
field :client_secret, String, null: false
|
17
|
+
field :redirect_uris, [Types::RedirectUri], null: true
|
18
|
+
|
19
|
+
def client_id
|
20
|
+
object.identifier
|
21
|
+
end
|
22
|
+
|
23
|
+
def client_secret
|
24
|
+
object.secret
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.authorized?(object, context)
|
28
|
+
super && context[:scope] == :admin
|
29
|
+
end
|
17
30
|
end
|
18
31
|
end
|
19
32
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'graphql'
|
4
|
+
|
5
|
+
module Osso
|
6
|
+
module GraphQL
|
7
|
+
module Types
|
8
|
+
class RedirectUri < Types::BaseObject
|
9
|
+
description 'An allowed redirect URI for an OauthClient'
|
10
|
+
implements ::GraphQL::Types::Relay::Node
|
11
|
+
|
12
|
+
global_id_field :gid
|
13
|
+
field :id, ID, null: false
|
14
|
+
field :uri, String, null: false
|
15
|
+
field :primary, Boolean, null: false
|
16
|
+
|
17
|
+
def self.authorized?(object, context)
|
18
|
+
super && context[:scope] == :admin
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/osso/helpers/auth.rb
CHANGED
@@ -14,13 +14,10 @@ module Osso
|
|
14
14
|
redirect ENV['JWT_URL']
|
15
15
|
end
|
16
16
|
|
17
|
+
# use client id in payload to restrict customer
|
18
|
+
# users from accessing dev?
|
17
19
|
def enterprise_authorized?(_domain)
|
18
|
-
payload, _args =
|
19
|
-
token,
|
20
|
-
ENV['JWT_HMAC_SECRET'],
|
21
|
-
true,
|
22
|
-
{ algorithm: 'HS256' },
|
23
|
-
)
|
20
|
+
payload, _args = decode(token)
|
24
21
|
|
25
22
|
@current_scope = payload['scope']
|
26
23
|
|
@@ -36,12 +33,7 @@ module Osso
|
|
36
33
|
end
|
37
34
|
|
38
35
|
def admin_authorized?
|
39
|
-
payload, _args =
|
40
|
-
token,
|
41
|
-
ENV['JWT_HMAC_SECRET'],
|
42
|
-
true,
|
43
|
-
{ algorithm: 'HS256' },
|
44
|
-
)
|
36
|
+
payload, _args = decode(token)
|
45
37
|
|
46
38
|
if payload['scope'] == 'admin'
|
47
39
|
@current_scope = :admin
|
@@ -66,6 +58,15 @@ module Osso
|
|
66
58
|
|
67
59
|
redirect request.path
|
68
60
|
end
|
61
|
+
|
62
|
+
def decode(token)
|
63
|
+
JWT.decode(
|
64
|
+
token,
|
65
|
+
ENV['JWT_HMAC_SECRET'],
|
66
|
+
true,
|
67
|
+
{ algorithm: 'HS256' },
|
68
|
+
)
|
69
|
+
end
|
69
70
|
end
|
70
71
|
end
|
71
72
|
end
|
@@ -27,3 +27,21 @@ module Osso
|
|
27
27
|
end
|
28
28
|
end
|
29
29
|
end
|
30
|
+
|
31
|
+
# == Schema Information
|
32
|
+
#
|
33
|
+
# Table name: access_tokens
|
34
|
+
#
|
35
|
+
# id :uuid not null, primary key
|
36
|
+
# token :string
|
37
|
+
# expires_at :datetime
|
38
|
+
# created_at :datetime not null
|
39
|
+
# updated_at :datetime not null
|
40
|
+
# user_id :uuid
|
41
|
+
# oauth_client_id :uuid
|
42
|
+
#
|
43
|
+
# Indexes
|
44
|
+
#
|
45
|
+
# index_access_tokens_on_oauth_client_id (oauth_client_id)
|
46
|
+
# index_access_tokens_on_user_id (user_id)
|
47
|
+
#
|
@@ -12,3 +12,23 @@ module Osso
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
end
|
15
|
+
|
16
|
+
# == Schema Information
|
17
|
+
#
|
18
|
+
# Table name: authorization_codes
|
19
|
+
#
|
20
|
+
# id :uuid not null, primary key
|
21
|
+
# token :string
|
22
|
+
# redirect_uri :string
|
23
|
+
# expires_at :datetime
|
24
|
+
# created_at :datetime not null
|
25
|
+
# updated_at :datetime not null
|
26
|
+
# user_id :uuid
|
27
|
+
# oauth_client_id :uuid
|
28
|
+
#
|
29
|
+
# Indexes
|
30
|
+
#
|
31
|
+
# index_authorization_codes_on_oauth_client_id (oauth_client_id)
|
32
|
+
# index_authorization_codes_on_token (token) UNIQUE
|
33
|
+
# index_authorization_codes_on_user_id (user_id)
|
34
|
+
#
|
@@ -26,3 +26,23 @@ module Osso
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
end
|
29
|
+
|
30
|
+
# == Schema Information
|
31
|
+
#
|
32
|
+
# Table name: enterprise_accounts
|
33
|
+
#
|
34
|
+
# id :uuid not null, primary key
|
35
|
+
# domain :string not null
|
36
|
+
# external_uuid :uuid
|
37
|
+
# external_int_id :integer
|
38
|
+
# external_id :string
|
39
|
+
# oauth_client_id :uuid
|
40
|
+
# name :string not null
|
41
|
+
# created_at :datetime not null
|
42
|
+
# updated_at :datetime not null
|
43
|
+
#
|
44
|
+
# Indexes
|
45
|
+
#
|
46
|
+
# index_enterprise_accounts_on_domain (domain) UNIQUE
|
47
|
+
# index_enterprise_accounts_on_oauth_client_id (oauth_client_id)
|
48
|
+
#
|
@@ -8,6 +8,7 @@ module Osso
|
|
8
8
|
belongs_to :enterprise_account
|
9
9
|
belongs_to :oauth_client
|
10
10
|
has_many :users
|
11
|
+
before_save :set_status
|
11
12
|
|
12
13
|
def name
|
13
14
|
service.titlecase
|
@@ -43,6 +44,34 @@ module Osso
|
|
43
44
|
end
|
44
45
|
|
45
46
|
alias acs_url assertion_consumer_service_url
|
47
|
+
|
48
|
+
def set_status
|
49
|
+
return if status != 'PENDING'
|
50
|
+
|
51
|
+
self.status = 'CONFIGURED' if sso_url && sso_cert
|
52
|
+
end
|
46
53
|
end
|
47
54
|
end
|
48
55
|
end
|
56
|
+
|
57
|
+
# == Schema Information
|
58
|
+
#
|
59
|
+
# Table name: identity_providers
|
60
|
+
#
|
61
|
+
# id :uuid not null, primary key
|
62
|
+
# service :string
|
63
|
+
# domain :string not null
|
64
|
+
# sso_url :string
|
65
|
+
# sso_cert :text
|
66
|
+
# enterprise_account_id :uuid
|
67
|
+
# oauth_client_id :uuid
|
68
|
+
# status :enum default("PENDING")
|
69
|
+
# created_at :datetime
|
70
|
+
# updated_at :datetime
|
71
|
+
#
|
72
|
+
# Indexes
|
73
|
+
#
|
74
|
+
# index_identity_providers_on_domain (domain)
|
75
|
+
# index_identity_providers_on_enterprise_account_id (enterprise_account_id)
|
76
|
+
# index_identity_providers_on_oauth_client_id (oauth_client_id)
|
77
|
+
#
|
data/lib/osso/models/models.rb
CHANGED
@@ -9,24 +9,34 @@ module Osso
|
|
9
9
|
has_many :identity_providers
|
10
10
|
has_many :redirect_uris
|
11
11
|
|
12
|
-
before_validation :
|
12
|
+
before_validation :generate_secrets, on: :create
|
13
13
|
validates :name, :secret, presence: true
|
14
14
|
validates :identifier, presence: true, uniqueness: true
|
15
15
|
|
16
|
-
def
|
16
|
+
def primary_redirect_uri
|
17
17
|
redirect_uris.find(&:primary)
|
18
18
|
end
|
19
19
|
|
20
|
-
def
|
21
|
-
redirect_uris.map(&:uri)
|
22
|
-
end
|
23
|
-
|
24
|
-
private
|
25
|
-
|
26
|
-
def setup
|
20
|
+
def generate_secrets
|
27
21
|
self.identifier = SecureRandom.hex(16)
|
28
|
-
self.secret = SecureRandom.hex(
|
22
|
+
self.secret = SecureRandom.hex(32)
|
29
23
|
end
|
30
24
|
end
|
31
25
|
end
|
32
26
|
end
|
27
|
+
|
28
|
+
# == Schema Information
|
29
|
+
#
|
30
|
+
# Table name: oauth_clients
|
31
|
+
#
|
32
|
+
# id :uuid not null, primary key
|
33
|
+
# name :string not null
|
34
|
+
# secret :string not null
|
35
|
+
# identifier :string not null
|
36
|
+
# created_at :datetime not null
|
37
|
+
# updated_at :datetime not null
|
38
|
+
#
|
39
|
+
# Indexes
|
40
|
+
#
|
41
|
+
# index_oauth_clients_on_identifier (identifier) UNIQUE
|
42
|
+
#
|