osso 0.0.3.8 → 0.0.3.13

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/.buildkite/pipeline.yml +5 -3
  3. data/Gemfile.lock +5 -1
  4. data/bin/annotate +1 -0
  5. data/db/schema.rb +9 -43
  6. data/lib/osso/db/migrate/20200723153750_add_missing_timestamps.rb +35 -0
  7. data/lib/osso/db/migrate/20200723162228_drop_unneeded_tables.rb +9 -0
  8. data/lib/osso/graphql/mutation.rb +7 -1
  9. data/lib/osso/graphql/mutations.rb +5 -1
  10. data/lib/osso/graphql/mutations/configure_identity_provider.rb +1 -1
  11. data/lib/osso/graphql/mutations/create_oauth_client.rb +30 -0
  12. data/lib/osso/graphql/mutations/delete_enterprise_account.rb +34 -0
  13. data/lib/osso/graphql/mutations/delete_oauth_client.rb +30 -0
  14. data/lib/osso/graphql/mutations/regenerate_oauth_credentials.rb +31 -0
  15. data/lib/osso/graphql/mutations/set_redirect_uris.rb +54 -0
  16. data/lib/osso/graphql/query.rb +15 -2
  17. data/lib/osso/graphql/resolvers/enterprise_accounts.rb +12 -4
  18. data/lib/osso/graphql/resolvers/oauth_clients.rb +1 -1
  19. data/lib/osso/graphql/types.rb +3 -0
  20. data/lib/osso/graphql/types/base_connection.rb +15 -0
  21. data/lib/osso/graphql/types/base_object.rb +4 -0
  22. data/lib/osso/graphql/types/oauth_client.rb +14 -1
  23. data/lib/osso/graphql/types/redirect_uri.rb +23 -0
  24. data/lib/osso/graphql/types/redirect_uri_input.rb +16 -0
  25. data/lib/osso/helpers/auth.rb +13 -12
  26. data/lib/osso/models/access_token.rb +18 -0
  27. data/lib/osso/models/authorization_code.rb +20 -0
  28. data/lib/osso/models/enterprise_account.rb +20 -0
  29. data/lib/osso/models/identity_provider.rb +22 -1
  30. data/lib/osso/models/models.rb +2 -0
  31. data/lib/osso/models/oauth_client.rb +20 -6
  32. data/lib/osso/models/redirect_uri.rb +17 -0
  33. data/lib/osso/models/user.rb +22 -0
  34. data/lib/osso/routes/admin.rb +6 -0
  35. data/lib/osso/routes/auth.rb +2 -2
  36. data/lib/osso/version.rb +1 -1
  37. data/osso-rb.gemspec +1 -0
  38. data/spec/factories/identity_providers.rb +22 -0
  39. data/spec/graphql/mutations/configure_identity_provider_spec.rb +1 -1
  40. data/spec/graphql/mutations/create_oauth_client_spec.rb +55 -0
  41. data/spec/graphql/mutations/delete_enterprise_account_spec.rb +63 -0
  42. data/spec/graphql/mutations/delete_oauth_client_spec.rb +51 -0
  43. data/spec/graphql/query/enterprise_accounts_spec.rb +32 -18
  44. data/spec/graphql/query/identity_provider_spec.rb +1 -1
  45. data/spec/graphql/query/{oauth_clients_account_spec.rb → oauth_clients_spec.rb} +2 -0
  46. data/spec/routes/auth_spec.rb +25 -0
  47. metadata +32 -8
  48. data/lib/osso/db/migrate/20200328143303_create_oauth_tables.rb +0 -57
  49. data/lib/osso/graphql/mutations/set_identity_provider.rb +0 -27
  50. data/lib/osso/models/saml_provider.rb +0 -49
  51. data/lib/osso/models/saml_providers/azure_saml_provider.rb +0 -22
  52. data/lib/osso/models/saml_providers/okta_saml_provider.rb +0 -23
@@ -4,12 +4,20 @@ module Osso
4
4
  module GraphQL
5
5
  module Resolvers
6
6
  class EnterpriseAccounts < ::GraphQL::Schema::Resolver
7
- type [Types::EnterpriseAccount], null: true
7
+ type Types::EnterpriseAccount.connection_type, null: true
8
8
 
9
- def resolve
10
- return Osso::Models::EnterpriseAccount.all if context[:scope] == :admin
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
- Array(Osso::Models::EnterpriseAccount.find_by(domain: context[:scope]))
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
@@ -4,7 +4,7 @@ module Osso
4
4
  module GraphQL
5
5
  module Resolvers
6
6
  class OAuthClients < ::GraphQL::Schema::Resolver
7
- type [Types::OAuthClient], null: true
7
+ type [Types::OauthClient], null: true
8
8
 
9
9
  def resolve
10
10
  return Osso::Models::OauthClient.all if context[:scope] == :admin
@@ -5,6 +5,7 @@ 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'
@@ -12,5 +13,7 @@ require_relative 'types/identity_provider_service'
12
13
  require_relative 'types/identity_provider_status'
13
14
  require_relative 'types/identity_provider'
14
15
  require_relative 'types/enterprise_account'
16
+ require_relative 'types/redirect_uri'
17
+ require_relative 'types/redirect_uri_input'
15
18
  require_relative 'types/oauth_client'
16
19
  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
@@ -5,7 +5,7 @@ require 'graphql'
5
5
  module Osso
