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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 13dd15fc9ae37a98f93fdf432534cfb91b04ad6838e799e12e7d77354a90aa0e
4
- data.tar.gz: de98a03a7d7580e77b8a664c1bbfc6aba64ab95a46cd894bf09cdc7675d890e2
3
+ metadata.gz: c1ba94c32e61517dd429dd54e06ac24924ddb1245fff2c4dd1795d9e227972b4
4
+ data.tar.gz: bd239880638f0d8f344050c5fa92e110dc519c06e75321c28b3fa92e1860a2be
5
5
  SHA512:
6
- metadata.gz: e92e3154859aed2e787d103d473c418aefca93560fb2d23be70fe8bfeef284acbcc9debb8e425ce8cb780ae987d7ef7cea94008400235aff41496af1f5177848
7
- data.tar.gz: 62e8f00ceab23928294bdbc98f671d480e1c86886de4db9a72c8fadf48e280a250e7860669e33571c0ed761fbad37c51054c5931f06bd009f9bb499fb26f7ccd
6
+ metadata.gz: abb0e59b77e44230d47850e9e43d1a131a76694b6482706ce4d245f6832c823eeffebea468f75a4007e80ecf151271b5e9908e748e191b652c24c32984ff5c74
7
+ data.tar.gz: 12e250de2709aad8a60da53237a1489034d21f0caa05b084edabab93395266dd77060b0ad68a8d38956a9e8177315d3a35724a746aab04c438a3678194eeff4c
@@ -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
- branches: "main"
23
+ if: build.tag != null
23
24
 
24
25
  - name: "Push :rubygems:"
25
26
  commands: "./bin/publish"
26
- branches: "main"
27
+ if: build.tag != null
@@ -0,0 +1,8 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: bundler
4
+ directory: "/"
5
+ schedule:
6
+ interval: daily
7
+ labels:
8
+ - "dependencies"
@@ -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.2'
13
+ gem 'rspec', '~> 3.10'
14
14
  gem 'rubocop'
15
15
  gem 'simplecov', '= 0.17', require: false
16
- gem 'webmock', '~> 3.0'
16
+ gem 'webmock', '~> 3.11'
17
17
  end
18
18
 
19
19
  gemspec
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- osso (0.0.5)
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 (~> 2.5.0)
17
- sequel (~> 5.37.0)
18
- sequel-activerecord_connection (~> 0.3)
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.3.4)
27
- activesupport (= 6.0.3.4)
28
- activerecord (6.0.3.4)
29
- activemodel (= 6.0.3.4)
30
- activesupport (= 6.0.3.4)
31
- activesupport (6.0.3.4)
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 (>= 0.7, < 2)
34
- minitest (~> 5.1)
35
- tzinfo (~> 1.1)
36
- zeitwerk (~> 2.2, >= 2.2.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.14.0)
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.13.0)
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.19.2)
92
- parser (2.7.2.0)
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.2.0)
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.1)
114
- regexp_parser (1.8.2)
115
+ rake (13.0.3)
116
+ regexp_parser (2.0.2)
115
117
  rexml (3.2.4)
116
- roda (3.37.0)
118
+ roda (3.39.0)
117
119
  rack
118
- rodauth (2.5.0)
120
+ rodauth (2.7.0)
119
121
  roda (>= 2.6.0)
120
122
  sequel (>= 4)
121
- rspec (3.9.0)
122
- rspec-core (~> 3.9.0)
123
- rspec-expectations (~> 3.9.0)
124
- rspec-mocks (~> 3.9.0)
125
- rspec-core (3.9.3)
126
- rspec-support (~> 3.9.3)
127
- rspec-expectations (3.9.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.9.0)
130
- rspec-mocks (3.9.1)
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.9.0)
133
- rspec-support (3.9.4)
134
- rubocop (1.1.0)
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.1)
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.1.0)
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.37.0)
150
- sequel-activerecord_connection (0.4.1)
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 (1.2.7)
175
- thread_safe (~> 0.1)
176
+ tzinfo (2.0.3)
177
+ concurrent-ruby (~> 1.0)
176
178
  unicode-display_width (1.7.0)
