osso 0.0.3.25 → 0.0.5.pre.beta
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/.ruby-version +1 -0
- data/Gemfile.lock +16 -18
- data/db/schema.rb +2 -2
- data/lib/osso/db/migrate/20200714223226_add_identity_provider_service_enum.rb +10 -14
- data/lib/osso/db/migrate/20200913154919_add_one_login_to_identity_provider_service_enum.rb +28 -0
- data/lib/osso/db/migrate/20200916125543_add_google_to_identity_provider_service_enum.rb +28 -0
- data/lib/osso/graphql/mutations/base_mutation.rb +17 -2
- data/lib/osso/graphql/mutations/configure_identity_provider.rb +2 -3
- data/lib/osso/graphql/mutations/create_enterprise_account.rb +1 -1
- data/lib/osso/graphql/mutations/create_identity_provider.rb +1 -1
- data/lib/osso/graphql/mutations/create_oauth_client.rb +1 -1
- data/lib/osso/graphql/mutations/delete_enterprise_account.rb +1 -1
- data/lib/osso/graphql/mutations/delete_oauth_client.rb +1 -1
- data/lib/osso/graphql/mutations/regenerate_oauth_credentials.rb +1 -1
- data/lib/osso/graphql/mutations/set_redirect_uris.rb +4 -4
- data/lib/osso/graphql/mutations/update_app_config.rb +1 -1
- data/lib/osso/graphql/types.rb +1 -0
- data/lib/osso/graphql/types/error.rb +20 -0
- data/lib/osso/graphql/types/identity_provider.rb +0 -5
- data/lib/osso/graphql/types/identity_provider_service.rb +4 -2
- data/lib/osso/models/identity_provider.rb +27 -1
- data/lib/osso/routes/auth.rb +3 -3
- data/lib/osso/version.rb +1 -1
- data/spec/factories/identity_providers.rb +2 -0
- data/spec/graphql/mutations/configure_identity_provider_spec.rb +1 -1
- data/spec/models/identity_provider_spec.rb +23 -1
- data/spec/routes/auth_spec.rb +26 -0
- data/spec/spec_helper.rb +13 -0
- data/spec/support/fixtures/test.pem +30 -0
- metadata +9 -7
- data/spec/models/azure_saml_provider_spec.rb +0 -19
- data/spec/models/okta_saml_provider_spec.rb +0 -20
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e2f9a55978dad2e0b1829183ff8c023a4a9981c9403e4fb7b7fce0448bd553d9
|
|
4
|
+
data.tar.gz: 3355b2e9c7ebe56afbe62ad678c2bda13ab7d924ae8e341511763df8683ece81
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f8128ec3cd5ae5111ebe6fab2af92fd8fd5b7e1c5b4f10b2c72867b1bc6dd8465207f4376f264c70a2d75aab7cef2385f905d8597f25fed6557a70bab0b807ef
|
|
7
|
+
data.tar.gz: b0f6199724d71b0cd3b6c21d1b2194cf5ce731c896b84d1be0f1558d5bffaa69b58196487f60a68559404488a1da8cac55b09262bf6c822f4ce5492c7f271a60
|
data/.ruby-version
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
2.6.6
|
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
osso (0.0.
|
|
4
|
+
osso (0.0.5.pre.alpha)
|
|
5
5
|
activesupport (>= 6.0.3.2)
|
|
6
6
|
graphql
|
|
7
7
|
jwt
|
|
@@ -31,14 +31,13 @@ GEM
|
|
|
31
31
|
zeitwerk (~> 2.2, >= 2.2.2)
|
|
32
32
|
addressable (2.7.0)
|
|
33
33
|
public_suffix (>= 2.0.2, < 5.0)
|
|
34
|
-
aes_key_wrap (1.0
|
|
34
|
+
aes_key_wrap (1.1.0)
|
|
35
35
|
annotate (3.1.1)
|
|
36
36
|
activerecord (>= 3.2, < 7.0)
|
|
37
37
|
rake (>= 10.4, < 14.0)
|
|
38
38
|
ast (2.4.1)
|
|
39
39
|
attr_required (1.0.1)
|
|
40
|
-
|
|
41
|
-
bindata (2.4.7)
|
|
40
|
+
bindata (2.4.8)
|
|
42
41
|
coderay (1.1.3)
|
|
43
42
|
concurrent-ruby (1.1.6)
|
|
44
43
|
crack (0.4.3)
|
|
@@ -53,7 +52,7 @@ GEM
|
|
|
53
52
|
activesupport (>= 5.0.0)
|
|
54
53
|
faker (2.13.0)
|
|
55
54
|
i18n (>= 1.6, < 2)
|
|
56
|
-
graphql (1.11.
|
|
55
|
+
graphql (1.11.4)
|
|
57
56
|
hashdiff (1.0.1)
|
|
58
57
|
hashie (4.1.0)
|
|
59
58
|
httpclient (2.8.3)
|
|
@@ -64,23 +63,23 @@ GEM
|
|
|
64
63
|
activesupport (>= 4.2)
|
|
65
64
|
aes_key_wrap
|
|
66
65
|
bindata
|
|
67
|
-
jwt (2.2.
|
|
66
|
+
jwt (2.2.2)
|
|
68
67
|
method_source (1.0.0)
|
|
69
68
|
mini_portile2 (2.4.0)
|
|
70
69
|
minitest (5.14.1)
|
|
71
70
|
multi_json (1.15.0)
|
|
72
71
|
mustermann (1.1.1)
|
|
73
72
|
ruby2_keywords (~> 0.0.1)
|
|
74
|
-
nokogiri (1.10.
|
|
73
|
+
nokogiri (1.10.10)
|
|
75
74
|
mini_portile2 (~> 2.4.0)
|
|
76
75
|
omniauth (1.9.1)
|
|
77
76
|
hashie (>= 3.4.6)
|
|
78
77
|
rack (>= 1.6.2, < 3)
|
|
79
78
|
omniauth-multi-provider (0.2.1)
|
|
80
79
|
omniauth
|
|
81
|
-
omniauth-saml (1.10.
|
|
80
|
+
omniauth-saml (1.10.2)
|
|
82
81
|
omniauth (~> 1.3, >= 1.3.2)
|
|
83
|
-
ruby-saml (~> 1.
|
|
82
|
+
ruby-saml (~> 1.9)
|
|
84
83
|
parallel (1.19.2)
|
|
85
84
|
parser (2.7.1.4)
|
|
86
85
|
ast (~> 2.4.1)
|
|
@@ -92,13 +91,13 @@ GEM
|
|
|
92
91
|
rack (2.2.3)
|
|
93
92
|
rack-contrib (2.2.0)
|
|
94
93
|
rack (~> 2.0)
|
|
95
|
-
rack-oauth2 (1.
|
|
94
|
+
rack-oauth2 (1.16.0)
|
|
96
95
|
activesupport
|
|
97
96
|
attr_required
|
|
98
97
|
httpclient
|
|
99
98
|
json-jwt (>= 1.11.0)
|
|
100
99
|
rack (>= 2.1.0)
|
|
101
|
-
rack-protection (2.0
|
|
100
|
+
rack-protection (2.1.0)
|
|
102
101
|
rack
|
|
103
102
|
rack-test (1.1.0)
|
|
104
103
|
rack (>= 1.0, < 3)
|
|
@@ -140,20 +139,19 @@ GEM
|
|
|
140
139
|
json (>= 1.8, < 3)
|
|
141
140
|
simplecov-html (~> 0.10.0)
|
|
142
141
|
simplecov-html (0.10.2)
|
|
143
|
-
sinatra (2.0
|
|
142
|
+
sinatra (2.1.0)
|
|
144
143
|
mustermann (~> 1.0)
|
|
145
|
-
rack (~> 2.
|
|
146
|
-
rack-protection (= 2.0
|
|
144
|
+
rack (~> 2.2)
|
|
145
|
+
rack-protection (= 2.1.0)
|
|
147
146
|
tilt (~> 2.0)
|
|
148
147
|
sinatra-activerecord (2.0.18)
|
|
149
148
|
activerecord (>= 4.1)
|
|
150
149
|
sinatra (>= 1.0)
|
|
151
|
-
sinatra-contrib (2.0
|
|
152
|
-
backports (>= 2.8.2)
|
|
150
|
+
sinatra-contrib (2.1.0)
|
|
153
151
|
multi_json
|
|
154
152
|
mustermann (~> 1.0)
|
|
155
|
-
rack-protection (= 2.0
|
|
156
|
-
sinatra (= 2.0
|
|
153
|
+
rack-protection (= 2.1.0)
|
|
154
|
+
sinatra (= 2.1.0)
|
|
157
155
|
tilt (~> 2.0)
|
|
158
156
|
thread_safe (0.3.6)
|
|
159
157
|
tilt (2.0.10)
|
data/db/schema.rb
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
#
|
|
11
11
|
# It's strongly recommended that you check this file into your version control system.
|
|
12
12
|
|
|
13
|
-
ActiveRecord::Schema.define(version:
|
|
13
|
+
ActiveRecord::Schema.define(version: 2020_09_13_154919) do
|
|
14
14
|
|
|
15
15
|
# These are extensions that must be enabled in order to support this database
|
|
16
16
|
enable_extension "pgcrypto"
|
|
@@ -62,7 +62,7 @@ ActiveRecord::Schema.define(version: 2020_08_26_201852) do
|
|
|
62
62
|
end
|
|
63
63
|
|
|
64
64
|
# Could not dump table "identity_providers" because of following StandardError
|
|
65
|
-
# Unknown type '
|
|
65
|
+
# Unknown type 'identity_provider_service' for column 'service'
|
|
66
66
|
|
|
67
67
|
create_table "oauth_clients", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
|
|
68
68
|
t.string "name", null: false
|
|
@@ -1,17 +1,13 @@
|
|
|
1
1
|
class AddIdentityProviderServiceEnum < ActiveRecord::Migration[6.0]
|
|
2
|
-
def
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
execute <<-SQL
|
|
13
|
-
DROP TYPE identity_provider_service;
|
|
14
|
-
SQL
|
|
15
|
-
end
|
|
2
|
+
def up
|
|
3
|
+
execute "CREATE TYPE identity_provider_service AS ENUM ('OKTA', 'AZURE');"
|
|
4
|
+
change_column :identity_providers, :service, 'identity_provider_service USING CAST(service as identity_provider_service)'
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def down
|
|
8
|
+
chnage_column :identity_providers, :service, :text
|
|
9
|
+
execute <<-SQL
|
|
10
|
+
DROP TYPE identity_provider_service;
|
|
11
|
+
SQL
|
|
16
12
|
end
|
|
17
13
|
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
class AddOneLoginToIdentityProviderServiceEnum < ActiveRecord::Migration[6.0]
|
|
2
|
+
disable_ddl_transaction!
|
|
3
|
+
|
|
4
|
+
def up
|
|
5
|
+
execute <<-SQL
|
|
6
|
+
ALTER TYPE identity_provider_service ADD VALUE 'ONELOGIN';
|
|
7
|
+
SQL
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def down
|
|
11
|
+
execute <<~SQL
|
|
12
|
+
CREATE TYPE identity_provider_service_new AS ENUM ('AZURE', 'OKTA');
|
|
13
|
+
|
|
14
|
+
-- Remove values that won't be compatible with new definition
|
|
15
|
+
DELETE FROM identity_providers WHERE service = 'ONELOGIN';
|
|
16
|
+
|
|
17
|
+
-- Convert to new type, casting via text representation
|
|
18
|
+
ALTER TABLE identity_providers
|
|
19
|
+
ALTER COLUMN service TYPE identity_provider_service_new
|
|
20
|
+
USING (service::text::identity_provider_service_new);
|
|
21
|
+
|
|
22
|
+
-- and swap the types
|
|
23
|
+
DROP TYPE identity_provider_service;
|
|
24
|
+
|
|
25
|
+
ALTER TYPE identity_provider_service_new RENAME TO identity_provider_service;
|
|
26
|
+
SQL
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
class AddGoogleToIdentityProviderServiceEnum < ActiveRecord::Migration[6.0]
|
|
2
|
+
disable_ddl_transaction!
|
|
3
|
+
|
|
4
|
+
def up
|
|
5
|
+
execute <<-SQL
|
|
6
|
+
ALTER TYPE identity_provider_service ADD VALUE 'GOOGLE';
|
|
7
|
+
SQL
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def down
|
|
11
|
+
execute <<~SQL
|
|
12
|
+
CREATE TYPE identity_provider_service_new AS ENUM ('AZURE', 'OKTA', 'ONELOGIN');
|
|
13
|
+
|
|
14
|
+
-- Remove values that won't be compatible with new definition
|
|
15
|
+
DELETE FROM identity_providers WHERE service = 'GOOGLE';
|
|
16
|
+
|
|
17
|
+
-- Convert to new type, casting via text representation
|
|
18
|
+
ALTER TABLE identity_providers
|
|
19
|
+
ALTER COLUMN service TYPE identity_provider_service_new
|
|
20
|
+
USING (service::text::identity_provider_service_new);
|
|
21
|
+
|
|
22
|
+
-- and swap the types
|
|
23
|
+
DROP TYPE identity_provider_service;
|
|
24
|
+
|
|
25
|
+
ALTER TYPE identity_provider_service_new RENAME TO identity_provider_service;
|
|
26
|
+
SQL
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -11,8 +11,23 @@ module Osso
|
|
|
11
11
|
data.merge(errors: [])
|
|
12
12
|
end
|
|
13
13
|
|
|
14
|
-
def response_error(
|
|
15
|
-
|
|
14
|
+
def response_error(errors)
|
|
15
|
+
raise ::GraphQL::ExecutionError.new(
|
|
16
|
+
'Mutation error',
|
|
17
|
+
extensions: {
|
|
18
|
+
'errors' => field_errors(errors),
|
|
19
|
+
},
|
|
20
|
+
)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def field_errors(errors)
|
|
24
|
+
errors.map do |attribute, messages|
|
|
25
|
+
attribute = attribute.to_s.camelize(:lower)
|
|
26
|
+
{
|
|
27
|
+
attribute: attribute,
|
|
28
|
+
message: messages,
|
|
29
|
+
}
|
|
30
|
+
end
|
|
16
31
|
end
|
|
17
32
|
|
|
18
33
|
def ready?(**args)
|
|
@@ -10,15 +10,14 @@ module Osso
|
|
|
10
10
|
argument :sso_url, String, required: false
|
|
11
11
|
argument :sso_cert, String, required: false
|
|
12
12
|
|
|
13
|
-
field :identity_provider, Types::IdentityProvider, null:
|
|
14
|
-
field :errors, [String], null: false
|
|
13
|
+
field :identity_provider, Types::IdentityProvider, null: true
|
|
15
14
|
|
|
16
15
|
def resolve(**args)
|
|
17
16
|
provider = identity_provider(**args)
|
|
18
17
|
|
|
19
18
|
return response_data(identity_provider: provider) if provider.update(args)
|
|
20
19
|
|
|
21
|
-
response_error(
|
|
20
|
+
response_error(provider.errors)
|
|
22
21
|
end
|
|
23
22
|
|
|
24
23
|
def domain(**args)
|
|
@@ -19,7 +19,7 @@ module Osso
|
|
|
19
19
|
|
|
20
20
|
return response_data(enterprise_account: enterprise_account) if enterprise_account.save
|
|
21
21
|
|
|
22
|
-
response_error(
|
|
22
|
+
response_error(enterprise_account.errors)
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
def find_client_db_id(oauth_client_identifier)
|
|
@@ -20,7 +20,7 @@ module Osso
|
|
|
20
20
|
|
|
21
21
|
response_data(oauth_client: oauth_client.reload)
|
|
22
22
|
rescue StandardError => e
|
|
23
|
-
response_error(
|
|
23
|
+
response_error(e)
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
def ready?(*)
|
|
@@ -33,17 +33,17 @@ module Osso
|
|
|
33
33
|
|
|
34
34
|
if updating_index
|
|
35
35
|
updating = redirect_uris.delete_at(updating_index)
|
|
36
|
-
redirect.update(updating.to_h)
|
|
36
|
+
redirect.update!(updating.to_h)
|
|
37
37
|
next
|
|
38
38
|
end
|
|
39
39
|
|
|
40
|
-
redirect.destroy
|
|
40
|
+
redirect.destroy!
|
|
41
41
|
end
|
|
42
42
|
end
|
|
43
43
|
|
|
44
44
|
def create_new(oauth_client, redirect_uris)
|
|
45
45
|
redirect_uris.map do |uri|
|
|
46
|
-
oauth_client.redirect_uris.create(uri.to_h.without(:id))
|
|
46
|
+
oauth_client.redirect_uris.create!(uri.to_h.without(:id))
|
|
47
47
|
end
|
|
48
48
|
end
|
|
49
49
|
end
|
data/lib/osso/graphql/types.rb
CHANGED
|
@@ -11,6 +11,7 @@ require_relative 'types/base_enum'
|
|
|
11
11
|
require_relative 'types/base_input_object'
|
|
12
12
|
require_relative 'types/admin_user'
|
|
13
13
|
require_relative 'types/app_config'
|
|
14
|
+
require_relative 'types/error'
|
|
14
15
|
require_relative 'types/identity_provider_service'
|
|
15
16
|
require_relative 'types/identity_provider_status'
|
|
16
17
|
require_relative 'types/identity_provider'
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'graphql'
|
|
4
|
+
|
|
5
|
+
module Osso
|
|
6
|
+
module GraphQL
|
|
7
|
+
module Types
|
|
8
|
+
class Error < Types::BaseObject
|
|
9
|
+
description 'A mutation error'
|
|
10
|
+
|
|
11
|
+
field :attribute, String, null: false
|
|
12
|
+
field :message, String, null: false
|
|
13
|
+
|
|
14
|
+
def self.authorized?(_object, _context)
|
|
15
|
+
true
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -16,11 +16,6 @@ module Osso
|
|
|
16
16
|
field :sso_url, String, null: true
|
|
17
17
|
field :sso_cert, String, null: true
|
|
18
18
|
field :status, Types::IdentityProviderStatus, null: false
|
|
19
|
-
field :documentation_pdf_url, String, null: true
|
|
20
|
-
|
|
21
|
-
def documentation_pdf_url
|
|
22
|
-
ENV['BASE_URL'] + '/identity_provider/documentation/' + @object.id
|
|
23
|
-
end
|
|
24
19
|
end
|
|
25
20
|
end
|
|
26
21
|
end
|
|
@@ -4,8 +4,10 @@ module Osso
|
|
|
4
4
|
module GraphQL
|
|
5
5
|
module Types
|
|
6
6
|
class IdentityProviderService < BaseEnum
|
|
7
|
-
value('AZURE', 'Microsoft Azure Identity Provider', value: '
|
|
8
|
-
value('OKTA', 'Okta Identity Provider', value: '
|
|
7
|
+
value('AZURE', 'Microsoft Azure Identity Provider', value: 'AZURE')
|
|
8
|
+
value('OKTA', 'Okta Identity Provider', value: 'OKTA')
|
|
9
|
+
value('ONELOGIN', 'OneLogin Identity Provider', value: 'ONELOGIN')
|
|
10
|
+
value('GOOGLE', 'Google SAML Identity Provider', value: 'GOOGLE')
|
|
9
11
|
end
|
|
10
12
|
end
|
|
11
13
|
end
|
|
@@ -4,11 +4,14 @@ module Osso
|
|
|
4
4
|
module Models
|
|
5
5
|
# Base class for SAML Providers
|
|
6
6
|
class IdentityProvider < ActiveRecord::Base
|
|
7
|
-
NAME_FORMAT = 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress'
|
|
8
7
|
belongs_to :enterprise_account
|
|
9
8
|
belongs_to :oauth_client
|
|
10
9
|
has_many :users
|
|
11
10
|
before_save :set_status
|
|
11
|
+
validate :sso_cert_valid
|
|
12
|
+
|
|
13
|
+
PEM_HEADER = "-----BEGIN CERTIFICATE-----\n"
|
|
14
|
+
PEM_FOOTER = "\n-----END CERTIFICATE-----"
|
|
12
15
|
|
|
13
16
|
def name
|
|
14
17
|
service.titlecase
|
|
@@ -41,11 +44,34 @@ module Osso
|
|
|
41
44
|
self.status = 'CONFIGURED' if sso_url && sso_cert
|
|
42
45
|
end
|
|
43
46
|
|
|
47
|
+
def active!
|
|
48
|
+
update(status: 'ACTIVE')
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def error!
|
|
52
|
+
update(status: 'ERROR')
|
|
53
|
+
end
|
|
54
|
+
|
|
44
55
|
def root_url
|
|
45
56
|
return "https://#{ENV['HEROKU_APP_NAME']}.herokuapp.com" if ENV['HEROKU_APP_NAME']
|
|
46
57
|
|
|
47
58
|
ENV.fetch('BASE_URL')
|
|
48
59
|
end
|
|
60
|
+
|
|
61
|
+
def sso_cert_valid
|
|
62
|
+
return if sso_cert.blank?
|
|
63
|
+
|
|
64
|
+
has_header_and_footer = sso_cert.match(/#{PEM_HEADER}(?<cert>.*)#{PEM_FOOTER}/m)
|
|
65
|
+
|
|
66
|
+
if has_header_and_footer
|
|
67
|
+
OpenSSL::X509::Certificate.new(sso_cert)
|
|
68
|
+
self.sso_cert = has_header_and_footer[:cert]
|
|
69
|
+
else
|
|
70
|
+
OpenSSL::X509::Certificate.new([PEM_HEADER, sso_cert, PEM_FOOTER].join)
|
|
71
|
+
end
|
|
72
|
+
rescue OpenSSL::X509::CertificateError
|
|
73
|
+
errors.add(:sso_cert, 'x509 Certificate is malformed')
|
|
74
|
+
end
|
|
49
75
|
end
|
|
50
76
|
end
|
|
51
77
|
end
|
data/lib/osso/routes/auth.rb
CHANGED
|
@@ -41,6 +41,7 @@ module Osso
|
|
|
41
41
|
provider = Models::IdentityProvider.find(params[:id])
|
|
42
42
|
@oauth_client = provider.oauth_client
|
|
43
43
|
|
|
44
|
+
# TODO: PORC for validating attributes
|
|
44
45
|
attributes = env['omniauth.auth']&.
|
|
45
46
|
extra&.
|
|
46
47
|
response_object&.
|
|
@@ -48,7 +49,7 @@ module Osso
|
|
|
48
49
|
|
|
49
50
|
user = Models::User.where(
|
|
50
51
|
email: attributes[:email],
|
|
51
|
-
idp_id: attributes[:id],
|
|
52
|
+
idp_id: attributes[:id] || attributes[:idp_id],
|
|
52
53
|
).first_or_create! do |new_user|
|
|
53
54
|
new_user.enterprise_account_id = provider.enterprise_account_id
|
|
54
55
|
new_user.identity_provider_id = provider.id
|
|
@@ -58,8 +59,7 @@ module Osso
|
|
|
58
59
|
oauth_client: @oauth_client,
|
|
59
60
|
redirect_uri: redirect_uri,
|
|
60
61
|
)
|
|
61
|
-
|
|
62
|
-
# Mark IDP as active
|
|
62
|
+
provider.active!
|
|
63
63
|
|
|
64
64
|
redirect(redirect_uri + "?code=#{CGI.escape(authorization_code.token)}&state=#{provider_state}")
|
|
65
65
|
end
|
data/lib/osso/version.rb
CHANGED
|
@@ -5,6 +5,7 @@ FactoryBot.define do
|
|
|
5
5
|
id { SecureRandom.uuid }
|
|
6
6
|
domain { Faker::Internet.domain_name }
|
|
7
7
|
oauth_client
|
|
8
|
+
status { 'PENDING' }
|
|
8
9
|
|
|
9
10
|
factory :okta_identity_provider, parent: :identity_provider do
|
|
10
11
|
service { 'OKTA' }
|
|
@@ -21,6 +22,7 @@ FactoryBot.define do
|
|
|
21
22
|
end
|
|
22
23
|
|
|
23
24
|
factory :configured_identity_provider, parent: :identity_provider do
|
|
25
|
+
status { 'CONFIGURED' }
|
|
24
26
|
sso_cert do
|
|
25
27
|
<<~CERT
|
|
26
28
|
-----BEGIN CERTIFICATE-----
|
|
@@ -7,10 +7,11 @@ describe Osso::Models::IdentityProvider do
|
|
|
7
7
|
|
|
8
8
|
describe '#assertion_consumer_service_url' do
|
|
9
9
|
it 'returns the expected URI for BASE_URL' do
|
|
10
|
+
ENV['HEROKU_APP_NAME'] = nil
|
|
10
11
|
ENV['BASE_URL'] = 'https://example.com'
|
|
11
12
|
|
|
12
13
|
expect(subject.assertion_consumer_service_url).to eq(
|
|
13
|
-
"
|
|
14
|
+
"#{ENV['BASE_URL']}/auth/saml/#{subject.id}/callback",
|
|
14
15
|
)
|
|
15
16
|
end
|
|
16
17
|
|
|
@@ -34,4 +35,25 @@ describe Osso::Models::IdentityProvider do
|
|
|
34
35
|
)
|
|
35
36
|
end
|
|
36
37
|
end
|
|
38
|
+
|
|
39
|
+
describe '#validate_sso_cert' do
|
|
40
|
+
it 'rejects an invalid cert' do
|
|
41
|
+
subject.update(sso_cert: 'bad-cert')
|
|
42
|
+
|
|
43
|
+
expect(subject.errors.full_messages.first).to include('x509 Certificate is malformed')
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it 'massages a cert with header and footer' do
|
|
47
|
+
subject.update(sso_cert: valid_x509_pem)
|
|
48
|
+
|
|
49
|
+
expect(subject.errors).to be_empty
|
|
50
|
+
expect(subject.sso_cert).to_not include('BEGIN CERTIFICATE')
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it 'accepts a cert without header and footer' do
|
|
54
|
+
subject.update(sso_cert: raw_x509_string)
|
|
55
|
+
|
|
56
|
+
expect(subject.errors).to be_empty
|
|
57
|
+
end
|
|
58
|
+
end
|
|
37
59
|
end
|
data/spec/routes/auth_spec.rb
CHANGED
|
@@ -104,6 +104,17 @@ describe Osso::Auth do
|
|
|
104
104
|
)
|
|
105
105
|
end.to_not(change { Osso::Models::User.count })
|
|
106
106
|
end
|
|
107
|
+
it 'marks the provider as ACTIVE' do
|
|
108
|
+
post(
|
|
109
|
+
"/auth/saml/#{okta_provider.id}/callback",
|
|
110
|
+
nil,
|
|
111
|
+
{
|
|
112
|
+
'omniauth.auth' => OmniAuth.config.mock_auth[:saml],
|
|
113
|
+
'identity_provider' => okta_provider,
|
|
114
|
+
},
|
|
115
|
+
)
|
|
116
|
+
expect(okta_provider.reload.status).to eq('ACTIVE')
|
|
117
|
+
end
|
|
107
118
|
end
|
|
108
119
|
end
|
|
109
120
|
|
|
@@ -126,6 +137,21 @@ describe Osso::Auth do
|
|
|
126
137
|
)
|
|
127
138
|
end.to change { Osso::Models::User.count }.by(1)
|
|
128
139
|
end
|
|
140
|
+
|
|
141
|
+
it 'marks the provider ACTIVE' do
|
|
142
|
+
mock_saml_omniauth
|
|
143
|
+
|
|
144
|
+
post(
|
|
145
|
+
"/auth/saml/#{azure_provider.id}/callback",
|
|
146
|
+
nil,
|
|
147
|
+
{
|
|
148
|
+
'omniauth.auth' => OmniAuth.config.mock_auth[:saml],
|
|
149
|
+
'identity_provider' => azure_provider,
|
|
150
|
+
},
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
expect(azure_provider.reload.status).to eq('ACTIVE')
|
|
154
|
+
end
|
|
129
155
|
end
|
|
130
156
|
|
|
131
157
|
describe 'on subsequent authentications' do
|
data/spec/spec_helper.rb
CHANGED
|
@@ -21,6 +21,9 @@ require File.expand_path '../lib/osso.rb', __dir__
|
|
|
21
21
|
require File.expand_path 'support/spec_app', __dir__
|
|
22
22
|
|
|
23
23
|
module RSpecMixin
|
|
24
|
+
PEM_HEADER = "-----BEGIN CERTIFICATE-----\n"
|
|
25
|
+
PEM_FOOTER = "\n-----END CERTIFICATE-----"
|
|
26
|
+
|
|
24
27
|
include Rack::Test::Methods
|
|
25
28
|
|
|
26
29
|
def app
|
|
@@ -46,6 +49,16 @@ module RSpecMixin
|
|
|
46
49
|
def spec_views
|
|
47
50
|
File.dirname(__FILE__) + '/support/views'
|
|
48
51
|
end
|
|
52
|
+
|
|
53
|
+
def valid_x509_pem
|
|
54
|
+
raw = File.read(File.dirname(__FILE__) + '/support/fixtures/test.pem')
|
|
55
|
+
OpenSSL::X509::Certificate.new(raw).to_pem
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def raw_x509_string
|
|
59
|
+
raw = valid_x509_pem.match(/#{PEM_HEADER}(?<cert>.*)#{PEM_FOOTER}/m)
|
|
60
|
+
raw[:cert]
|
|
61
|
+
end
|
|
49
62
|
end
|
|
50
63
|
|
|
51
64
|
RSpec.configure do |config|
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
-----BEGIN PRIVATE KEY-----
|
|
2
|
+
MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBANDYf/XXreldztPH
|
|
3
|
+
0IJSkvgeQVZCu1ie+D2Ij9nEzJAuM10bD4p2IjI8EQUKUTn1OBbX4ykhn5Ovw9SU
|
|
4
|
+
D8qEllQCzq7zuX54BEm8cHX3IXTpMLM90T2zJayS+3hQqXHzGXeX3fuP1KhNrrkL
|
|
5
|
+
HAlDEtVD/vwIci/TS2Mep7weytOjAgMBAAECgYA23kpwCmQUhaLLHRn4wzz9luVP
|
|
6
|
+
hmS2Gb3aXMB+VCfyUVEJSwzAMd02GXXXPyir83Ly/XEe40iLgogOl3+2kzLzEegI
|
|
7
|
+
1wx9mydlar0kBIDKJkYdnikbvy0IKFNXRxqHl0Oecy9lArDKmBmadYsse8hsZLX2
|
|
8
|
+
eZUmB8G50TeDyz/4gQJBAO1OM4dT/Uo/zTaTDMs7A+td1C4gvjpI7aKPwHdwmvoc
|
|
9
|
+
dQN9BKoAV0EMoUcXvAeVreWEYGZrMwXQB6xT7aydyUMCQQDhTFffVlvsqOmQYhzf
|
|
10
|
+
lbKS8orI0SZZHz8F5dnj1zwb4Xp+hl6tIAkxcZ1DxP4emfc1htd4GswzNqSVfFJv
|
|
11
|
+
JXYhAkEAsmdWSekUxVtN9jd7KNbHTY2O1Nb87GijbtFPyvu3J015kxPMC9qRvm+2
|
|
12
|
+
V/I6BCG9SI3Kw3TYOQh6nE3Eoz9EbQJBAKvzm4F+pOwsQw8KguT2mPNkoB4C2xTc
|
|
13
|
+
LzquIi2t4VeaMOaOYYYa1EljYFcP66+pbS7yOlOViFJyGw1odHYWDmECQCBGi7f5
|
|
14
|
+
qT4Bs3DoaIyD0w9F3LY/ny7+Pa7WGUqQvQWygUDObBtwojXhg/A9BGckUrQ2jmu/
|
|
15
|
+
bhqnqQJs3f05ETA=
|
|
16
|
+
-----END PRIVATE KEY-----
|
|
17
|
+
-----BEGIN CERTIFICATE-----
|
|
18
|
+
MIICDTCCAXYCCQCm0tqsG7zO2TANBgkqhkiG9w0BAQsFADBLMQswCQYDVQQGEwJV
|
|
19
|
+
UzERMA8GA1UECAwITmV3IFlvcmsxETAPBgNVBAcMCEJyb29rbHluMRYwFAYDVQQK
|
|
20
|
+
DA1FbnRlcnByaXNlT1NTMB4XDTIwMDkwMjE0MTEyMVoXDTIxMDkwMjE0MTEyMVow
|
|
21
|
+
SzELMAkGA1UEBhMCVVMxETAPBgNVBAgMCE5ldyBZb3JrMREwDwYDVQQHDAhCcm9v
|
|
22
|
+
a2x5bjEWMBQGA1UECgwNRW50ZXJwcmlzZU9TUzCBnzANBgkqhkiG9w0BAQEFAAOB
|
|
23
|
+
jQAwgYkCgYEA0Nh/9det6V3O08fQglKS+B5BVkK7WJ74PYiP2cTMkC4zXRsPinYi
|
|
24
|
+
MjwRBQpROfU4FtfjKSGfk6/D1JQPyoSWVALOrvO5fngESbxwdfchdOkwsz3RPbMl
|
|
25
|
+
rJL7eFCpcfMZd5fd+4/UqE2uuQscCUMS1UP+/AhyL9NLYx6nvB7K06MCAwEAATAN
|
|
26
|
+
BgkqhkiG9w0BAQsFAAOBgQDGze/POq+GSwOIYftr83+YkNTIQAg+bl8hiFMtJ3OV
|
|
27
|
+
buFsI/oUGaKloXOrDLbygk+lvimFbj36k3IhwRI7iXJDCwZGxtVCC4+8VNqqT1Yj
|
|
28
|
+
uZT9xHGYVszzGc8nz4wcaQ8M/W4mCuXet1qDwAi0Zo9yLBnyEdc6pluDdJuz0cg6
|
|
29
|
+
xQ==
|
|
30
|
+
-----END CERTIFICATE-----
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: osso
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.5.pre.beta
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Sam Bauch
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2020-
|
|
11
|
+
date: 2020-09-16 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activesupport
|
|
@@ -231,7 +231,6 @@ executables:
|
|
|
231
231
|
extensions: []
|
|
232
232
|
extra_rdoc_files: []
|
|
233
233
|
files:
|
|
234
|
-
- ".DS_Store"
|
|
235
234
|
- ".buildkite/hooks/environment"
|
|
236
235
|
- ".buildkite/hooks/pre-command"
|
|
237
236
|
- ".buildkite/pipeline.yml"
|
|
@@ -239,6 +238,7 @@ files:
|
|
|
239
238
|
- ".gitignore"
|
|
240
239
|
- ".rspec"
|
|
241
240
|
- ".rubocop.yml"
|
|
241
|
+
- ".ruby-version"
|
|
242
242
|
- CODE_OF_CONDUCT.md
|
|
243
243
|
- Gemfile
|
|
244
244
|
- Gemfile.lock
|
|
@@ -271,6 +271,8 @@ files:
|
|
|
271
271
|
- lib/osso/db/migrate/20200723153750_add_missing_timestamps.rb
|
|
272
272
|
- lib/osso/db/migrate/20200723162228_drop_unneeded_tables.rb
|
|
273
273
|
- lib/osso/db/migrate/20200826201852_create_app_config.rb
|
|
274
|
+
- lib/osso/db/migrate/20200913154919_add_one_login_to_identity_provider_service_enum.rb
|
|
275
|
+
- lib/osso/db/migrate/20200916125543_add_google_to_identity_provider_service_enum.rb
|
|
274
276
|
- lib/osso/graphql/.DS_Store
|
|
275
277
|
- lib/osso/graphql/mutation.rb
|
|
276
278
|
- lib/osso/graphql/mutations.rb
|
|
@@ -299,6 +301,7 @@ files:
|
|
|
299
301
|
- lib/osso/graphql/types/base_input_object.rb
|
|
300
302
|
- lib/osso/graphql/types/base_object.rb
|
|
301
303
|
- lib/osso/graphql/types/enterprise_account.rb
|
|
304
|
+
- lib/osso/graphql/types/error.rb
|
|
302
305
|
- lib/osso/graphql/types/identity_provider.rb
|
|
303
306
|
- lib/osso/graphql/types/identity_provider_service.rb
|
|
304
307
|
- lib/osso/graphql/types/identity_provider_status.rb
|
|
@@ -346,14 +349,13 @@ files:
|
|
|
346
349
|
- spec/graphql/query/identity_provider_spec.rb
|
|
347
350
|
- spec/graphql/query/oauth_clients_spec.rb
|
|
348
351
|
- spec/helpers/auth_spec.rb
|
|
349
|
-
- spec/models/azure_saml_provider_spec.rb
|
|
350
352
|
- spec/models/identity_provider_spec.rb
|
|
351
|
-
- spec/models/okta_saml_provider_spec.rb
|
|
352
353
|
- spec/routes/admin_spec.rb
|
|
353
354
|
- spec/routes/app_spec.rb
|
|
354
355
|
- spec/routes/auth_spec.rb
|
|
355
356
|
- spec/routes/oauth_spec.rb
|
|
356
357
|
- spec/spec_helper.rb
|
|
358
|
+
- spec/support/fixtures/test.pem
|
|
357
359
|
- spec/support/spec_app.rb
|
|
358
360
|
- spec/support/views/admin.erb
|
|
359
361
|
- spec/support/views/error.erb
|
|
@@ -372,9 +374,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
372
374
|
version: 2.3.0
|
|
373
375
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
374
376
|
requirements:
|
|
375
|
-
- - "
|
|
377
|
+
- - ">"
|
|
376
378
|
- !ruby/object:Gem::Version
|
|
377
|
-
version:
|
|
379
|
+
version: 1.3.1
|
|
378
380
|
requirements: []
|
|
379
381
|
rubygems_version: 3.0.3
|
|
380
382
|
signing_key:
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'spec_helper'
|
|
4
|
-
|
|
5
|
-
# describe Osso::Models::AzureSamlProvider do
|
|
6
|
-
# subject { create(:azure_identity_provider) }
|
|
7
|
-
|
|
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
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'spec_helper'
|
|
4
|
-
|
|
5
|
-
# describe Osso::Models::OktaSamlProvider do
|
|
6
|
-
# subject { create(:okta_identity_provider) }
|
|
7
|
-
|
|
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
|