6
6
  module GraphQL
7
7
  module Types
8
- class OAuthClient < Types::BaseObject
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
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'graphql'
4
+
5
+ module Osso
6
+ module GraphQL
7
+ module Types
8
+ class RedirectUrisInput < Types::BaseInputObject
9
+ description 'Attributes for creating or updating a collection of redirect URIs for an Oauth Client'
10
+ argument :id, ID, 'Database ID', required: false
11
+ argument :uri, String, 'URI value', required: true
12
+ argument :primary, Boolean, 'Whether the URI is the primary uri used in IDP initiated login', required: true
13
+ end
14
+ end
15
+ end
16
+ end
@@ -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 = JWT.decode(
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 = JWT.decode(
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
+ #
@@ -10,7 +10,6 @@ module Osso
10
10
  has_many :users
11
11
  before_save :set_status
12
12
 
13
-
14
13
  def name
15
14
  service.titlecase
16
15
  # raise(
@@ -54,3 +53,25 @@ module Osso
54
53
  end
55
54
  end
56
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
+ #
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # -*- SkipSchemaAnnotations
4
+
3
5
  require 'sinatra/activerecord'
4
6
 
5
7
  module Osso
@@ -9,11 +9,11 @@ module Osso
9
9
  has_many :identity_providers
10
10
  has_many :redirect_uris
11
11
 
12
- before_validation :setup, on: :create
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 default_redirect_uri
16
+ def primary_redirect_uri
17
17
  redirect_uris.find(&:primary)
18
18
  end
19
19
 
@@ -21,12 +21,26 @@ module Osso
21
21
  redirect_uris.map(&:uri)
22
22
  end
23
23
 
24
- private
25
-
26
- def setup
24
+ def generate_secrets
27
25
  self.identifier = SecureRandom.hex(16)
28
- self.secret = SecureRandom.hex(64)
26
+ self.secret = SecureRandom.hex(32)
29
27
  end
30
28
  end
31
29
  end
32
30
  end
31
+
32
+ # == Schema Information
33
+ #
34
+ # Table name: oauth_clients
35
+ #
36
+ # id :uuid not null, primary key
37
+ # name :string not null
38
+ # secret :string not null
39
+ # identifier :string not null
40
+ # created_at :datetime not null
41
+ # updated_at :datetime not null
42
+ #
43
+ # Indexes
44
+ #
45
+ # index_oauth_clients_on_identifier (identifier) UNIQUE
46
+ #
@@ -18,3 +18,20 @@ module Osso
18
18
  end
19
19
  end
20
20
  end
21
+
22
+ # == Schema Information
23
+ #
24
+ # Table name: redirect_uris
25
+ #
26
+ # id :uuid not null, primary key
27
+ # uri :string not null
28
+ # primary :boolean default(FALSE), not null
29
+ # oauth_client_id :uuid
30
+ # created_at :datetime not null
31
+ # updated_at :datetime not null
32
+ #
33
+ # Indexes
34
+ #
35
+ # index_redirect_uris_on_oauth_client_id (oauth_client_id)
36
+ # index_redirect_uris_on_uri_and_primary (uri,primary) UNIQUE
37
+ #
@@ -22,3 +22,25 @@ module Osso
22
22
  end
23
23
  end
24
24
  end
25
+
26
+ # == Schema Information
27
+ #
28
+ # Table name: users
29
+ #
30
+ # id :uuid not null, primary key
31
+ # email :string not null
32
+ # idp_id :string not null
33
+ # identity_provider_id :uuid
34
+ # enterprise_account_id :uuid
35
+ # created_at :datetime not null
36
+ # updated_at :datetime not null
37
+ #
38
+ # Indexes
39
+ #
40
+ # index_users_on_email_and_idp_id (email,idp_id) UNIQUE
41
+ # index_users_on_enterprise_account_id (enterprise_account_id)
42
+ #
43
+ # Foreign Keys
44
+ #
45
+ # fk_rails_... (identity_provider_id => identity_providers.id)
46
+ #
@@ -36,6 +36,12 @@ module Osso
36
36
 
37
37
  erb :admin
38
38
  end
39
+
40
+ get '/config/:id' do
41
+ admin_protected!
42
+
43
+ erb :admin
44
+ end
39
45
  end
40
46
  end
41
47
  end
@@ -23,7 +23,7 @@ module Osso
23
23
  self,
24
24
  provider_name: 'saml',
25
25
  identity_provider_id_regex: UUID_REGEXP,
26
- path_prefix: '/saml',
26
+ path_prefix: '/auth/saml',
27
27
  callback_suffix: 'callback',
28
28
  ) do |identity_provider_id, _env|
29
29
  provider = Models::IdentityProvider.find(identity_provider_id)
@@ -40,7 +40,7 @@ module Osso
40
40
  post '/saml/:id/callback' do
41
41
  provider = Models::IdentityProvider.find(params[:id])
42
42
  oauth_client = provider.oauth_client
43
- redirect_uri = env['redirect_uri'] || oauth_client.default_redirect_uri.uri
43
+ redirect_uri = env['redirect_uri'] || oauth_client.primary_redirect_uri.uri
44
44
 
45
45
  attributes = env['omniauth.auth']&.
46
46
  extra&.
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Osso
4
- VERSION = '0.0.3.8'
4
+ VERSION = '0.0.3.13'
5
5
  end