177
- webmock (3.9.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.1)
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.2)
198
+ rspec (~> 3.10)
197
199
  rubocop
198
200
  simplecov (= 0.17)
199
- webmock (~> 3.0)
201
+ webmock (~> 3.11)
200
202
 
201
203
  BUNDLED WITH
202
204
  2.1.4
data/Rakefile CHANGED
@@ -4,6 +4,9 @@
4
4
  # to tell ActiveRecord where to find the database
5
5
  # schema and migrations
6
6
 
7
+ ENV['SESSION_SECRET'] ||= 'rake-secret'
8
+ ENV['BASE_URL'] ||= 'https://example.com'
9
+
7
10
  require 'bundler/gem_tasks'
8
11
  require 'sinatra/activerecord/rake'
9
12
  require './lib/osso'
@@ -1,6 +1,9 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
+ ENV['SESSION_SECRET'] ||= 'irb-secret'
5
+ ENV['BASE_URL'] ||= 'https://example.com'
6
+
4
7
  require 'bundler/setup'
5
8
  require 'osso'
6
9
 
@@ -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: 2020_11_12_160120) do
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.uuid "oauth_client_id"
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
@@ -2,7 +2,6 @@
2
2
 
3
3
  module Osso
4
4
  require_relative 'osso/error/error'
5
- require_relative 'osso/helpers/helpers'
6
5
  require_relative 'osso/lib/app_config'
7
6
  require_relative 'osso/lib/oauth2_token'
8
7
  require_relative 'osso/lib/route_map'
@@ -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
@@ -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['SESSION_SECRET']
10
+ use Rack::Session::Cookie, secret: ENV.fetch('SESSION_SECRET')
11
11
 
12
12
  error ActiveRecord::RecordNotFound do
13
13
  status 404
@@ -30,6 +30,7 @@ module Osso
30
30
  idp_sso_target_url: sso_url,
31
31
  idp_cert: sso_cert,
32
32
  issuer: sso_issuer,
33
+ name_identifier_format: "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
33
34
  }
34
35
  end
35
36
 
@@ -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['SESSION_SECRET']
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(rodauth.session['account_id']).
35
- context.
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
 
@@ -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
- redirect "/auth/saml/#{identity_providers.first.id}" if identity_providers.one?
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] },
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Osso
4
- VERSION = '0.0.5'
4
+ VERSION = '0.0.10'
5
5
  end
@@ -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
- rodauth = Osso::Admin.rodauth.new(Osso::Admin.new({}))
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
@@ -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', '~> 2.5.0'
30
- spec.add_runtime_dependency 'sequel', '~> 5.37.0'
31
- spec.add_runtime_dependency 'sequel-activerecord_connection', '~> 0.3'
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'
@@ -66,6 +66,7 @@ describe Osso::Models::IdentityProvider do
66
66
  idp_cert: subject.sso_cert,
67
67
  idp_sso_target_url: subject.sso_url,
68
68
  issuer: subject.sso_issuer,
69
+ name_identifier_format: "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
69
70
  )
70
71
  end
71
72
  end
@@ -4,23 +4,41 @@ require 'spec_helper'
4
4
 
5
5
  describe Osso::Admin do
6
6
  describe 'get /admin' do
7
- it 'redirects to /login without a session' do
7
+ it 'renders the admin layout' do
8
8
  get('/admin')
9
9
 
10
- expect(last_response).to be_redirect
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
- xit 'renders the admin page for a valid session token' do
16
- password = SecureRandom.urlsafe_base64(16)
17
- account = create(:verified_account, password: password)
14
+ describe 'post /graphql' do
15
+ let(:account) { create(:account) }
18
16
 
19
- post('/login', { email: account.email, password: password })
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
- get('/admin')
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
@@ -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.5
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-16 00:00:00.000000000 Z
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.5.0
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.5.0
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.37.0
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.37.0
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
@@ -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
@@ -1,8 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Osso
4
- module Helpers
5
- end
6
- end
7
-
8
- require_relative 'auth'
@@ -1,6 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
-
5
- describe 'App' do
6
- end