osso 0.0.5 → 0.0.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.buildkite/pipeline.yml +3 -2
- data/.github/dependabot.yml +8 -0
- data/.github/workflows/automerge.yml +19 -0
- data/Gemfile +2 -2
- data/Gemfile.lock +49 -47
- data/Rakefile +3 -0
- data/bin/console +3 -0
- data/db/schema.rb +2 -2
- data/lib/osso.rb +0 -1
- data/lib/osso/db/migrate/20201125143501_add_salesforce_to_provider_service_enum.rb +28 -0
- data/lib/osso/graphql/types/identity_provider_service.rb +1 -0
- data/lib/osso/lib/app_config.rb +1 -1
- data/lib/osso/models/identity_provider.rb +1 -0
- data/lib/osso/routes/admin.rb +35 -7
- data/lib/osso/routes/oauth.rb +10 -4
- data/lib/osso/version.rb +1 -1
- data/lib/tasks/bootstrap.rake +9 -2
- data/osso-rb.gemspec +3 -3
- data/spec/models/identity_provider_spec.rb +1 -0
- data/spec/routes/admin_spec.rb +27 -9
- data/spec/routes/oauth_spec.rb +14 -0
- data/spec/support/views/hosted_login.erb +1 -0
- metadata +34 -15
- data/lib/osso/helpers/auth.rb +0 -94
- data/lib/osso/helpers/helpers.rb +0 -8
- data/spec/routes/app_spec.rb +0 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c1ba94c32e61517dd429dd54e06ac24924ddb1245fff2c4dd1795d9e227972b4
|
4
|
+
data.tar.gz: bd239880638f0d8f344050c5fa92e110dc519c06e75321c28b3fa92e1860a2be
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: abb0e59b77e44230d47850e9e43d1a131a76694b6482706ce4d245f6832c823eeffebea468f75a4007e80ecf151271b5e9908e748e191b652c24c32984ff5c74
|
7
|
+
data.tar.gz: 12e250de2709aad8a60da53237a1489034d21f0caa05b084edabab93395266dd77060b0ad68a8d38956a9e8177315d3a35724a746aab04c438a3678194eeff4c
|
data/.buildkite/pipeline.yml
CHANGED
@@ -12,6 +12,7 @@ steps:
|
|
12
12
|
- coverage/*
|
13
13
|
|
14
14
|
- name: ":codeclimate:"
|
15
|
+
soft_fail: true
|
15
16
|
plugins:
|
16
17
|
- jobready/codeclimate-test-reporter#v2.0:
|
17
18
|
artifact: "coverage/.resultset.json"
|
@@ -19,8 +20,8 @@ steps:
|
|
19
20
|
prefix: '/var/lib/buildkite-agent/builds/enterprise-oss-bk-1/enterpriseoss/osso-rb/'
|
20
21
|
|
21
22
|
- block: ":rubygems: Publish :red_button:"
|
22
|
-
|
23
|
+
if: build.tag != null
|
23
24
|
|
24
25
|
- name: "Push :rubygems:"
|
25
26
|
commands: "./bin/publish"
|
26
|
-
|
27
|
+
if: build.tag != null
|
@@ -0,0 +1,19 @@
|
|
1
|
+
name: auto-merge
|
2
|
+
|
3
|
+
on:
|
4
|
+
pull_request:
|
5
|
+
|
6
|
+
jobs:
|
7
|
+
auto-approve:
|
8
|
+
runs-on: ubuntu-latest
|
9
|
+
steps:
|
10
|
+
- uses: actions/checkout@v2
|
11
|
+
- uses: ahmadnassri/action-dependabot-auto-merge@v2
|
12
|
+
with:
|
13
|
+
target: minor
|
14
|
+
github-token: ${{ secrets.TOKEN }}
|
15
|
+
- uses: hmarr/auto-approve-action@v2.0.0
|
16
|
+
if: github.actor == 'dependabot[bot]'
|
17
|
+
with:
|
18
|
+
github-token: "${{ secrets.TOKEN }}"
|
19
|
+
|
data/Gemfile
CHANGED
@@ -10,10 +10,10 @@ group :test do
|
|
10
10
|
gem 'faker'
|
11
11
|
gem 'pg'
|
12
12
|
gem 'rack-test'
|
13
|
-
gem 'rspec', '~> 3.
|
13
|
+
gem 'rspec', '~> 3.10'
|
14
14
|
gem 'rubocop'
|
15
15
|
gem 'simplecov', '= 0.17', require: false
|
16
|
-
gem 'webmock', '~> 3.
|
16
|
+
gem 'webmock', '~> 3.11'
|
17
17
|
end
|
18
18
|
|
19
19
|
gemspec
|
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.9)
|
5
5
|
activesupport (>= 6.0.3.2)
|
6
6
|
bcrypt (~> 3.1.13)
|
7
7
|
graphql
|
@@ -13,9 +13,9 @@ PATH
|
|
13
13
|
rack-contrib
|
14
14
|
rack-oauth2
|
15
15
|
rake
|
16
|
-
rodauth (
|
17
|
-
sequel (
|
18
|
-
sequel-activerecord_connection (
|
16
|
+
rodauth (>= 2.6, < 2.8)
|
17
|
+
sequel (>= 5.37, < 5.40)
|
18
|
+
sequel-activerecord_connection (>= 0.3, < 2.0)
|
19
19
|
sinatra
|
20
20
|
sinatra-activerecord
|
21
21
|
sinatra-contrib
|
@@ -23,20 +23,22 @@ PATH
|
|
23
23
|
GEM
|
24
24
|
remote: https://rubygems.org/
|
25
25
|
specs:
|
26
|
-
activemodel (6.0
|
27
|
-
activesupport (= 6.0
|
28
|
-
activerecord (6.0
|
29
|
-
activemodel (= 6.0
|
30
|
-
activesupport (= 6.0
|
31
|
-
activesupport (6.0
|
26
|
+
activemodel (6.1.0)
|
27
|
+
activesupport (= 6.1.0)
|
28
|
+
activerecord (6.1.0)
|
29
|
+
activemodel (= 6.1.0)
|
30
|
+
activesupport (= 6.1.0)
|
31
|
+
activesupport (6.1.0)
|
32
32
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
33
|
-
i18n (>=
|
34
|
-
minitest (
|
35
|
-
tzinfo (~>
|
36
|
-
zeitwerk (~> 2.
|
33
|
+
i18n (>= 1.6, < 2)
|
34
|
+
minitest (>= 5.1)
|
35
|
+
tzinfo (~> 2.0)
|
36
|
+
zeitwerk (~> 2.3)
|
37
37
|
addressable (2.7.0)
|
38
38
|
public_suffix (>= 2.0.2, < 5.0)
|
39
39
|
aes_key_wrap (1.1.0)
|
40
|
+
after_commit_everywhere (0.1.5)
|
41
|
+
activerecord (>= 4.2)
|
40
42
|
annotate (3.1.1)
|
41
43
|
activerecord (>= 3.2, < 7.0)
|
42
44
|
rake (>= 10.4, < 14.0)
|
@@ -55,7 +57,7 @@ GEM
|
|
55
57
|
docile (1.3.2)
|
56
58
|
factory_bot (6.1.0)
|
57
59
|
activesupport (>= 5.0.0)
|
58
|
-
faker (2.
|
60
|
+
faker (2.15.1)
|
59
61
|
i18n (>= 1.6, < 2)
|
60
62
|
graphql (1.11.6)
|
61
63
|
hashdiff (1.0.1)
|
@@ -64,7 +66,7 @@ GEM
|
|
64
66
|
i18n (1.8.5)
|
65
67
|
concurrent-ruby (~> 1.0)
|
66
68
|
json (2.3.1)
|
67
|
-
json-jwt (1.
|
69
|
+
json-jwt (1.12.0)
|
68
70
|
activesupport (>= 4.2)
|
69
71
|
aes_key_wrap
|
70
72
|
bindata
|
@@ -88,8 +90,8 @@ GEM
|
|
88
90
|
omniauth-saml (1.10.3)
|
89
91
|
omniauth (~> 1.3, >= 1.3.2)
|
90
92
|
ruby-saml (~> 1.9)
|
91
|
-
parallel (1.
|
92
|
-
parser (
|
93
|
+
parallel (1.20.1)
|
94
|
+
parser (3.0.0.0)
|
93
95
|
ast (~> 2.4.1)
|
94
96
|
pg (1.2.3)
|
95
97
|
pry (0.13.1)
|
@@ -97,7 +99,7 @@ GEM
|
|
97
99
|
method_source (~> 1.0)
|
98
100
|
public_suffix (4.0.6)
|
99
101
|
rack (2.2.3)
|
100
|
-
rack-contrib (2.
|
102
|
+
rack-contrib (2.3.0)
|
101
103
|
rack (~> 2.0)
|
102
104
|
rack-oauth2 (1.16.0)
|
103
105
|
activesupport
|
@@ -110,45 +112,46 @@ GEM
|
|
110
112
|
rack-test (1.1.0)
|
111
113
|
rack (>= 1.0, < 3)
|
112
114
|
rainbow (3.0.0)
|
113
|
-
rake (13.0.
|
114
|
-
regexp_parser (
|
115
|
+
rake (13.0.3)
|
116
|
+
regexp_parser (2.0.2)
|
115
117
|
rexml (3.2.4)
|
116
|
-
roda (3.
|
118
|
+
roda (3.39.0)
|
117
119
|
rack
|
118
|
-
rodauth (2.
|
120
|
+
rodauth (2.7.0)
|
119
121
|
roda (>= 2.6.0)
|
120
122
|
sequel (>= 4)
|
121
|
-
rspec (3.
|
122
|
-
rspec-core (~> 3.
|
123
|
-
rspec-expectations (~> 3.
|
124
|
-
rspec-mocks (~> 3.
|
125
|
-
rspec-core (3.
|
126
|
-
rspec-support (~> 3.
|
127
|
-
rspec-expectations (3.
|
123
|
+
rspec (3.10.0)
|
124
|
+
rspec-core (~> 3.10.0)
|
125
|
+
rspec-expectations (~> 3.10.0)
|
126
|
+
rspec-mocks (~> 3.10.0)
|
127
|
+
rspec-core (3.10.0)
|
128
|
+
rspec-support (~> 3.10.0)
|
129
|
+
rspec-expectations (3.10.0)
|
128
130
|
diff-lcs (>= 1.2.0, < 2.0)
|
129
|
-
rspec-support (~> 3.
|
130
|
-
rspec-mocks (3.
|
131
|
+
rspec-support (~> 3.10.0)
|
132
|
+
rspec-mocks (3.10.0)
|
131
133
|
diff-lcs (>= 1.2.0, < 2.0)
|
132
|
-
rspec-support (~> 3.
|
133
|
-
rspec-support (3.
|
134
|
-
rubocop (1.
|
134
|
+
rspec-support (~> 3.10.0)
|
135
|
+
rspec-support (3.10.0)
|
136
|
+
rubocop (1.7.0)
|
135
137
|
parallel (~> 1.10)
|
136
138
|
parser (>= 2.7.1.5)
|
137
139
|
rainbow (>= 2.2.2, < 4.0)
|
138
|
-
regexp_parser (>= 1.8)
|
140
|
+
regexp_parser (>= 1.8, < 3.0)
|
139
141
|
rexml
|
140
|
-
rubocop-ast (>= 1.0.
|
142
|
+
rubocop-ast (>= 1.2.0, < 2.0)
|
141
143
|
ruby-progressbar (~> 1.7)
|
142
144
|
unicode-display_width (>= 1.4.0, < 2.0)
|
143
|
-
rubocop-ast (1.
|
145
|
+
rubocop-ast (1.3.0)
|
144
146
|
parser (>= 2.7.1.5)
|
145
147
|
ruby-progressbar (1.10.1)
|
146
148
|
ruby-saml (1.11.0)
|
147
149
|
nokogiri (>= 1.5.10)
|
148
150
|
ruby2_keywords (0.0.2)
|
149
|
-
sequel (5.
|
150
|
-
sequel-activerecord_connection (
|
151
|
+
sequel (5.39.0)
|
152
|
+
sequel-activerecord_connection (1.2.0)
|
151
153
|
activerecord (>= 4.2, < 7)
|
154
|
+
after_commit_everywhere (~> 0.1.5)
|
152
155
|
sequel (~> 5.16)
|
153
156
|
simplecov (0.17.0)
|
154
157
|
docile (~> 1.1)
|
@@ -169,16 +172,15 @@ GEM
|
|
169
172
|
rack-protection (= 2.1.0)
|
170
173
|
sinatra (= 2.1.0)
|
171
174
|
tilt (~> 2.0)
|
172
|
-
thread_safe (0.3.6)
|
173
175
|
tilt (2.0.10)
|
174
|
-
tzinfo (
|
175
|
-
|
176
|
+
tzinfo (2.0.3)
|
177
|
+
concurrent-ruby (~> 1.0)
|
176
178
|
unicode-display_width (1.7.0)
|
177
|
-
webmock (3.
|
179
|
+
webmock (3.11.0)
|
178
180
|
addressable (>= 2.3.6)
|
179
181
|
crack (>= 0.3.2)
|
180
182
|
hashdiff (>= 0.4.0, < 2.0.0)
|
181
|
-
zeitwerk (2.4.
|
183
|
+
zeitwerk (2.4.2)
|
182
184
|
|
183
185
|
PLATFORMS
|
184
186
|
ruby
|
@@ -193,10 +195,10 @@ DEPENDENCIES
|
|
193
195
|
pg
|
194
196
|
pry
|
195
197
|
rack-test
|
196
|
-
rspec (~> 3.
|
198
|
+
rspec (~> 3.10)
|
197
199
|
rubocop
|
198
200
|
simplecov (= 0.17)
|
199
|
-
webmock (~> 3.
|
201
|
+
webmock (~> 3.11)
|
200
202
|
|
201
203
|
BUNDLED WITH
|
202
204
|
2.1.4
|
data/Rakefile
CHANGED
data/bin/console
CHANGED
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_11_25_143501) do
|
14
14
|
|
15
15
|
# These are extensions that must be enabled in order to support this database
|
16
16
|
enable_extension "citext"
|
@@ -57,7 +57,7 @@ ActiveRecord::Schema.define(version: 2020_11_12_160120) do
|
|
57
57
|
t.citext "email", null: false
|
58
58
|
t.integer "status_id", default: 1, null: false
|
59
59
|
t.string "role", default: "admin", null: false
|
60
|
-
t.
|
60
|
+
t.string "oauth_client_id"
|
61
61
|
t.index ["email"], name: "index_accounts_on_email", unique: true, where: "(status_id = ANY (ARRAY[1, 2]))"
|
62
62
|
t.index ["oauth_client_id"], name: "index_accounts_on_oauth_client_id"
|
63
63
|
end
|
data/lib/osso.rb
CHANGED
@@ -0,0 +1,28 @@
|
|
1
|
+
class AddSalesforceToProviderServiceEnum < ActiveRecord::Migration[6.0]
|
2
|
+
disable_ddl_transaction!
|
3
|
+
|
4
|
+
def up
|
5
|
+
execute <<-SQL
|
6
|
+
ALTER TYPE identity_provider_service ADD VALUE 'SALESFORCE';
|
7
|
+
SQL
|
8
|
+
end
|
9
|
+
|
10
|
+
def down
|
11
|
+
execute <<~SQL
|
12
|
+
CREATE TYPE identity_provider_service_new AS ENUM ('AZURE', 'OKTA', 'ONELOGIN', 'GOOGLE', 'PING');
|
13
|
+
|
14
|
+
-- Remove values that won't be compatible with new definition
|
15
|
+
DELETE FROM identity_providers WHERE service = 'SALESFORCE';
|
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
|
@@ -9,6 +9,7 @@ module Osso
|
|
9
9
|
value('OKTA', 'Okta Identity Provider', value: 'OKTA')
|
10
10
|
value('ONELOGIN', 'OneLogin Identity Provider', value: 'ONELOGIN')
|
11
11
|
value('PING', 'PingID Identity Provider', value: 'PING')
|
12
|
+
value('SALESFORCE', 'Salesforce Identity Provider', value: 'SALESFORCE')
|
12
13
|
end
|
13
14
|
end
|
14
15
|
end
|
data/lib/osso/lib/app_config.rb
CHANGED
@@ -7,7 +7,7 @@ module Osso
|
|
7
7
|
def self.included(klass)
|
8
8
|
klass.class_eval do
|
9
9
|
use Rack::JSONBodyParser
|
10
|
-
use Rack::Session::Cookie, secret: ENV
|
10
|
+
use Rack::Session::Cookie, secret: ENV.fetch('SESSION_SECRET')
|
11
11
|
|
12
12
|
error ActiveRecord::RecordNotFound do
|
13
13
|
status 404
|
data/lib/osso/routes/admin.rb
CHANGED
@@ -8,18 +8,43 @@ DEFAULT_VIEWS_DIR = File.join(File.expand_path(Bundler.root), 'views/rodauth')
|
|
8
8
|
module Osso
|
9
9
|
class Admin < Roda
|
10
10
|
DB = Sequel.postgres(extensions: :activerecord_connection)
|
11
|
-
use Rack::Session::Cookie, secret: ENV
|
12
|
-
|
11
|
+
use Rack::Session::Cookie, secret: ENV.fetch('SESSION_SECRET')
|
12
|
+
|
13
|
+
plugin :json
|
13
14
|
plugin :middleware
|
14
15
|
plugin :render, engine: 'erb', views: ENV['RODAUTH_VIEWS'] || DEFAULT_VIEWS_DIR
|
15
16
|
plugin :route_csrf
|
16
17
|
|
17
18
|
plugin :rodauth do
|
18
|
-
enable :login, :verify_account
|
19
|
+
enable :login, :verify_account, :jwt
|
20
|
+
|
21
|
+
base_uri = URI.parse(ENV.fetch('BASE_URL'))
|
22
|
+
base_url base_uri
|
23
|
+
domain base_uri.host
|
24
|
+
|
25
|
+
jwt_secret ENV.fetch('SESSION_SECRET')
|
26
|
+
only_json? false
|
27
|
+
|
28
|
+
email_from { "Osso <no-reply@#{domain}>" }
|
19
29
|
verify_account_set_password? true
|
20
|
-
already_logged_in { redirect login_redirect }
|
21
30
|
use_database_authentication_functions? false
|
22
31
|
|
32
|
+
verify_account_view do
|
33
|
+
render :admin
|
34
|
+
end
|
35
|
+
|
36
|
+
login_view do
|
37
|
+
render :admin
|
38
|
+
end
|
39
|
+
|
40
|
+
verify_account_email_subject do
|
41
|
+
DB[:accounts].one? ? 'Your Osso instance is ready' : 'You\'ve been invited to start using Osso'
|
42
|
+
end
|
43
|
+
|
44
|
+
verify_account_email_body do
|
45
|
+
DB[:accounts].one? ? render('verify-first-account-email') : render('verify-account-email')
|
46
|
+
end
|
47
|
+
|
23
48
|
before_create_account_route do
|
24
49
|
request.halt unless DB[:accounts].empty?
|
25
50
|
end
|
@@ -31,13 +56,16 @@ module Osso
|
|
31
56
|
r.rodauth
|
32
57
|
|
33
58
|
def current_account
|
34
|
-
Osso::Models::Account.find(
|
35
|
-
|
59
|
+
Osso::Models::Account.find(
|
60
|
+
rodauth.
|
61
|
+
session.
|
62
|
+
to_hash.
|
63
|
+
stringify_keys['account_id']
|
64
|
+
).context.
|
36
65
|
merge({ rodauth: rodauth })
|
37
66
|
end
|
38
67
|
|
39
68
|
r.on 'admin' do
|
40
|
-
rodauth.require_authentication
|
41
69
|
erb :admin, layout: false
|
42
70
|
end
|
43
71
|
|
data/lib/osso/routes/oauth.rb
CHANGED
@@ -16,13 +16,14 @@ 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
|
-
identity_providers = find_providers
|
20
|
-
|
21
19
|
validate_oauth_request(env)
|
22
20
|
|
23
|
-
|
21
|
+
return erb :hosted_login if render_hosted_login?
|
22
|
+
|
23
|
+
@providers = find_providers
|
24
|
+
|
25
|
+
redirect "/auth/saml/#{@providers.first.id}" if @providers.one?
|
24
26
|
|
25
|
-
@providers = identity_providers.not_pending
|
26
27
|
return erb :multiple_providers if @providers.count > 1
|
27
28
|
|
28
29
|
raise Osso::Error::MissingConfiguredIdentityProvider.new(domain: params[:domain])
|
@@ -61,6 +62,10 @@ module Osso
|
|
61
62
|
|
62
63
|
private
|
63
64
|
|
65
|
+
def render_hosted_login?
|
66
|
+
[params[:email], params[:domain]].all?(&:nil?)
|
67
|
+
end
|
68
|
+
|
64
69
|
def find_providers
|
65
70
|
if params[:email]
|
66
71
|
user = Osso::Models::User.
|
@@ -71,6 +76,7 @@ module Osso
|
|
71
76
|
|
72
77
|
Osso::Models::IdentityProvider.
|
73
78
|
joins(:oauth_client).
|
79
|
+
not_pending.
|
74
80
|
where(
|
75
81
|
domain: domain_from_params,
|
76
82
|
oauth_clients: { identifier: params[:client_id] },
|
data/lib/osso/version.rb
CHANGED
data/lib/tasks/bootstrap.rake
CHANGED
@@ -18,13 +18,20 @@ namespace :osso do
|
|
18
18
|
admin_email = ENV['ADMIN_EMAIL']
|
19
19
|
|
20
20
|
if admin_email
|
21
|
-
admin = Osso::Models::Account.create
|
21
|
+
admin = Osso::Models::Account.create(
|
22
22
|
email: admin_email,
|
23
23
|
status_id: 1,
|
24
24
|
role: 'admin',
|
25
25
|
)
|
26
26
|
|
27
|
-
|
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
|
+
|
28
35
|
account = rodauth.account_from_login(admin_email)
|
29
36
|
rodauth.setup_account_verification
|
30
37
|
end
|
data/osso-rb.gemspec
CHANGED
@@ -26,9 +26,9 @@ Gem::Specification.new do |spec|
|
|
26
26
|
spec.add_runtime_dependency 'rack-contrib'
|
27
27
|
spec.add_runtime_dependency 'rack-oauth2'
|
28
28
|
spec.add_runtime_dependency 'rake'
|
29
|
-
spec.add_runtime_dependency 'rodauth', '
|
30
|
-
spec.add_runtime_dependency 'sequel', '
|
31
|
-
spec.add_runtime_dependency 'sequel-activerecord_connection', '
|
29
|
+
spec.add_runtime_dependency 'rodauth', '>= 2.6', '< 2.8'
|
30
|
+
spec.add_runtime_dependency 'sequel', '>= 5.37', '< 5.40'
|
31
|
+
spec.add_runtime_dependency 'sequel-activerecord_connection', '>= 0.3', '< 2.0'
|
32
32
|
spec.add_runtime_dependency 'sinatra'
|
33
33
|
spec.add_runtime_dependency 'sinatra-activerecord'
|
34
34
|
spec.add_runtime_dependency 'sinatra-contrib'
|
data/spec/routes/admin_spec.rb
CHANGED
@@ -4,23 +4,41 @@ require 'spec_helper'
|
|
4
4
|
|
5
5
|
describe Osso::Admin do
|
6
6
|
describe 'get /admin' do
|
7
|
-
it '
|
7
|
+
it 'renders the admin layout' do
|
8
8
|
get('/admin')
|
9
9
|
|
10
|
-
expect(last_response).to
|
11
|
-
follow_redirect!
|
12
|
-
expect(last_request.url).to match('/login')
|
10
|
+
expect(last_response).to be_ok
|
13
11
|
end
|
12
|
+
end
|
14
13
|
|
15
|
-
|
16
|
-
|
17
|
-
account = create(:verified_account, password: password)
|
14
|
+
describe 'post /graphql' do
|
15
|
+
let(:account) { create(:account) }
|
18
16
|
|
19
|
-
|
17
|
+
it 'runs a GraphQL query with a valid jwt' do
|
18
|
+
allow_any_instance_of(described_class.rodauth).to receive(:logged_in?).and_return(true)
|
19
|
+
allow(Osso::Models::Account).to receive(:find).and_return(account)
|
20
|
+
allow(Osso::GraphQL::Schema).to receive(:execute).and_return({graphql: true})
|
20
21
|
|
21
|
-
|
22
|
+
header 'Content-Type', 'application/json'
|
23
|
+
post("/graphql")
|
22
24
|
|
23
25
|
expect(last_response).to be_ok
|
26
|
+
expect(last_json_response).to eq({graphql: true})
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'returns a 400 for an invalid jwt' do
|
30
|
+
header 'Content-Type', 'application/json'
|
31
|
+
header 'Authorization', 'Bearer bad-token'
|
32
|
+
post("/graphql")
|
33
|
+
|
34
|
+
expect(last_response.status).to eq 400
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'returns a 401 without a jwt' do
|
38
|
+
header 'Content-Type', 'application/json'
|
39
|
+
post("/graphql")
|
40
|
+
|
41
|
+
expect(last_response.status).to eq 401
|
24
42
|
end
|
25
43
|
end
|
26
44
|
end
|
data/spec/routes/oauth_spec.rb
CHANGED
@@ -27,6 +27,20 @@ describe Osso::Oauth do
|
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
+
describe 'for a request without email or domain' do
|
31
|
+
it 'redirects to /auth/saml/:provider_id' do
|
32
|
+
get(
|
33
|
+
'/oauth/authorize',
|
34
|
+
client_id: client.identifier,
|
35
|
+
response_type: 'code',
|
36
|
+
redirect_uri: client.redirect_uri_values.sample,
|
37
|
+
)
|
38
|
+
|
39
|
+
expect(last_response).to be_ok
|
40
|
+
expect(last_response.body).to eq('HOSTED LOGIN')
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
30
44
|
describe 'for an enterprise domain with one SAML provider' do
|
31
45
|
it 'redirects to /auth/saml/:provider_id' do
|
32
46
|
enterprise = create(:enterprise_with_okta, oauth_client: client)
|
@@ -0,0 +1 @@
|
|
1
|
+
HOSTED LOGIN
|
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.10
|
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-12-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -168,44 +168,62 @@ dependencies:
|
|
168
168
|
name: rodauth
|
169
169
|
requirement: !ruby/object:Gem::Requirement
|
170
170
|
requirements:
|
171
|
-
- - "
|
171
|
+
- - ">="
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '2.6'
|
174
|
+
- - "<"
|
172
175
|
- !ruby/object:Gem::Version
|
173
|
-
version: 2.
|
176
|
+
version: '2.8'
|
174
177
|
type: :runtime
|
175
178
|
prerelease: false
|
176
179
|
version_requirements: !ruby/object:Gem::Requirement
|
177
180
|
requirements:
|
178
|
-
- - "
|
181
|
+
- - ">="
|
179
182
|
- !ruby/object:Gem::Version
|
180
|
-
version: 2.
|
183
|
+
version: '2.6'
|
184
|
+
- - "<"
|
185
|
+
- !ruby/object:Gem::Version
|
186
|
+
version: '2.8'
|
181
187
|
- !ruby/object:Gem::Dependency
|
182
188
|
name: sequel
|
183
189
|
requirement: !ruby/object:Gem::Requirement
|
184
190
|
requirements:
|
185
|
-
- - "
|
191
|
+
- - ">="
|
192
|
+
- !ruby/object:Gem::Version
|
193
|
+
version: '5.37'
|
194
|
+
- - "<"
|
186
195
|
- !ruby/object:Gem::Version
|
187
|
-
version: 5.
|
196
|
+
version: '5.40'
|
188
197
|
type: :runtime
|
189
198
|
prerelease: false
|
190
199
|
version_requirements: !ruby/object:Gem::Requirement
|
191
200
|
requirements:
|
192
|
-
- - "
|
201
|
+
- - ">="
|
202
|
+
- !ruby/object:Gem::Version
|
203
|
+
version: '5.37'
|
204
|
+
- - "<"
|
193
205
|
- !ruby/object:Gem::Version
|
194
|
-
version: 5.
|
206
|
+
version: '5.40'
|
195
207
|
- !ruby/object:Gem::Dependency
|
196
208
|
name: sequel-activerecord_connection
|
197
209
|
requirement: !ruby/object:Gem::Requirement
|
198
210
|
requirements:
|
199
|
-
- - "
|
211
|
+
- - ">="
|
200
212
|
- !ruby/object:Gem::Version
|
201
213
|
version: '0.3'
|
214
|
+
- - "<"
|
215
|
+
- !ruby/object:Gem::Version
|
216
|
+
version: '2.0'
|
202
217
|
type: :runtime
|
203
218
|
prerelease: false
|
204
219
|
version_requirements: !ruby/object:Gem::Requirement
|
205
220
|
requirements:
|
206
|
-
- - "
|
221
|
+
- - ">="
|
207
222
|
- !ruby/object:Gem::Version
|
208
223
|
version: '0.3'
|
224
|
+
- - "<"
|
225
|
+
- !ruby/object:Gem::Version
|
226
|
+
version: '2.0'
|
209
227
|
- !ruby/object:Gem::Dependency
|
210
228
|
name: sinatra
|
211
229
|
requirement: !ruby/object:Gem::Requirement
|
@@ -305,6 +323,8 @@ files:
|
|
305
323
|
- ".buildkite/hooks/pre-command"
|
306
324
|
- ".buildkite/pipeline.yml"
|
307
325
|
- ".buildkite/template.yml"
|
326
|
+
- ".github/dependabot.yml"
|
327
|
+
- ".github/workflows/automerge.yml"
|
308
328
|
- ".gitignore"
|
309
329
|
- ".rspec"
|
310
330
|
- ".rubocop.yml"
|
@@ -350,6 +370,7 @@ files:
|
|
350
370
|
- lib/osso/db/migrate/20201109160851_add_sso_issuer_to_identity_providers.rb
|
351
371
|
- lib/osso/db/migrate/20201110190754_remove_oauth_client_id_from_enterprise_accounts.rb
|
352
372
|
- lib/osso/db/migrate/20201112160120_add_ping_to_identity_provider_service_enum.rb
|
373
|
+
- lib/osso/db/migrate/20201125143501_add_salesforce_to_provider_service_enum.rb
|
353
374
|
- lib/osso/error/account_configuration_error.rb
|
354
375
|
- lib/osso/error/error.rb
|
355
376
|
- lib/osso/error/missing_saml_attribute_error.rb
|
@@ -392,8 +413,6 @@ files:
|
|
392
413
|
- lib/osso/graphql/types/oauth_client.rb
|
393
414
|
- lib/osso/graphql/types/redirect_uri.rb
|
394
415
|
- lib/osso/graphql/types/redirect_uri_input.rb
|
395
|
-
- lib/osso/helpers/auth.rb
|
396
|
-
- lib/osso/helpers/helpers.rb
|
397
416
|
- lib/osso/lib/app_config.rb
|
398
417
|
- lib/osso/lib/oauth2_token.rb
|
399
418
|
- lib/osso/lib/route_map.rb
|
@@ -442,7 +461,6 @@ files:
|
|
442
461
|
- spec/models/enterprise_account_spec.rb
|
443
462
|
- spec/models/identity_provider_spec.rb
|
444
463
|
- spec/routes/admin_spec.rb
|
445
|
-
- spec/routes/app_spec.rb
|
446
464
|
- spec/routes/auth_spec.rb
|
447
465
|
- spec/routes/oauth_spec.rb
|
448
466
|
- spec/spec_helper.rb
|
@@ -450,6 +468,7 @@ files:
|
|
450
468
|
- spec/support/spec_app.rb
|
451
469
|
- spec/support/views/admin.erb
|
452
470
|
- spec/support/views/error.erb
|
471
|
+
- spec/support/views/hosted_login.erb
|
453
472
|
- spec/support/views/layout.erb
|
454
473
|
- spec/support/views/multiple_providers.erb
|
455
474
|
homepage: https://github.com/enterprise-oss/osso-rb
|
data/lib/osso/helpers/auth.rb
DELETED
@@ -1,94 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Osso
|
4
|
-
module Helpers
|
5
|
-
module Auth
|
6
|
-
END_USER_SCOPE = 'end-user'
|
7
|
-
INTERNAL_SCOPE = 'internal'
|
8
|
-
ADMIN_SCOPE = 'admin'
|
9
|
-
|
10
|
-
attr_accessor :current_user
|
11
|
-
|
12
|
-
def token_protected!
|
13
|
-
decode(token)
|
14
|
-
rescue JWT::DecodeError
|
15
|
-
halt 401
|
16
|
-
end
|
17
|
-
|
18
|
-
def enterprise_protected!(domain = nil)
|
19
|
-
return if admin_authorized?
|
20
|
-
return if internal_authorized?
|
21
|
-
return if enterprise_authorized?(domain)
|
22
|
-
|
23
|
-
halt 401 if request.post?
|
24
|
-
|
25
|
-
redirect ENV['JWT_URL']
|
26
|
-
end
|
27
|
-
|
28
|
-
def internal_protected!
|
29
|
-
return if admin_authorized?
|
30
|
-
return if internal_authorized?
|
31
|
-
|
32
|
-
redirect ENV['JWT_URL']
|
33
|
-
end
|
34
|
-
|
35
|
-
def admin_protected!
|
36
|
-
return true if admin_authorized?
|
37
|
-
|
38
|
-
redirect ENV['JWT_URL']
|
39
|
-
end
|
40
|
-
|
41
|
-
private
|
42
|
-
|
43
|
-
def enterprise_authorized?(domain)
|
44
|
-
decode(token)
|
45
|
-
|
46
|
-
@current_user[:scope] == END_USER_SCOPE &&
|
47
|
-
@current_user[:email].split('@')[1] == domain
|
48
|
-
rescue JWT::DecodeError
|
49
|
-
false
|
50
|
-
end
|
51
|
-
|
52
|
-
def internal_authorized?
|
53
|
-
decode(token)
|
54
|
-
|
55
|
-
@current_user[:scope] == INTERNAL_SCOPE
|
56
|
-
rescue JWT::DecodeError
|
57
|
-
false
|
58
|
-
end
|
59
|
-
|
60
|
-
def admin_authorized?
|
61
|
-
decode(token)
|
62
|
-
|
63
|
-
@current_user[:scope] == ADMIN_SCOPE
|
64
|
-
rescue JWT::DecodeError
|
65
|
-
false
|
66
|
-
end
|
67
|
-
|
68
|
-
def token
|
69
|
-
session['admin_token'] || request.env['HTTP_AUTHORIZATION'] || request.params['admin_token']
|
70
|
-
end
|
71
|
-
|
72
|
-
def chomp_token
|
73
|
-
return unless request['admin_token'].present?
|
74
|
-
|
75
|
-
session['admin_token'] = request['admin_token']
|
76
|
-
|
77
|
-
return if request.post?
|
78
|
-
|
79
|
-
redirect request.path
|
80
|
-
end
|
81
|
-
|
82
|
-
def decode(token)
|
83
|
-
payload, _args = JWT.decode(
|
84
|
-
token,
|
85
|
-
ENV['JWT_HMAC_SECRET'],
|
86
|
-
true,
|
87
|
-
{ algorithm: 'HS256' },
|
88
|
-
)
|
89
|
-
|
90
|
-
@current_user = payload.symbolize_keys
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
data/lib/osso/helpers/helpers.rb
DELETED