osso 0.0.5 → 0.0.10

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 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