osso 0.0.2.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. checksums.yaml +7 -0
  2. data/.DS_Store +0 -0
  3. data/.buildkite/hooks/environment +9 -0
  4. data/.buildkite/hooks/pre-command +7 -0
  5. data/.buildkite/pipeline.yml +3 -0
  6. data/.buildkite/template.yml +5 -0
  7. data/.gitignore +9 -0
  8. data/.rspec +1 -0
  9. data/.rubocop.yml +82 -0
  10. data/CODE_OF_CONDUCT.md +130 -0
  11. data/Gemfile +18 -0
  12. data/Gemfile.lock +174 -0
  13. data/LICENSE +111 -0
  14. data/README.md +2 -0
  15. data/Rakefile +14 -0
  16. data/bin/console +7 -0
  17. data/bin/setup +8 -0
  18. data/config/database.yml +14 -0
  19. data/lib/.DS_Store +0 -0
  20. data/lib/osso/Rakefile +13 -0
  21. data/lib/osso/db/migrate/20190909230109_enable_uuid.rb +7 -0
  22. data/lib/osso/db/migrate/20200328135750_create_users.rb +12 -0
  23. data/lib/osso/db/migrate/20200328143303_create_oauth_tables.rb +57 -0
  24. data/lib/osso/db/migrate/20200411144528_create_saml_providers.rb +13 -0
  25. data/lib/osso/db/migrate/20200411184535_add_provider_id_to_users.rb +7 -0
  26. data/lib/osso/db/migrate/20200411192645_create_enterprise_accounts.rb +15 -0
  27. data/lib/osso/db/migrate/20200413132407_add_oauth_clients.rb +13 -0
  28. data/lib/osso/db/migrate/20200413142511_create_authorization_codes.rb +15 -0
  29. data/lib/osso/db/migrate/20200413153029_add_oauth_client_reference_to_saml_providers.rb +5 -0
  30. data/lib/osso/db/migrate/20200413163451_create_access_tokens.rb +13 -0
  31. data/lib/osso/db/migrate/20200501203026_drop_null_constraints_from_saml_provider.rb +7 -0
  32. data/lib/osso/db/migrate/20200501204047_drop_acs_url.rb +5 -0
  33. data/lib/osso/db/migrate/20200502120616_create_redirect_uris_and_drop_from_oauth_clients.rb +13 -0
  34. data/lib/osso/db/migrate/20200502135008_add_oauth_client_id_to_enterprise_account.rb +5 -0
  35. data/lib/osso/db/migrate/20200601131227_drop_null_constraint_from_saml_providers_provider.rb +7 -0
  36. data/lib/osso/db/schema.rb +132 -0
  37. data/lib/osso/helpers/auth.rb +67 -0
  38. data/lib/osso/helpers/helpers.rb +6 -0
  39. data/lib/osso/lib/app_config.rb +20 -0
  40. data/lib/osso/lib/oauth2_token.rb +38 -0
  41. data/lib/osso/models/access_token.rb +29 -0
  42. data/lib/osso/models/authorization_code.rb +14 -0
  43. data/lib/osso/models/enterprise_account.rb +28 -0
  44. data/lib/osso/models/models.rb +16 -0
  45. data/lib/osso/models/oauth_client.rb +32 -0
  46. data/lib/osso/models/redirect_uri.rb +20 -0
  47. data/lib/osso/models/saml_provider.rb +52 -0
  48. data/lib/osso/models/saml_providers/azure_saml_provider.rb +22 -0
  49. data/lib/osso/models/saml_providers/okta_saml_provider.rb +23 -0
  50. data/lib/osso/models/user.rb +24 -0
  51. data/lib/osso/rake.rb +4 -0
  52. data/lib/osso/routes/admin.rb +42 -0
  53. data/lib/osso/routes/auth.rb +64 -0
  54. data/lib/osso/routes/oauth.rb +57 -0
  55. data/lib/osso/routes/routes.rb +10 -0
  56. data/lib/osso/routes/views/error.erb +1 -0
  57. data/lib/osso/routes/views/multiple_providers.erb +1 -0
  58. data/lib/osso/version.rb +5 -0
  59. data/lib/osso.rb +9 -0
  60. data/lib/tasks/bootstrap.rake +17 -0
  61. data/osso-rb.gemspec +40 -0
  62. data/spec/factories/authorization_code.rb +10 -0
  63. data/spec/factories/enterprise_account.rb +45 -0
  64. data/spec/factories/oauth_client.rb +12 -0
  65. data/spec/factories/redirect_uri.rb +14 -0
  66. data/spec/factories/saml_providers.rb +46 -0
  67. data/spec/factories/user.rb +18 -0
  68. data/spec/models/azure_saml_provider_spec.rb +19 -0
  69. data/spec/models/okta_saml_provider_spec.rb +20 -0
  70. data/spec/models/saml_provider_spec.rb +31 -0
  71. data/spec/routes/admin_spec.rb +57 -0
  72. data/spec/routes/app_spec.rb +6 -0
  73. data/spec/routes/auth_spec.rb +112 -0
  74. data/spec/routes/oauth_spec.rb +134 -0
  75. data/spec/spec_helper.rb +65 -0
  76. data/spec/support/vcr_cassettes/okta_saml_callback.yml +59 -0
  77. metadata +302 -0
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ class CreateOauthTables < ActiveRecord::Migration[6.0]
4
+ def change
5
+ create_table :oauth_applications, id: :uuid do |t|
6
+ t.string :name, null: false
7
+ t.string :secret, null: false
8
+ t.text :redirect_uri, null: false
9
+ t.string :scopes, null: false, default: ''
10
+ t.boolean :confidential, null: false, default: true
11
+ t.timestamps null: false
12
+ end
13
+
14
+ create_table :oauth_access_grants, id: :uuid do |t|
15
+ t.uuid :resource_owner_id, null: false
16
+ t.references :application, type: :uuid, null: false
17
+ t.string :token, null: false
18
+ t.integer :expires_in, null: false
19
+ t.text :redirect_uri, null: false
20
+ t.datetime :created_at, null: false
21
+ t.datetime :revoked_at
22
+ t.string :scopes, null: false, default: ''
23
+ end
24
+
25
+ add_index :oauth_access_grants, :token, unique: true
26
+ add_foreign_key(
27
+ :oauth_access_grants,
28
+ :oauth_applications,
29
+ column: :application_id
30
+ )
31
+
32
+ create_table :oauth_access_tokens, id: :uuid do |t|
33
+ t.uuid :resource_owner_id
34
+ t.references :application, type: :uuid
35
+ t.string :token, null: false
36
+
37
+ t.string :refresh_token
38
+ t.integer :expires_in
39
+ t.datetime :revoked_at
40
+ t.datetime :created_at, null: false
41
+ t.string :scopes
42
+
43
+ t.string :previous_refresh_token, null: false, default: ''
44
+ end
45
+
46
+ add_index :oauth_access_tokens, :token, unique: true
47
+ add_index :oauth_access_tokens, :refresh_token, unique: true
48
+ add_foreign_key(
49
+ :oauth_access_tokens,
50
+ :oauth_applications,
51
+ column: :application_id
52
+ )
53
+
54
+ add_foreign_key :oauth_access_grants, :users, column: :resource_owner_id
55
+ add_foreign_key :oauth_access_tokens, :users, column: :resource_owner_id
56
+ end
57
+ end
@@ -0,0 +1,13 @@
1
+ class CreateSamlProviders < ActiveRecord::Migration[6.0]
2
+ def change
3
+ create_table :saml_providers, id: :uuid do |t|
4
+ t.string :provider, null: false
5
+ t.string :domain, null: false
6
+ t.string :idp_sso_target_url, null: false
7
+ t.text :idp_cert, null: false
8
+ t.string :assertion_consumer_service_url
9
+ end
10
+
11
+ add_index :saml_providers, [:domain, :provider], unique: true
12
+ end
13
+ end
@@ -0,0 +1,7 @@
1
+ class AddProviderIdToUsers < ActiveRecord::Migration[6.0]
2
+ def change
3
+ add_column :users, :saml_provider_id, :uuid
4
+
5
+ add_foreign_key :users, :saml_providers
6
+ end
7
+ end
@@ -0,0 +1,15 @@
1
+ class CreateEnterpriseAccounts < ActiveRecord::Migration[6.0]
2
+ def change
3
+ create_table :enterprise_accounts, id: :uuid do |t|
4
+ t.string :domain, null: false
5
+ t.uuid :external_uuid
6
+ t.integer :external_int_id
7
+ t.string :external_id
8
+ end
9
+
10
+ add_index :enterprise_accounts, :domain, unique: true
11
+
12
+ add_reference :saml_providers, :enterprise_account, type: :uuid, index: true
13
+ add_reference :users, :enterprise_account, type: :uuid, index: true
14
+ end
15
+ end
@@ -0,0 +1,13 @@
1
+ class AddOauthClients < ActiveRecord::Migration[6.0]
2
+ def change
3
+ create_table :oauth_clients, id: :uuid do |t|
4
+ t.string :name, null: false
5
+ t.string :secret, null: false
6
+ t.string :identifier, null: false
7
+ t.jsonb :redirect_uris, default: [], null: false
8
+ end
9
+
10
+ add_index :oauth_clients, :redirect_uris, using: :gin
11
+ add_index :oauth_clients, :identifier, unique: true
12
+ end
13
+ end
@@ -0,0 +1,15 @@
1
+ class CreateAuthorizationCodes < ActiveRecord::Migration[6.0]
2
+ def change
3
+ create_table :authorization_codes, id: :uuid do |t|
4
+ t.string :token
5
+ t.string :redirect_uri
6
+ t.datetime :expires_at
7
+
8
+ t.timestamps
9
+ end
10
+
11
+ add_index :authorization_codes, :token, unique: true
12
+ add_reference :authorization_codes, :user, type: :uuid, index: true
13
+ add_reference :authorization_codes, :oauth_client, type: :uuid, index: true
14
+ end
15
+ end
@@ -0,0 +1,5 @@
1
+ class AddOauthClientReferenceToSamlProviders < ActiveRecord::Migration[6.0]
2
+ def change
3
+ add_reference :saml_providers, :oauth_client, type: :uuid, index: true
4
+ end
5
+ end
@@ -0,0 +1,13 @@
1
+ class CreateAccessTokens < ActiveRecord::Migration[6.0]
2
+ def change
3
+ create_table :access_tokens, id: :uuid do |t|
4
+ t.string :token
5
+ t.datetime :expires_at
6
+
7
+ t.timestamps
8
+ end
9
+
10
+ add_reference :access_tokens, :user, type: :uuid, index: true
11
+ add_reference :access_tokens, :oauth_client, type: :uuid, index: true
12
+ end
13
+ end
@@ -0,0 +1,7 @@
1
+ class DropNullConstraintsFromSamlProvider < ActiveRecord::Migration[6.0]
2
+ def change
3
+ change_column :saml_providers, :idp_sso_target_url, :string, null: true
4
+ change_column :saml_providers, :idp_cert, :text, null: true
5
+ change_column :saml_providers, :assertion_consumer_service_url, :string, null: false
6
+ end
7
+ end
@@ -0,0 +1,5 @@
1
+ class DropAcsUrl < ActiveRecord::Migration[6.0]
2
+ def change
3
+ remove_column :saml_providers, :assertion_consumer_service_url
4
+ end
5
+ end
@@ -0,0 +1,13 @@
1
+ class CreateRedirectUrisAndDropFromOauthClients < ActiveRecord::Migration[6.0]
2
+ def change
3
+ remove_column :oauth_clients, :redirect_uris
4
+
5
+ create_table :redirect_uris, id: :uuid do |t|
6
+ t.string :uri, null: false
7
+ t.boolean :primary, default: false, null: false
8
+ end
9
+
10
+ add_index :redirect_uris, [:uri, :primary], unique: true
11
+ add_reference :redirect_uris, :oauth_client, type: :uuid, index: true
12
+ end
13
+ end
@@ -0,0 +1,5 @@
1
+ class AddOauthClientIdToEnterpriseAccount < ActiveRecord::Migration[6.0]
2
+ def change
3
+ add_reference :enterprise_accounts, :oauth_client, type: :uuid, index: true
4
+ end
5
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class DropNullConstraintFromSamlProvidersProvider < ActiveRecord::Migration[6.0]
4
+ def change
5
+ change_column :saml_providers, :provider, :string, null: true
6
+ end
7
+ end
@@ -0,0 +1,132 @@
1
+ # This file is auto-generated from the current state of the database. Instead
2
+ # of editing this file, please use the migrations feature of Active Record to
3
+ # incrementally modify your database, and then regenerate this schema definition.
4
+ #
5
+ # This file is the source Rails uses to define your schema when running `rails
6
+ # db:schema:load`. When creating a new database, `rails db:schema:load` tends to
7
+ # be faster and is potentially less error prone than running all of your
8
+ # migrations from scratch. Old migrations may fail to apply correctly if those
9
+ # migrations use external dependencies or application code.
10
+ #
11
+ # It's strongly recommended that you check this file into your version control system.
12
+
13
+ ActiveRecord::Schema.define(version: 2020_05_02_135008) do
14
+
15
+ # These are extensions that must be enabled in order to support this database
16
+ enable_extension "pgcrypto"
17
+ enable_extension "plpgsql"
18
+
19
+ create_table "access_tokens", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
20
+ t.string "token"
21
+ t.datetime "expires_at"
22
+ t.datetime "created_at", precision: 6, null: false
23
+ t.datetime "updated_at", precision: 6, null: false
24
+ t.uuid "user_id"
25
+ t.uuid "oauth_client_id"
26
+ t.index ["oauth_client_id"], name: "index_access_tokens_on_oauth_client_id"
27
+ t.index ["user_id"], name: "index_access_tokens_on_user_id"
28
+ end
29
+
30
+ create_table "authorization_codes", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
31
+ t.string "token"
32
+ t.string "redirect_uri"
33
+ t.datetime "expires_at"
34
+ t.datetime "created_at", precision: 6, null: false
35
+ t.datetime "updated_at", precision: 6, null: false
36
+ t.uuid "user_id"
37
+ t.uuid "oauth_client_id"
38
+ t.index ["oauth_client_id"], name: "index_authorization_codes_on_oauth_client_id"
39
+ t.index ["token"], name: "index_authorization_codes_on_token", unique: true
40
+ t.index ["user_id"], name: "index_authorization_codes_on_user_id"
41
+ end
42
+
43
+ create_table "enterprise_accounts", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
44
+ t.string "domain", null: false
45
+ t.uuid "external_uuid"
46
+ t.integer "external_int_id"
47
+ t.string "external_id"
48
+ t.uuid "oauth_client_id"
49
+ t.index ["domain"], name: "index_enterprise_accounts_on_domain", unique: true
50
+ t.index ["oauth_client_id"], name: "index_enterprise_accounts_on_oauth_client_id"
51
+ end
52
+
53
+ create_table "oauth_access_grants", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
54
+ t.uuid "resource_owner_id", null: false
55
+ t.uuid "application_id", null: false
56
+ t.string "token", null: false
57
+ t.integer "expires_in", null: false
58
+ t.text "redirect_uri", null: false
59
+ t.datetime "created_at", null: false
60
+ t.datetime "revoked_at"
61
+ t.string "scopes", default: "", null: false
62
+ t.index ["application_id"], name: "index_oauth_access_grants_on_application_id"
63
+ t.index ["token"], name: "index_oauth_access_grants_on_token", unique: true
64
+ end
65
+
66
+ create_table "oauth_access_tokens", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
67
+ t.uuid "resource_owner_id"
68
+ t.uuid "application_id"
69
+ t.string "token", null: false
70
+ t.string "refresh_token"
71
+ t.integer "expires_in"
72
+ t.datetime "revoked_at"
73
+ t.datetime "created_at", null: false
74
+ t.string "scopes"
75
+ t.string "previous_refresh_token", default: "", null: false
76
+ t.index ["application_id"], name: "index_oauth_access_tokens_on_application_id"
77
+ t.index ["refresh_token"], name: "index_oauth_access_tokens_on_refresh_token", unique: true
78
+ t.index ["token"], name: "index_oauth_access_tokens_on_token", unique: true
79
+ end
80
+
81
+ create_table "oauth_applications", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
82
+ t.string "name", null: false
83
+ t.string "secret", null: false
84
+ t.text "redirect_uri", null: false
85
+ t.string "scopes", default: "", null: false
86
+ t.boolean "confidential", default: true, null: false
87
+ t.datetime "created_at", precision: 6, null: false
88
+ t.datetime "updated_at", precision: 6, null: false
89
+ end
90
+
91
+ create_table "oauth_clients", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
92
+ t.string "name", null: false
93
+ t.string "secret", null: false
94
+ t.string "identifier", null: false
95
+ t.index ["identifier"], name: "index_oauth_clients_on_identifier", unique: true
96
+ end
97
+
98
+ create_table "redirect_uris", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
99
+ t.string "uri", null: false
100
+ t.boolean "primary", default: false, null: false
101
+ t.uuid "oauth_client_id"
102
+ t.index ["oauth_client_id"], name: "index_redirect_uris_on_oauth_client_id"
103
+ t.index ["uri", "primary"], name: "index_redirect_uris_on_uri_and_primary", unique: true
104
+ end
105
+
106
+ create_table "saml_providers", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
107
+ t.string "provider", null: false
108
+ t.string "domain", null: false
109
+ t.string "idp_sso_target_url"
110
+ t.text "idp_cert"
111
+ t.uuid "enterprise_account_id"
112
+ t.uuid "oauth_client_id"
113
+ t.index ["domain", "provider"], name: "index_saml_providers_on_domain_and_provider", unique: true
114
+ t.index ["enterprise_account_id"], name: "index_saml_providers_on_enterprise_account_id"
115
+ t.index ["oauth_client_id"], name: "index_saml_providers_on_oauth_client_id"
116
+ end
117
+
118
+ create_table "users", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
119
+ t.string "email", null: false
120
+ t.string "idp_id", null: false
121
+ t.uuid "saml_provider_id"
122
+ t.uuid "enterprise_account_id"
123
+ t.index ["email", "idp_id"], name: "index_users_on_email_and_idp_id", unique: true
124
+ t.index ["enterprise_account_id"], name: "index_users_on_enterprise_account_id"
125
+ end
126
+
127
+ add_foreign_key "oauth_access_grants", "oauth_applications", column: "application_id"
128
+ add_foreign_key "oauth_access_grants", "users", column: "resource_owner_id"
129
+ add_foreign_key "oauth_access_tokens", "oauth_applications", column: "application_id"
130
+ add_foreign_key "oauth_access_tokens", "users", column: "resource_owner_id"
131
+ add_foreign_key "users", "saml_providers"
132
+ end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Helpers
4
+ module Auth
5
+ attr_accessor :current_scope
6
+
7
+ def enterprise_protected!(domain = nil)
8
+ return if admin_authorized?
9
+ return if enterprise_authorized?(domain)
10
+
11
+ redirect ENV['JWT_URL']
12
+ end
13
+
14
+ def enterprise_authorized?(domain)
15
+ payload, _args = JWT.decode(
16
+ token,
17
+ ENV['JWT_HMAC_SECRET'],
18
+ true,
19
+ { algorithm: 'HS256' },
20
+ )
21
+
22
+ @current_scope = payload['scope']
23
+
24
+ true
25
+ rescue JWT::DecodeError
26
+ false
27
+ end
28
+
29
+ def admin_protected!
30
+ return if admin_authorized?
31
+
32
+ redirect ENV['JWT_URL']
33
+ end
34
+
35
+ def admin_authorized?
36
+ payload, _args = JWT.decode(
37
+ token,
38
+ ENV['JWT_HMAC_SECRET'],
39
+ true,
40
+ { algorithm: 'HS256' },
41
+ )
42
+
43
+ if payload['scope'] == 'admin'
44
+ @current_scope = :admin
45
+ return true
46
+ end
47
+
48
+ false
49
+ rescue JWT::DecodeError
50
+ false
51
+ end
52
+
53
+ def token
54
+ request.env['admin_token'] || session['admin_token'] || request['admin_token']
55
+ end
56
+
57
+ def chomp_token
58
+ return unless request['admin_token'].present?
59
+
60
+ session['admin_token'] = request['admin_token']
61
+
62
+ return if request.post?
63
+
64
+ redirect request.path
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Helpers
4
+ end
5
+
6
+ require_relative 'auth'
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rack/contrib'
4
+
5
+ module Osso
6
+ module AppConfig
7
+ def self.included(klass)
8
+ klass.class_eval do
9
+ use Rack::JSONBodyParser
10
+ use Rack::Session::Cookie, secret: ENV.fetch('SESSION_SECRET')
11
+
12
+ error ActiveRecord::RecordNotFound do
13
+ status 404
14
+ end
15
+
16
+ set :root, Dir.pwd
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+
5
+ module Osso
6
+ module OAuth2Token
7
+ def self.included(klass)
8
+ klass.class_eval do
9
+ cattr_accessor :default_lifetime
10
+ self.default_lifetime = 1.minute
11
+ belongs_to :user
12
+ belongs_to :oauth_client
13
+
14
+ before_validation :setup, on: :create
15
+ validates :oauth_client, :expires_at, presence: true
16
+ validates :token, presence: true, uniqueness: true
17
+
18
+ scope :valid, -> { where('expires_at > ?', Time.now.utc) }
19
+ end
20
+ end
21
+
22
+ def expires_in
23
+ (expires_at - Time.now.utc).to_i
24
+ end
25
+
26
+ def expired!
27
+ self.expires_at = Time.now.utc
28
+ save!
29
+ end
30
+
31
+ private
32
+
33
+ def setup
34
+ self.token = SecureRandom.hex(32)
35
+ self.expires_at ||= default_lifetime.from_now
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Osso
4
+ module Models
5
+ class AccessToken < ::ActiveRecord::Base
6
+ include OAuth2Token
7
+ self.default_lifetime = 10.minutes
8
+ belongs_to :refresh_token
9
+
10
+ def to_bearer_token
11
+ Rack::OAuth2::AccessToken::Bearer.new(
12
+ access_token: token,
13
+ expires_in: expires_in,
14
+ )
15
+ end
16
+
17
+ private
18
+
19
+ def setup
20
+ super
21
+ return unless refresh_token
22
+
23
+ self.user = refresh_token.user
24
+ self.client = refresh_token.client
25
+ self.expires_at = [expires_at, refresh_token.expires_at].min
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Osso
4
+ module Models
5
+ class AuthorizationCode < ActiveRecord::Base
6
+ include OAuth2Token
7
+
8
+ def access_token
9
+ @access_token ||= expired! &&
10
+ user.access_tokens.create(oauth_client: oauth_client)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Osso
4
+ module Models
5
+ # Base class for Enterprises. This should map one-to-one with
6
+ # your own Account model. Persisting the EnterpriseAccount id
7
+ # in your application's database is recommended. The table also
8
+ # includes fields for external IDs such that you can persist
9
+ # your ID for an account in your Osso instance.
10
+ class EnterpriseAccount < ActiveRecord::Base
11
+ belongs_to :oauth_client
12
+ has_many :users
13
+ has_many :saml_providers
14
+
15
+ def single_provider?
16
+ saml_providers.one?
17
+ end
18
+
19
+ def provider
20
+ return nil unless single_provider?
21
+
22
+ saml_providers.first
23
+ end
24
+
25
+ alias saml_provider provider
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'sinatra/activerecord'
4
+
5
+ module Osso
6
+ module Models
7
+ end
8
+ end
9
+
10
+ require_relative 'access_token'
11
+ require_relative 'authorization_code'
12
+ require_relative 'enterprise_account'
13
+ require_relative 'oauth_client'
14
+ require_relative 'redirect_uri'
15
+ require_relative 'saml_provider'
16
+ require_relative 'user'
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+ module Osso
5
+ module Models
6
+ class OauthClient < ActiveRecord::Base
7
+ has_many :access_tokens
8
+ has_many :refresh_tokens
9
+ has_many :saml_providers
10
+ has_many :redirect_uris
11
+
12
+ before_validation :setup, on: :create
13
+ validates :name, :secret, presence: true
14
+ validates :identifier, presence: true, uniqueness: true
15
+
16
+ def default_redirect_uri
17
+ redirect_uris.find(&:primary)
18
+ end
19
+
20
+ def redirect_uri_values
21
+ redirect_uris.map(&:uri)
22
+ end
23
+
24
+ private
25
+
26
+ def setup
27
+ self.identifier = SecureRandom.hex(16)
28
+ self.secret = SecureRandom.hex(64)
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Osso
4
+ module Models
5
+ class RedirectUri < ActiveRecord::Base
6
+ belongs_to :oauth_client
7
+
8
+ # TODO
9
+ # before_validation :set_primary, on: :creaet, :update
10
+
11
+ private
12
+
13
+ def set_primary
14
+ if primary_was.true? && primary.false?
15
+
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Osso
4
+ module Models
5
+ # Base class for SAML Providers
6
+ class SamlProvider < ActiveRecord::Base
7
+ NAME_FORMAT = 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress'
8
+ self.inheritance_column = :provider
9
+ belongs_to :enterprise_account
10
+ belongs_to :oauth_client
11
+ has_many :users
12
+
13
+ before_create :create_enterprise_account
14
+
15
+ def name
16
+ raise(
17
+ NoMethodError,
18
+ '#name must be defined on each provider specific subclass',
19
+ )
20
+ end
21
+
22
+ def saml_options
23
+ raise(
24
+ NoMethodError,
25
+ '#saml_options must be defined on each provider specific subclass',
26
+ )
27
+ end
28
+
29
+ def assertion_consumer_service_url
30
+ [
31
+ ENV.fetch('BASE_URL'),
32
+ 'auth',
33
+ 'saml',
34
+ id,
35
+ 'callback',
36
+ ].join('/')
37
+ end
38
+
39
+ alias acs_url assertion_consumer_service_url
40
+
41
+ def create_enterprise_account
42
+ return if enterprise_account_id
43
+
44
+ self.enterprise_account = Models::EnterpriseAccount.create(
45
+ domain: domain,
46
+ )
47
+ end
48
+ end
49
+ end
50
+ end
51
+ require_relative 'saml_providers/azure_saml_provider'
52
+ require_relative 'saml_providers/okta_saml_provider'