osso 0.0.5.pre.lambda → 0.0.6
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 +6 -4
- data/.github/dependabot.yml +8 -0
- data/.github/workflows/automerge.yml +19 -0
- data/.rubocop.yml +4 -1
- data/Gemfile +1 -1
- data/Gemfile.lock +48 -27
- data/bin/annotate +3 -1
- data/db/schema.rb +40 -3
- data/lib/osso.rb +0 -1
- data/lib/osso/db/migrate/20201023142158_add_rodauth_tables.rb +47 -0
- data/lib/osso/db/migrate/20201105122026_add_token_index_to_access_tokens.rb +5 -0
- data/lib/osso/db/migrate/20201106154936_add_requested_to_authorization_codes_and_access_tokens.rb +6 -0
- data/lib/osso/db/migrate/20201109160851_add_sso_issuer_to_identity_providers.rb +12 -0
- data/lib/osso/db/migrate/20201110190754_remove_oauth_client_id_from_enterprise_accounts.rb +9 -0
- data/lib/osso/db/migrate/20201112160120_add_ping_to_identity_provider_service_enum.rb +28 -0
- data/lib/osso/error/account_configuration_error.rb +1 -0
- data/lib/osso/error/oauth_error.rb +6 -3
- data/lib/osso/graphql/mutation.rb +1 -0
- data/lib/osso/graphql/mutations.rb +1 -0
- data/lib/osso/graphql/mutations/create_enterprise_account.rb +0 -7
- data/lib/osso/graphql/mutations/create_identity_provider.rb +7 -6
- data/lib/osso/graphql/mutations/invite_admin_user.rb +43 -0
- data/lib/osso/graphql/query.rb +8 -0
- data/lib/osso/graphql/resolvers/enterprise_accounts.rb +2 -2
- data/lib/osso/graphql/types.rb +2 -2
- data/lib/osso/graphql/types/admin_user.rb +9 -0
- data/lib/osso/graphql/types/base_object.rb +1 -1
- data/lib/osso/graphql/types/identity_provider.rb +2 -0
- data/lib/osso/graphql/types/identity_provider_service.rb +2 -1
- data/lib/osso/lib/app_config.rb +1 -1
- data/lib/osso/lib/route_map.rb +0 -16
- data/lib/osso/lib/saml_handler.rb +5 -0
- data/lib/osso/models/access_token.rb +4 -2
- data/lib/osso/models/account.rb +34 -0
- data/lib/osso/models/authorization_code.rb +2 -1
- data/lib/osso/models/enterprise_account.rb +3 -1
- data/lib/osso/models/identity_provider.rb +18 -4
- data/lib/osso/models/models.rb +1 -0
- data/lib/osso/models/oauth_client.rb +0 -1
- data/lib/osso/routes/admin.rb +39 -33
- data/lib/osso/routes/auth.rb +9 -9
- data/lib/osso/routes/oauth.rb +34 -16
- data/lib/osso/version.rb +1 -1
- data/lib/osso/views/admin.erb +5 -0
- data/lib/osso/views/error.erb +1 -0
- data/lib/osso/views/layout.erb +0 -0
- data/lib/osso/views/multiple_providers.erb +1 -0
- data/lib/osso/views/welcome.erb +0 -0
- data/lib/tasks/bootstrap.rake +25 -4
- data/osso-rb.gemspec +5 -0
- data/spec/factories/account.rb +24 -0
- data/spec/factories/enterprise_account.rb +11 -3
- data/spec/factories/identity_providers.rb +10 -2
- data/spec/factories/user.rb +4 -0
- data/spec/graphql/mutations/configure_identity_provider_spec.rb +1 -1
- data/spec/graphql/mutations/create_enterprise_account_spec.rb +0 -14
- data/spec/graphql/mutations/create_identity_provider_spec.rb +59 -8
- data/spec/graphql/query/identity_provider_spec.rb +2 -2
- data/spec/models/enterprise_account_spec.rb +18 -0
- data/spec/models/identity_provider_spec.rb +24 -3
- data/spec/routes/admin_spec.rb +7 -41
- data/spec/routes/auth_spec.rb +17 -18
- data/spec/routes/oauth_spec.rb +87 -5
- data/spec/spec_helper.rb +3 -3
- data/spec/support/views/layout.erb +1 -0
- metadata +98 -7
- data/lib/osso/helpers/auth.rb +0 -94
- data/lib/osso/helpers/helpers.rb +0 -8
- data/spec/helpers/auth_spec.rb +0 -269
@@ -7,14 +7,19 @@ module Osso
|
|
7
7
|
belongs_to :enterprise_account
|
8
8
|
belongs_to :oauth_client
|
9
9
|
has_many :users, dependent: :delete_all
|
10
|
+
before_create :set_sso_issuer
|
10
11
|
before_save :set_status
|
11
12
|
validate :sso_cert_valid
|
12
13
|
|
13
|
-
enum status: { pending:
|
14
|
+
enum status: { pending: 'PENDING', configured: 'CONFIGURED', active: 'ACTIVE', error: 'ERROR' }
|
14
15
|
|
15
16
|
PEM_HEADER = "-----BEGIN CERTIFICATE-----\n"
|
16
17
|
PEM_FOOTER = "\n-----END CERTIFICATE-----"
|
17
18
|
|
19
|
+
ENTITY_ID_URI_REQUIRED = [
|
20
|
+
'PING',
|
21
|
+
]
|
22
|
+
|
18
23
|
def name
|
19
24
|
service.titlecase
|
20
25
|
end
|
@@ -24,7 +29,7 @@ module Osso
|
|
24
29
|
domain: domain,
|
25
30
|
idp_sso_target_url: sso_url,
|
26
31
|
idp_cert: sso_cert,
|
27
|
-
issuer:
|
32
|
+
issuer: sso_issuer,
|
28
33
|
}
|
29
34
|
end
|
30
35
|
|
@@ -48,6 +53,14 @@ module Osso
|
|
48
53
|
self.status = 'configured' if sso_url && sso_cert && pending?
|
49
54
|
end
|
50
55
|
|
56
|
+
def set_sso_issuer
|
57
|
+
parts = [domain, oauth_client_id]
|
58
|
+
|
59
|
+
parts.unshift('https:/') if ENTITY_ID_URI_REQUIRED.any?(service)
|
60
|
+
|
61
|
+
self.sso_issuer = parts.join('/')
|
62
|
+
end
|
63
|
+
|
51
64
|
def active!
|
52
65
|
update(status: 'active')
|
53
66
|
end
|
@@ -85,15 +98,16 @@ end
|
|
85
98
|
# Table name: identity_providers
|
86
99
|
#
|
87
100
|
# id :uuid not null, primary key
|
88
|
-
# service :
|
101
|
+
# service :enum
|
89
102
|
# domain :string not null
|
90
103
|
# sso_url :string
|
91
104
|
# sso_cert :text
|
92
105
|
# enterprise_account_id :uuid
|
93
106
|
# oauth_client_id :uuid
|
94
|
-
# status :enum default("
|
107
|
+
# status :enum default("pending")
|
95
108
|
# created_at :datetime
|
96
109
|
# updated_at :datetime
|
110
|
+
# users_count :integer default(0)
|
97
111
|
#
|
98
112
|
# Indexes
|
99
113
|
#
|
data/lib/osso/models/models.rb
CHANGED
data/lib/osso/routes/admin.rb
CHANGED
@@ -1,53 +1,59 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require '
|
3
|
+
require 'roda'
|
4
|
+
require 'sequel/core'
|
4
5
|
|
5
|
-
|
6
|
-
class Admin < Sinatra::Base
|
7
|
-
include AppConfig
|
8
|
-
helpers Helpers::Auth
|
9
|
-
register Sinatra::Namespace
|
6
|
+
DEFAULT_VIEWS_DIR = File.join(File.expand_path(Bundler.root), 'views/rodauth')
|
10
7
|
|
11
|
-
|
12
|
-
|
8
|
+
module Osso
|
9
|
+
class Admin < Roda
|
10
|
+
DB = Sequel.postgres(extensions: :activerecord_connection)
|
11
|
+
use Rack::Session::Cookie, secret: ENV.fetch('SESSION_SECRET')
|
12
|
+
|
13
|
+
plugin :middleware
|
14
|
+
plugin :render, engine: 'erb', views: ENV['RODAUTH_VIEWS'] || DEFAULT_VIEWS_DIR
|
15
|
+
plugin :route_csrf
|
16
|
+
|
17
|
+
plugin :rodauth do
|
18
|
+
enable :login, :verify_account
|
19
|
+
verify_account_set_password? true
|
20
|
+
already_logged_in { redirect login_redirect }
|
21
|
+
use_database_authentication_functions? false
|
22
|
+
|
23
|
+
before_create_account_route do
|
24
|
+
request.halt unless DB[:accounts].empty?
|
25
|
+
end
|
13
26
|
end
|
14
27
|
|
15
|
-
|
16
|
-
get '/login' do
|
17
|
-
token_protected!
|
18
|
-
|
19
|
-
erb :admin, layout: false
|
20
|
-
end
|
28
|
+
alias erb render
|
21
29
|
|
22
|
-
|
23
|
-
|
30
|
+
route do |r|
|
31
|
+
r.rodauth
|
24
32
|
|
25
|
-
|
33
|
+
def current_account
|
34
|
+
Osso::Models::Account.find(rodauth.session['account_id']).
|
35
|
+
context.
|
36
|
+
merge({ rodauth: rodauth })
|
26
37
|
end
|
27
38
|
|
28
|
-
|
29
|
-
|
30
|
-
|
39
|
+
r.on 'admin' do
|
40
|
+
rodauth.require_authentication
|
31
41
|
erb :admin, layout: false
|
32
42
|
end
|
33
43
|
|
34
|
-
|
35
|
-
|
44
|
+
r.post 'graphql' do
|
45
|
+
rodauth.require_authentication
|
36
46
|
|
37
|
-
|
38
|
-
|
47
|
+
result = Osso::GraphQL::Schema.execute(
|
48
|
+
r.params['query'],
|
49
|
+
variables: r.params['variables'],
|
50
|
+
context: current_account,
|
51
|
+
)
|
39
52
|
|
40
|
-
|
41
|
-
admin_protected!
|
42
|
-
|
43
|
-
erb :admin, layout: false
|
53
|
+
result.to_json
|
44
54
|
end
|
45
55
|
|
46
|
-
|
47
|
-
admin_protected!
|
48
|
-
|
49
|
-
erb :admin, layout: false
|
50
|
-
end
|
56
|
+
env['rodauth'] = rodauth
|
51
57
|
end
|
52
58
|
end
|
53
59
|
end
|
data/lib/osso/routes/auth.rb
CHANGED
@@ -13,7 +13,7 @@ module Osso
|
|
13
13
|
UUID_REGEXP =
|
14
14
|
/[0-9a-f]{8}-[0-9a-f]{3,4}-[0-9a-f]{4}-[0-9a-f]{3,4}-[0-9a-f]{12}/.
|
15
15
|
freeze
|
16
|
-
|
16
|
+
|
17
17
|
use OmniAuth::Builder do
|
18
18
|
OmniAuth::MultiProvider.register(
|
19
19
|
self,
|
@@ -26,7 +26,8 @@ module Osso
|
|
26
26
|
not_pending.
|
27
27
|
find(identity_provider_id).
|
28
28
|
saml_options
|
29
|
-
rescue
|
29
|
+
rescue StandardError => e
|
30
|
+
Raven.capture_exception(e) if defined?(Raven)
|
30
31
|
{}
|
31
32
|
end
|
32
33
|
end
|
@@ -38,21 +39,20 @@ module Osso
|
|
38
39
|
namespace '/auth' do
|
39
40
|
get '/failure' do
|
40
41
|
# ??? invalid ticket, warden throws, ugh
|
41
|
-
|
42
|
+
|
42
43
|
# confirmed:
|
43
|
-
# - a valid but wrong cert will throw here
|
44
|
+
# - a valid but wrong cert will throw here
|
44
45
|
# (OneLogin::RubySaml::ValidationError, Fingerprint mismatch)
|
45
46
|
# but an _invalid_ cert is not caught. we do validate certs on
|
46
47
|
# configuration, so this may be ok
|
47
48
|
#
|
48
49
|
# - a valid but wrong ACS URL will throw here. the urls
|
49
50
|
# are pretty complex, but it has come up
|
50
|
-
#
|
51
|
+
#
|
51
52
|
# - specifying the wrong "recipient" in your IDP. Only OL so far
|
52
53
|
# (OneLogin::RubySaml::ValidationError, The response was received
|
53
|
-
# at vcardme.com instead of
|
54
|
-
# http://localhost:9292/auth/saml/e54a9a92-b4b5-4ea5-b0e3-b1423eb20b76/callback)
|
55
|
-
|
54
|
+
# at vcardme.com instead of
|
55
|
+
# http://localhost:9292/auth/saml/e54a9a92-b4b5-4ea5-b0e3-b1423eb20b76/callback)
|
56
56
|
|
57
57
|
@error = Osso::Error::SamlConfigError.new
|
58
58
|
erb :error
|
@@ -73,7 +73,7 @@ module Osso
|
|
73
73
|
rescue Osso::Error::Base => e
|
74
74
|
@error = e
|
75
75
|
erb :error
|
76
|
-
end
|
76
|
+
end
|
77
77
|
end
|
78
78
|
end
|
79
79
|
end
|
data/lib/osso/routes/oauth.rb
CHANGED
@@ -16,14 +16,13 @@ module Osso
|
|
16
16
|
# Once they complete IdP login, they will be returned to the
|
17
17
|
# redirect_uri with an authorization code parameter.
|
18
18
|
get '/authorize' do
|
19
|
-
|
20
|
-
enterprise = find_account(domain: params[:domain], client_id: client.id)
|
19
|
+
identity_providers = find_providers
|
21
20
|
|
22
21
|
validate_oauth_request(env)
|
23
22
|
|
24
|
-
redirect "/auth/saml/#{
|
23
|
+
redirect "/auth/saml/#{identity_providers.first.id}" if identity_providers.one?
|
25
24
|
|
26
|
-
@providers =
|
25
|
+
@providers = identity_providers.not_pending
|
27
26
|
return erb :multiple_providers if @providers.count > 1
|
28
27
|
|
29
28
|
raise Osso::Error::MissingConfiguredIdentityProvider.new(domain: params[:domain])
|
@@ -38,11 +37,12 @@ module Osso
|
|
38
37
|
# and client secret
|
39
38
|
post '/token' do
|
40
39
|
Rack::OAuth2::Server::Token.new do |req, res|
|
41
|
-
code = Models::AuthorizationCode.
|
42
|
-
find_by_token!(params[:code])
|
43
40
|
client = Models::OauthClient.find_by!(identifier: req.client_id)
|
44
41
|
req.invalid_client! if client.secret != req.client_secret
|
42
|
+
|
43
|
+
code = Models::AuthorizationCode.find_by_token!(params[:code])
|
45
44
|
req.invalid_grant! if code.redirect_uri != req.redirect_uri
|
45
|
+
|
46
46
|
res.access_token = code.access_token.to_bearer_token
|
47
47
|
end.call(env)
|
48
48
|
end
|
@@ -50,22 +50,35 @@ module Osso
|
|
50
50
|
# Use the access token to request a profile for the user who
|
51
51
|
# just logged in. Access tokens are short-lived.
|
52
52
|
get '/me' do
|
53
|
-
|
53
|
+
token = Models::AccessToken.
|
54
54
|
includes(:user).
|
55
55
|
valid.
|
56
|
-
find_by_token!(
|
57
|
-
|
56
|
+
find_by_token!(access_token)
|
57
|
+
|
58
|
+
json token.user.as_json.merge(requested: token.requested)
|
58
59
|
end
|
59
60
|
end
|
60
61
|
|
61
62
|
private
|
62
63
|
|
63
|
-
def
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
64
|
+
def find_providers
|
65
|
+
if params[:email]
|
66
|
+
user = Osso::Models::User.
|
67
|
+
includes(:identity_provider).
|
68
|
+
find_by(email: params[:email])
|
69
|
+
return [user.identity_provider] if user
|
70
|
+
end
|
71
|
+
|
72
|
+
Osso::Models::IdentityProvider.
|
73
|
+
joins(:oauth_client).
|
74
|
+
where(
|
75
|
+
domain: domain_from_params,
|
76
|
+
oauth_clients: { identifier: params[:client_id] },
|
77
|
+
)
|
78
|
+
end
|
79
|
+
|
80
|
+
def domain_from_params
|
81
|
+
params[:domain] || params[:email].split('@')[1]
|
69
82
|
end
|
70
83
|
|
71
84
|
def find_client(identifier)
|
@@ -74,14 +87,19 @@ module Osso
|
|
74
87
|
raise Osso::Error::InvalidOAuthClientIdentifier
|
75
88
|
end
|
76
89
|
|
77
|
-
def validate_oauth_request(env)
|
90
|
+
def validate_oauth_request(env) # rubocop:disable Metrics/AbcSize
|
78
91
|
Rack::OAuth2::Server::Authorize.new do |req, _res|
|
79
92
|
client = find_client(req[:client_id])
|
80
93
|
session[:osso_oauth_redirect_uri] = req.verify_redirect_uri!(client.redirect_uri_values)
|
81
94
|
session[:osso_oauth_state] = params[:state]
|
95
|
+
session[:osso_oauth_requested] = { domain: req[:domain], email: req[:email] }
|
82
96
|
end.call(env)
|
83
97
|
rescue Rack::OAuth2::Server::Authorize::BadRequest
|
84
98
|
raise Osso::Error::InvalidRedirectUri.new(redirect_uri: params[:redirect_uri])
|
85
99
|
end
|
100
|
+
|
101
|
+
def access_token
|
102
|
+
params[:access_token] || env.fetch('HTTP_AUTHORIZATION', '').slice(-64..-1)
|
103
|
+
end
|
86
104
|
end
|
87
105
|
end
|
data/lib/osso/version.rb
CHANGED
@@ -0,0 +1 @@
|
|
1
|
+
<%= @error %>
|
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
MULITPLE PROVIDERS
|
File without changes
|
data/lib/tasks/bootstrap.rake
CHANGED
@@ -7,12 +7,33 @@ require 'osso'
|
|
7
7
|
namespace :osso do
|
8
8
|
desc 'Bootstrap Osso data for a deployment'
|
9
9
|
task :bootstrap do
|
10
|
-
%w[Production Staging Development].each do |
|
10
|
+
%w[Production Staging Development].each do |environment|
|
11
11
|
Osso::Models::OauthClient.create!(
|
12
|
-
name:
|
13
|
-
)
|
12
|
+
name: environment,
|
13
|
+
) unless Osso::Models::OauthClient.find_by_name(environment)
|
14
14
|
end
|
15
15
|
|
16
|
-
Osso::Models::AppConfig.create
|
16
|
+
Osso::Models::AppConfig.create
|
17
|
+
|
18
|
+
admin_email = ENV['ADMIN_EMAIL']
|
19
|
+
|
20
|
+
if admin_email
|
21
|
+
admin = Osso::Models::Account.create(
|
22
|
+
email: admin_email,
|
23
|
+
status_id: 1,
|
24
|
+
role: 'admin',
|
25
|
+
)
|
26
|
+
|
27
|
+
base_uri = URI.parse(ENV['BASE_URL'])
|
28
|
+
|
29
|
+
rodauth = Osso::Admin.rodauth.new(Osso::Admin.new({
|
30
|
+
'HTTP_HOST' => base_uri.host,
|
31
|
+
'SERVER_NAME' => base_uri.to_s,
|
32
|
+
'rack.url_scheme' => base_uri.scheme
|
33
|
+
}))
|
34
|
+
|
35
|
+
account = rodauth.account_from_login(admin_email)
|
36
|
+
rodauth.setup_account_verification
|
37
|
+
end
|
17
38
|
end
|
18
39
|
end
|
data/osso-rb.gemspec
CHANGED
@@ -16,14 +16,19 @@ Gem::Specification.new do |spec|
|
|
16
16
|
spec.license = 'MIT'
|
17
17
|
|
18
18
|
spec.add_runtime_dependency 'activesupport', '>= 6.0.3.2'
|
19
|
+
spec.add_runtime_dependency 'bcrypt', '~> 3.1.13'
|
19
20
|
spec.add_runtime_dependency 'graphql'
|
20
21
|
spec.add_runtime_dependency 'jwt'
|
22
|
+
spec.add_runtime_dependency 'mail', '~> 2.7.1'
|
21
23
|
spec.add_runtime_dependency 'omniauth-multi-provider'
|
22
24
|
spec.add_runtime_dependency 'omniauth-saml'
|
23
25
|
spec.add_runtime_dependency 'rack', '>= 2.1.4'
|
24
26
|
spec.add_runtime_dependency 'rack-contrib'
|
25
27
|
spec.add_runtime_dependency 'rack-oauth2'
|
26
28
|
spec.add_runtime_dependency 'rake'
|
29
|
+
spec.add_runtime_dependency 'rodauth', '~> 2.6.0'
|
30
|
+
spec.add_runtime_dependency 'sequel', '~> 5.37.0'
|
31
|
+
spec.add_runtime_dependency 'sequel-activerecord_connection', '>= 0.3', '< 2.0'
|
27
32
|
spec.add_runtime_dependency 'sinatra'
|
28
33
|
spec.add_runtime_dependency 'sinatra-activerecord'
|
29
34
|
spec.add_runtime_dependency 'sinatra-contrib'
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
DB = Sequel.postgres(extensions: :activerecord_connection)
|
4
|
+
|
5
|
+
FactoryBot.define do
|
6
|
+
factory :account, class: Osso::Models::Account do
|
7
|
+
id { SecureRandom.uuid }
|
8
|
+
email { Faker::Internet.email }
|
9
|
+
end
|
10
|
+
|
11
|
+
factory :verified_account, parent: :account do
|
12
|
+
transient do
|
13
|
+
password { SecureRandom.urlsafe_base64(8) }
|
14
|
+
end
|
15
|
+
status_id { 2 }
|
16
|
+
|
17
|
+
after :create do |account|
|
18
|
+
DB[:account_password_hashes].insert(
|
19
|
+
id: account.id,
|
20
|
+
password_hash: BCrypt::Password.create('secret', cost: BCrypt::Engine::MIN_COST).to_s,
|
21
|
+
)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -2,19 +2,22 @@
|
|
2
2
|
|
3
3
|
FactoryBot.define do
|
4
4
|
factory :enterprise_account, class: Osso::Models::EnterpriseAccount do
|
5
|
+
transient do
|
6
|
+
oauth_client { create(:oauth_client) }
|
7
|
+
end
|
5
8
|
id { SecureRandom.uuid }
|
6
9
|
name { Faker::Company.name }
|
7
10
|
domain { Faker::Internet.domain_name }
|
8
|
-
oauth_client
|
9
11
|
end
|
10
12
|
|
11
13
|
factory :enterprise_with_okta, parent: :enterprise_account do
|
12
|
-
after :create do |enterprise|
|
14
|
+
after :create do |enterprise, evaluator|
|
13
15
|
create(
|
14
16
|
:configured_identity_provider,
|
15
17
|
service: 'OKTA',
|
16
18
|
domain: enterprise.domain,
|
17
19
|
enterprise_account_id: enterprise.id,
|
20
|
+
oauth_client: evaluator.oauth_client,
|
18
21
|
)
|
19
22
|
end
|
20
23
|
end
|
@@ -31,12 +34,16 @@ FactoryBot.define do
|
|
31
34
|
end
|
32
35
|
|
33
36
|
factory :enterprise_with_multiple_providers, parent: :enterprise_account do
|
34
|
-
|
37
|
+
transient do
|
38
|
+
oauth_client { nil }
|
39
|
+
end
|
40
|
+
after :create do |enterprise, evaluator|
|
35
41
|
create(
|
36
42
|
:configured_identity_provider,
|
37
43
|
service: 'OKTA',
|
38
44
|
domain: enterprise.domain,
|
39
45
|
enterprise_account_id: enterprise.id,
|
46
|
+
oauth_client: evaluator.oauth_client,
|
40
47
|
)
|
41
48
|
|
42
49
|
create(
|
@@ -44,6 +51,7 @@ FactoryBot.define do
|
|
44
51
|
service: 'AZURE',
|
45
52
|
domain: enterprise.domain,
|
46
53
|
enterprise_account_id: enterprise.id,
|
54
|
+
oauth_client: evaluator.oauth_client,
|
47
55
|
)
|
48
56
|
end
|
49
57
|
end
|