gds-sso 17.1.1 → 18.0.0

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: 299db37f74135bea6ee6479680dc31be21a3aab23a661ce27548f566829dd1d2
4
- data.tar.gz: c440c23020cc6fd40294ccdb69031e6ea163ff29f3d33c8755fe7c725d4c24d3
3
+ metadata.gz: 6450ab2114242674c0c5f9ddeba9d15cca06e538f2f211a1c621469f9fd2d9af
4
+ data.tar.gz: eedc4aaa3abd89833c43af03c841f63dc6d68f9fbbd965a15aa917bc20ad933a
5
5
  SHA512:
6
- metadata.gz: 1e6fead794241c45cdc8a0e23fd1734b11c8e1edad85d3eef4d56867d0bacbed944b1d083745c24573c5886df35f3f4d07d39c3a14966c0840a06736c0ebb548
7
- data.tar.gz: 16850d916b1b8e0cfb2a974f171e3eb5c7625ef88b1a4abe4ec59bc5edcf90579b231890297f276974b5dd233ae45dd7c4184ca5324617558ab44f3529210bde
6
+ metadata.gz: cfe330d97944bac31202779575770107056ca493ac5af511eb5fb316bbd4a83b459367dd683d69c01656c3e446177dabd008e47cf6d83138f29f139b7e765374
7
+ data.tar.gz: 01b11032563802c91717c6418150dafadd4518f95845c938bb6ad855895971d541f1a95d59cddae92060e4896ec6fdea6620af24a72515cd9fb79074d705c3c3
data/README.md CHANGED
@@ -177,12 +177,6 @@ Run the tests with:
177
177
  bundle exec rake
178
178
  ```
179
179
 
180
- By default, the tests use the master of [Signon](https://github.com/alphagov/signon) for running integration tests. If you want to use a branch (or commit, or tag), you can run it like this:
181
-
182
- ```
183
- SIGNON_COMMITISH=my_branch_name bundle exec rake
184
- ```
185
-
186
180
  ## Licence
187
181
 
188
182
  [MIT License](LICENCE)
@@ -6,6 +6,7 @@ module GDS
6
6
  config.cache = Rails.cache
7
7
  config.api_only = Rails.configuration.api_only
8
8
  end
9
+ OmniAuth.config.logger = Rails.logger
9
10
  end
10
11
  end
11
12
  end
@@ -1,5 +1,5 @@
1
1
  module GDS
2
2
  module SSO
3
- VERSION = "17.1.1".freeze
3
+ VERSION = "18.0.0".freeze
4
4
  end
5
5
  end
@@ -1,7 +1,8 @@
1
1
  class ExampleController < ApplicationController
2
- before_action :authenticate_user!, only: %i[restricted this_requires_signin_permission]
2
+ before_action :authenticate_user!, except: :not_restricted
3
+ before_action -> { authorise_user!("execute") }, only: :this_requires_execute_permission
3
4
 
4
- def index
5
+ def not_restricted
5
6
  render body: "jabberwocky"
6
7
  end
7
8
 
@@ -9,7 +10,7 @@ class ExampleController < ApplicationController
9
10
  render body: "restricted kablooie"
10
11
  end
11
12
 
12
- def this_requires_signin_permission
13
- render body: "you have signin permission"
13
+ def this_requires_execute_permission
14
+ render body: "you have execute permission"
14
15
  end
15
16
  end
@@ -2,5 +2,5 @@ GDS::SSO.config do |config|
2
2
  config.user_model = "User"
3
3
  config.oauth_id = "gds-sso-test"
4
4
  config.oauth_secret = "secret"
5
- config.oauth_root_url = "http://localhost:4567"
5
+ config.oauth_root_url = "http://signon"
6
6
  end
@@ -1,8 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  Rails.application.routes.draw do
4
- # Add your own routes here, or remove this file if you don't have need for it.
5
- root to: "example#index"
4
+ get "/not-restricted" => "example#not_restricted"
6
5
  get "/restricted" => "example#restricted"
7
- get "/this_requires_signin_permission" => "example#this_requires_signin_permission"
6
+ get "/this-requires-execute-permission" => "example#this_requires_execute_permission"
8
7
  end
data/spec/spec_helper.rb CHANGED
@@ -2,22 +2,28 @@
2
2
  # Bad things happen if we don't ;-)
3
3
  ENV["GDS_SSO_STRATEGY"] = "real"
4
4
 
5
- require "bundler/setup"
6
- require "combustion"
7
5
  require "capybara/rspec"
6
+ require "webmock/rspec"
7
+ require "combustion"
8
8
 
9
- Combustion.initialize! :all
9
+ Combustion.initialize! :all do
10
+ config.cache_store = :null_store
11
+ end
10
12
 
11
13
  require "rspec/rails"
12
14
  require "capybara/rails"
13
- require "mechanize"
14
- require "capybara/mechanize"
15
+ WebMock.disable_net_connect!
15
16
 
16
17
  Dir[File.join(File.dirname(__FILE__), "support/**/*.rb")].sort.each { |f| require f }
17
18
 
19
+ Capybara.register_driver :rack_test do |app|
20
+ Capybara::RackTest::Driver.new(app, follow_redirects: false)
21
+ end
22
+
18
23
  RSpec.configure do |config|
19
24
  config.run_all_when_everything_filtered = true
20
25
  config.filter_run :focus
26
+ config.use_transactional_fixtures = true
21
27
 
22
28
  # Run specs in random order to surface order dependencies. If you find an
23
29
  # order dependency and want to debug it, you can fix the order by providing
@@ -25,6 +31,6 @@ RSpec.configure do |config|
25
31
  # --seed 1234
26
32
  config.order = "random"
27
33
 
28
- config.include(BackportControllerTestParams) if Rails.version < "5"
29
- config.include(Warden::Test::Helpers)
34
+ config.include Warden::Test::Helpers
35
+ config.include Capybara::DSL
30
36
  end
@@ -0,0 +1,115 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe "Authenication and authorisation" do
4
+ context "when accessing a route that doesn't require permissions or authentication" do
5
+ it "allows access" do
6
+ visit "/not-restricted"
7
+ expect(page).to have_content("jabberwocky")
8
+ end
9
+ end
10
+
11
+ context "when accessing a route that requires authentication" do
12
+ it "redirects an unauthenticated request to signon" do
13
+ # We manually follow the redirects because we have configured capybara
14
+ # to not follow redirects (and thus allow testing an external redirect)
15
+ visit "/restricted"
16
+ expect(page.response_headers["Location"]).to match("/auth/gds")
17
+ visit page.response_headers["Location"]
18
+ expect(page.response_headers["Location"]).to match("http://signon/oauth/authorize")
19
+ end
20
+
21
+ it "allows access for an authenticated user" do
22
+ stub_signon_authenticated
23
+
24
+ visit "/restricted"
25
+ expect(page).to have_content("restricted kablooie")
26
+ end
27
+
28
+ it "restricts access if a user is authenticated but remotely signed out" do
29
+ stub_signon_authenticated
30
+ User.last.set_remotely_signed_out!
31
+
32
+ visit "/restricted"
33
+ expect(page.status_code).to eql(302)
34
+ expect(page.response_headers["Location"]).to match("/auth/gds")
35
+ end
36
+
37
+ it "restricts access if a user is authenticated but session has expired" do
38
+ stub_signon_authenticated
39
+
40
+ Timecop.travel(Time.now.utc + GDS::SSO::Config.auth_valid_for + 5.minutes) do
41
+ visit "/restricted"
42
+ expect(page.status_code).to eql(302)
43
+ expect(page.response_headers["Location"]).to match("/auth/gds")
44
+ end
45
+ end
46
+
47
+ it "allows access when given a valid bearer token" do
48
+ stub_signon_user_request
49
+ page.driver.header("Authorization", "Bearer 123")
50
+
51
+ visit "/restricted"
52
+ expect(page).to have_content("restricted kablooie")
53
+ end
54
+
55
+ it "restricts access when given an invalid bearer token" do
56
+ stub_request(:get, "http://signon/user.json?client_id=gds-sso-test")
57
+ .to_return(status: 401)
58
+ page.driver.header("Authorization", "Bearer 123")
59
+
60
+ visit "/restricted"
61
+ expect(page.status_code).to eq(401)
62
+ end
63
+
64
+ it "returns a 401 when a bearer token is missing and the app is api_only" do
65
+ allow(GDS::SSO::Config).to receive(:api_only).and_return(true)
66
+
67
+ visit "/restricted"
68
+ expect(page.status_code).to eq(401)
69
+ end
70
+ end
71
+
72
+ context "when accessing a route that requires a permission" do
73
+ it "allows access when an authenticated user has the permission" do
74
+ stub_signon_authenticated(permissions: %w[execute])
75
+ visit "/this-requires-execute-permission"
76
+ expect(page).to have_content("you have execute permission")
77
+ end
78
+
79
+ it "restricts access when an authenticated user lacks the permission" do
80
+ stub_signon_authenticated
81
+ visit "/this-requires-execute-permission"
82
+ expect(page.status_code).to eq(403)
83
+ end
84
+ end
85
+
86
+ def stub_signon_authenticated(permissions: [])
87
+ # visit restricted page to trigger redirect URL to record state attribute
88
+ visit "/auth/gds"
89
+ state = CGI.parse(URI.parse(page.response_headers["Location"]).query)
90
+ .then { |query| query["state"].first }
91
+
92
+ stub_request(:post, "http://signon/oauth/access_token")
93
+ .to_return(body: { access_token: "token" }.to_json,
94
+ headers: { content_type: "application/json" })
95
+
96
+ stub_signon_user_request(permissions: permissions)
97
+
98
+ visit "/auth/gds/callback?code=code&state=#{state}"
99
+ end
100
+
101
+ def stub_signon_user_request(permissions: [])
102
+ stub_request(:get, "http://signon/user.json?client_id=gds-sso-test")
103
+ .to_return(
104
+ body: {
105
+ user: {
106
+ uid: "123",
107
+ email: "test-user@example.com",
108
+ name: "Test User",
109
+ permissions: permissions,
110
+ },
111
+ }.to_json,
112
+ headers: { content_type: "application/json" },
113
+ )
114
+ end
115
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gds-sso
3
3
  version: !ruby/object:Gem::Version
4
- version: 17.1.1
4
+ version: 18.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - GOV.UK Dev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-11-21 00:00:00.000000000 Z
11
+ date: 2023-08-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: oauth2
@@ -128,26 +128,6 @@ dependencies:
128
128
  - - "~>"
129
129
  - !ruby/object:Gem::Version
130
130
  version: '3'
131
- - !ruby/object:Gem::Dependency
132
- name: capybara-mechanize
133
- requirement: !ruby/object:Gem::Requirement
134
- requirements:
135
- - - "~>"
136
- - !ruby/object:Gem::Version
137
- version: '1'
138
- - - ">="
139
- - !ruby/object:Gem::Version
140
- version: 1.12.1
141
- type: :development
142
- prerelease: false
143
- version_requirements: !ruby/object:Gem::Requirement
144
- requirements:
145
- - - "~>"
146
- - !ruby/object:Gem::Version
147
- version: '1'
148
- - - ">="
149
- - !ruby/object:Gem::Version
150
- version: 1.12.1
151
131
  - !ruby/object:Gem::Dependency
152
132
  name: combustion
153
133
  requirement: !ruby/object:Gem::Requirement
@@ -194,16 +174,16 @@ dependencies:
194
174
  name: rubocop-govuk
195
175
  requirement: !ruby/object:Gem::Requirement
196
176
  requirements:
197
- - - '='
177
+ - - "~>"
198
178
  - !ruby/object:Gem::Version
199
- version: 4.8.0
179
+ version: '4'
200
180
  type: :development
201
181
  prerelease: false
202
182
  version_requirements: !ruby/object:Gem::Requirement
203
183
  requirements:
204
- - - '='
184
+ - - "~>"
205
185
  - !ruby/object:Gem::Version
206
- version: 4.8.0
186
+ version: '4'
207
187
  - !ruby/object:Gem::Dependency
208
188
  name: sqlite3
209
189
  requirement: !ruby/object:Gem::Requirement
@@ -232,6 +212,20 @@ dependencies:
232
212
  - - "~>"
233
213
  - !ruby/object:Gem::Version
234
214
  version: '0.9'
215
+ - !ruby/object:Gem::Dependency
216
+ name: webmock
217
+ requirement: !ruby/object:Gem::Requirement
218
+ requirements:
219
+ - - ">="
220
+ - !ruby/object:Gem::Version
221
+ version: '0'
222
+ type: :development
223
+ prerelease: false
224
+ version_requirements: !ruby/object:Gem::Requirement
225
+ requirements:
226
+ - - ">="
227
+ - !ruby/object:Gem::Version
228
+ version: '0'
235
229
  description: Client for GDS' OAuth 2-based SSO
236
230
  email:
237
231
  - govuk-dev@digital.cabinet-office.gov.uk
@@ -264,8 +258,6 @@ files:
264
258
  - lib/omniauth/strategies/gds.rb
265
259
  - spec/controller/api_user_controller_spec.rb
266
260
  - spec/controller/controller_methods_spec.rb
267
- - spec/fixtures/integration/authorize_api_users.sql
268
- - spec/fixtures/integration/signon.sql
269
261
  - spec/internal/app/assets/config/manifest.js
270
262
  - spec/internal/app/controllers/application_controller.rb
271
263
  - spec/internal/app/controllers/example_controller.rb
@@ -273,17 +265,13 @@ files:
273
265
  - spec/internal/config/database.yml
274
266
  - spec/internal/config/initializers/gds-sso.rb
275
267
  - spec/internal/config/routes.rb
276
- - spec/internal/config/storage.yml
277
268
  - spec/internal/db/schema.rb
278
- - spec/internal/public/favicon.ico
279
- - spec/requests/end_to_end_spec.rb
280
269
  - spec/spec_helper.rb
281
- - spec/support/backport_controller_test_params.rb
282
270
  - spec/support/controller_spy.rb
283
271
  - spec/support/serializable_user.rb
284
- - spec/support/signon_integration_helpers.rb
285
272
  - spec/support/test_user.rb
286
273
  - spec/support/timecop.rb
274
+ - spec/system/authentication_and_authorisation_spec.rb
287
275
  - spec/unit/api_access_spec.rb
288
276
  - spec/unit/bearer_token_spec.rb
289
277
  - spec/unit/config_spec.rb
@@ -303,44 +291,38 @@ required_ruby_version: !ruby/object:Gem::Requirement
303
291
  requirements:
304
292
  - - ">="
305
293
  - !ruby/object:Gem::Version
306
- version: '2.7'
294
+ version: '3.0'
307
295
  required_rubygems_version: !ruby/object:Gem::Requirement
308
296
  requirements:
309
297
  - - ">="
310
298
  - !ruby/object:Gem::Version
311
299
  version: '0'
312
300
  requirements: []
313
- rubygems_version: 3.3.26
301
+ rubygems_version: 3.4.18
314
302
  signing_key:
315
303
  specification_version: 4
316
304
  summary: Client for GDS' OAuth 2-based SSO
317
305
  test_files:
318
- - spec/spec_helper.rb
319
- - spec/fixtures/integration/signon.sql
320
- - spec/fixtures/integration/authorize_api_users.sql
321
- - spec/requests/end_to_end_spec.rb
322
- - spec/support/controller_spy.rb
323
- - spec/support/timecop.rb
324
- - spec/support/serializable_user.rb
325
- - spec/support/test_user.rb
326
- - spec/support/signon_integration_helpers.rb
327
- - spec/support/backport_controller_test_params.rb
328
306
  - spec/controller/api_user_controller_spec.rb
329
307
  - spec/controller/controller_methods_spec.rb
330
- - spec/internal/config/routes.rb
308
+ - spec/internal/app/assets/config/manifest.js
309
+ - spec/internal/app/controllers/application_controller.rb
310
+ - spec/internal/app/controllers/example_controller.rb
311
+ - spec/internal/app/models/user.rb
331
312
  - spec/internal/config/database.yml
332
313
  - spec/internal/config/initializers/gds-sso.rb
333
- - spec/internal/config/storage.yml
334
- - spec/internal/app/models/user.rb
335
- - spec/internal/app/controllers/example_controller.rb
336
- - spec/internal/app/controllers/application_controller.rb
337
- - spec/internal/app/assets/config/manifest.js
314
+ - spec/internal/config/routes.rb
338
315
  - spec/internal/db/schema.rb
339
- - spec/internal/public/favicon.ico
340
- - spec/unit/mock_bearer_token_spec.rb
341
- - spec/unit/bearer_token_spec.rb
316
+ - spec/spec_helper.rb
317
+ - spec/support/controller_spy.rb
318
+ - spec/support/serializable_user.rb
319
+ - spec/support/test_user.rb
320
+ - spec/support/timecop.rb
321
+ - spec/system/authentication_and_authorisation_spec.rb
342
322
  - spec/unit/api_access_spec.rb
343
- - spec/unit/user_spec.rb
344
- - spec/unit/session_serialisation_spec.rb
323
+ - spec/unit/bearer_token_spec.rb
345
324
  - spec/unit/config_spec.rb
325
+ - spec/unit/mock_bearer_token_spec.rb
346
326
  - spec/unit/railtie_spec.rb
327
+ - spec/unit/session_serialisation_spec.rb
328
+ - spec/unit/user_spec.rb
@@ -1,7 +0,0 @@
1
- DELETE FROM `oauth_access_tokens`;
2
-
3
- INSERT INTO oauth_access_tokens (resource_owner_id, application_id, token, refresh_token, expires_in, created_at)
4
- VALUES (1, 1, 'caaeb53be5c7277fb0ef158181bfd1537b57f9e3b83eb795be3cd0af6e118b28', '1bc343797483954d7306d67e96687feccdfdaa8b23ed662ae23e2b03e6661d16', POW(2, 31)-1, '2012-06-27 13:57:47');
5
-
6
- INSERT INTO oauth_access_tokens (resource_owner_id, application_id, token, refresh_token, expires_in, created_at)
7
- VALUES (1, 2, '98c72f4da02fdc43398e029d05567542944d2a9b0df3c20b0accd8bd6c5dc728', 'e2da0489a58219fd4f542139909737627874ceacd2af23f5c268ccecb36e85af', POW(2, 31)-1, '2014-07-14 09:06:14');
@@ -1,26 +0,0 @@
1
- -- Clean data from database
2
- DELETE FROM `oauth_access_grants`;
3
- DELETE FROM `oauth_access_tokens`;
4
- DELETE FROM `oauth_applications`;
5
- DELETE FROM `supported_permissions`;
6
- DELETE FROM `users`;
7
- DELETE FROM `user_application_permissions`;
8
-
9
- -- Setup fixture data
10
- INSERT INTO `oauth_applications` (id, name, uid, secret, redirect_uri, created_at, updated_at, home_uri, description)
11
- VALUES (1,'GDS_SSO integration test','gds-sso-test','secret','http://www.example-client.com/auth/gds/callback','2012-04-19 13:26:54','2012-04-19 13:26:54', 'http://home.com', 'GDS_SSO integration test');
12
- INSERT INTO `oauth_applications` (id, name, uid, secret, redirect_uri, created_at, updated_at, home_uri, description)
13
- VALUES (2,'A different appilcation','application-2','different secret','http://www.example-client2.com/auth/gds/callback','2014-07-14-09:07:32','2014-07-14-09:07:32', 'http://www.example-client2.com', '');
14
-
15
- INSERT INTO `supported_permissions` (id, application_id, name, created_at, updated_at)
16
- VALUES (1,1,'signin','2012-04-19 13:26:54','2012-04-19 13:26:54');
17
- INSERT INTO `supported_permissions` (id, application_id, name, created_at, updated_at)
18
- VALUES (2,2,'signin','2012-04-19 13:26:54','2012-04-19 13:26:54');
19
-
20
- INSERT INTO `users` (id, email, encrypted_password, password_salt, created_at, updated_at, confirmed_at, name, uid, role, password_changed_at)
21
- VALUES (1,'test@example-client.com','3a890fe5e95b328b83f2ba57ea893cae595f4937291ff5550acb68f4a8dafeac22e5f8120c1e66be8f2b769df142dd3d111b404c5c1741595c9ecc9e7e6ad827','QCsZsJs7m5ojdgvysHSy','2012-04-19 13:26:54','2012-04-19 13:26:54','2012-04-19 13:26:54','Test User','integration-uid', "normal", NOW());
22
-
23
- INSERT INTO `user_application_permissions` (user_id, application_id, supported_permission_id, created_at, updated_at)
24
- VALUES (1,1,1,'2012-04-19 13:26:54','2012-04-19 13:26:54');
25
- INSERT INTO `user_application_permissions` (user_id, application_id, supported_permission_id, created_at, updated_at)
26
- VALUES (1,2,2,'2012-04-19 13:26:54','2012-04-19 13:26:54');
@@ -1,3 +0,0 @@
1
- test:
2
- service: Disk
3
- root: <%= Rails.root.join("tmp/storage") %>
File without changes
@@ -1,215 +0,0 @@
1
- require "spec_helper"
2
- require "timecop"
3
-
4
- describe "Integration of client using GDS-SSO with signon" do
5
- include SignonIntegrationHelpers
6
-
7
- before :all do
8
- wait_for_signon_to_start
9
- end
10
-
11
- before :each do
12
- # points to an internal app, using combustion gem
13
- # see spec/internal
14
- @client_host = "www.example-client.com"
15
- Capybara.current_driver = :mechanize
16
- Capybara::Mechanize.local_hosts << @client_host
17
-
18
- load_signon_setup_fixture
19
- end
20
-
21
- describe "Web client accesses" do
22
- before :each do
23
- page.driver.header "accept", "text/html"
24
- end
25
-
26
- specify "a non-restricted page can be accessed without authentication" do
27
- visit "http://#{@client_host}/"
28
- expect(page).to have_content("jabberwocky")
29
- end
30
-
31
- specify "first access to a restricted page requires authentication and application approval" do
32
- visit "http://#{@client_host}/restricted"
33
- expect(page).to have_content("Sign in")
34
- fill_in "Email", with: "test@example-client.com"
35
- fill_in "Password", with: "q1w2e3r4t5y6u7i8o9p0"
36
- click_on "Sign in"
37
-
38
- expect(page).to have_content("restricted kablooie")
39
- end
40
-
41
- specify "access to a restricted page for an approved application requires only authentication" do
42
- # First we login to authorise the app
43
- visit "http://#{@client_host}/restricted"
44
- fill_in "Email", with: "test@example-client.com"
45
- fill_in "Password", with: "q1w2e3r4t5y6u7i8o9p0"
46
- click_on "Sign in"
47
-
48
- # At this point the app should be authorised, we reset the session to simulate a new browser visit.
49
- reset_session!
50
- page.driver.header "accept", "text/html"
51
-
52
- visit "http://#{@client_host}/restricted"
53
- expect(page).to have_content("Sign in")
54
-
55
- fill_in "Email", with: "test@example-client.com"
56
- fill_in "Password", with: "q1w2e3r4t5y6u7i8o9p0"
57
- click_on "Sign in"
58
-
59
- expect(page).to have_content("restricted kablooie")
60
- end
61
-
62
- specify "access to a page that requires signin permission granted" do
63
- # First we login to authorise the app
64
- visit "http://#{@client_host}/this_requires_signin_permission"
65
- fill_in "Email", with: "test@example-client.com"
66
- fill_in "Password", with: "q1w2e3r4t5y6u7i8o9p0"
67
- click_on "Sign in"
68
-
69
- # At this point the app should be authorised, we reset the session to simulate a new browser visit.
70
- reset_session!
71
- page.driver.header "accept", "text/html"
72
-
73
- visit "http://#{@client_host}/this_requires_signin_permission"
74
- expect(page).to have_content("Sign in")
75
-
76
- fill_in "Email", with: "test@example-client.com"
77
- fill_in "Password", with: "q1w2e3r4t5y6u7i8o9p0"
78
- click_on "Sign in"
79
-
80
- expect(page).to have_content("you have signin permission")
81
- end
82
-
83
- describe "remotely signed out" do
84
- specify "should prevent all access to the application until successful signin" do
85
- # First we login and authorise the app
86
- visit "http://#{@client_host}/restricted"
87
- fill_in "Email", with: "test@example-client.com"
88
- fill_in "Password", with: "q1w2e3r4t5y6u7i8o9p0"
89
- click_on "Sign in"
90
-
91
- page.driver.header "accept", "text/html"
92
- expect(page).to have_content("restricted kablooie")
93
-
94
- # logout from signon
95
- visit "http://localhost:4567/users/sign_out"
96
-
97
- # Simulate a POST to /auth/gds/api/users/:uid/reauth by signon
98
- # This is already tested in api_user_controller_spec.rb
99
- user = User.where(email: "test@example-client.com").first
100
- user.set_remotely_signed_out!
101
-
102
- # attempt to visit a restricted page
103
- visit "http://#{@client_host}/restricted"
104
-
105
- # be redirected to signon
106
- expect(page).to have_content("GOV.UK Signon")
107
- fill_in "Email", with: "test@example-client.com"
108
- fill_in "Password", with: "q1w2e3r4t5y6u7i8o9p0"
109
- click_on "Sign in"
110
-
111
- # then back again to the restricted page
112
- expect(page).to have_content("restricted kablooie")
113
- end
114
- end
115
-
116
- describe "session expiry" do
117
- it "should force you to re-authenticate with signon N hours after login" do
118
- visit "http://#{@client_host}/restricted"
119
- expect(page).to have_content("Sign in")
120
- fill_in "Email", with: "test@example-client.com"
121
- fill_in "Password", with: "q1w2e3r4t5y6u7i8o9p0"
122
- click_on "Sign in"
123
-
124
- expect(page).to have_content("restricted kablooie")
125
-
126
- visit "http://localhost:4567/users/sign_out"
127
-
128
- Timecop.travel(Time.now.utc + GDS::SSO::Config.auth_valid_for + 5.minutes) do
129
- visit "http://#{@client_host}/restricted"
130
- end
131
-
132
- expect(page).to have_content("Sign in")
133
- end
134
-
135
- it "should accept signon's remembered authentication N hours after login" do
136
- visit "http://#{@client_host}/restricted"
137
- expect(page).to have_content("Sign in")
138
- fill_in "Email", with: "test@example-client.com"
139
- fill_in "Password", with: "q1w2e3r4t5y6u7i8o9p0"
140
- click_on "Sign in"
141
-
142
- expect(page).to have_content("restricted kablooie")
143
-
144
- Timecop.travel(Time.now.utc + GDS::SSO::Config.auth_valid_for + 5.minutes) do
145
- visit "http://#{@client_host}/restricted"
146
- end
147
-
148
- expect(page).to have_content("restricted kablooie")
149
- end
150
-
151
- it "should not require re-authentication with signon fewer than N hours after login" do
152
- visit "http://#{@client_host}/restricted"
153
- expect(page).to have_content("Sign in")
154
- fill_in "Email", with: "test@example-client.com"
155
- fill_in "Password", with: "q1w2e3r4t5y6u7i8o9p0"
156
- click_on "Sign in"
157
-
158
- expect(page).to have_content("restricted kablooie")
159
-
160
- Timecop.travel(Time.now.utc + GDS::SSO::Config.auth_valid_for - 5.minutes) do
161
- visit "http://#{@client_host}/restricted"
162
- end
163
-
164
- expect(page).to have_content("restricted kablooie")
165
- end
166
- end
167
- end
168
-
169
- describe "OAuth based API client accesses" do
170
- before :each do
171
- page.driver.header "accept", "application/json"
172
- authorize_signon_api_user
173
-
174
- token = "caaeb53be5c7277fb0ef158181bfd1537b57f9e3b83eb795be3cd0af6e118b28"
175
- page.driver.header "authorization", "Bearer #{token}"
176
- end
177
-
178
- specify "access to a restricted page for an api client requires auth" do
179
- page.driver.header "authorization", "Bearer Bad Token"
180
- visit "http://#{@client_host}/restricted"
181
- expect(page.driver.response.status).to eq(401)
182
- end
183
-
184
- specify "setting a correct bearer token allows sign in" do
185
- visit "http://#{@client_host}/restricted"
186
- expect(page).to have_content("restricted kablooie")
187
- end
188
-
189
- specify "setting a correct bearer token picks up permissions" do
190
- visit "http://#{@client_host}/this_requires_signin_permission"
191
- expect(page).to have_content("you have signin permission")
192
- end
193
-
194
- specify "a token for one app cannot be used to access a different app" do
195
- page.driver.header "authorization", "Bearer 98c72f4da02fdc43398e029d05567542944d2a9b0df3c20b0accd8bd6c5dc728"
196
- visit "http://#{@client_host}/restricted"
197
- expect(page.driver.response.status).to eq(401)
198
- end
199
- end
200
-
201
- context "when in api_only mode" do
202
- around do |examples|
203
- GDS::SSO::Config.api_only = true
204
- Combustion::Application.reload_routes!
205
- examples.run
206
- GDS::SSO::Config.api_only = false
207
- Combustion::Application.reload_routes!
208
- end
209
-
210
- specify "accessing without a bearer token is not authorized" do
211
- visit "http://#{@client_host}/restricted"
212
- expect(page.driver.response.status).to eq(401)
213
- end
214
- end
215
- end
@@ -1,21 +0,0 @@
1
- module BackportControllerTestParams
2
- def delete(*args)
3
- action, rest = *args
4
- super(action, rest[:params])
5
- end
6
-
7
- def get(*args)
8
- action, rest = *args
9
- super(action, rest[:params])
10
- end
11
-
12
- def post(*args)
13
- action, rest = *args
14
- super(action, rest[:params])
15
- end
16
-
17
- def put(*args)
18
- action, rest = *args
19
- super(action, rest[:params])
20
- end
21
- end
@@ -1,56 +0,0 @@
1
- require "net/http"
2
-
3
- module SignonIntegrationHelpers
4
- def wait_for_signon_to_start
5
- retries = 0
6
- url = GDS::SSO::Config.oauth_root_url
7
- puts "Waiting for signon to start at #{url}"
8
- until signon_started?(url)
9
- print "."
10
- if retries > 20
11
- raise "Signon is not running at #{url}. Please start with `./start_signon.sh`. Under jenkins this should happen automatically."
12
- end
13
-
14
- retries += 1
15
- sleep 1
16
- end
17
- puts "Signon is now running at #{url}"
18
- end
19
-
20
- def signon_started?(url)
21
- uri = URI.parse(url)
22
- conn = Net::HTTP.start(uri.host, uri.port)
23
- true
24
- rescue Errno::ECONNREFUSED
25
- false
26
- ensure
27
- conn.try(:finish)
28
- end
29
-
30
- def load_signon_setup_fixture
31
- load_signon_fixture("signon.sql")
32
- end
33
-
34
- def authorize_signon_api_user
35
- load_signon_fixture("authorize_api_users.sql")
36
- end
37
-
38
- def load_signon_fixture(filename)
39
- require "erb"
40
- parsed = ERB.new(File.read("#{signon_path}/config/database.yml")).result
41
- db = YAML.safe_load(parsed, aliases: true)["test"]
42
-
43
- cmd = "mysql #{db['database']} -u#{db['username']} -p#{db['password']} < #{fixture_file(filename)}"
44
- system cmd or raise "Error loading signon fixture"
45
- end
46
-
47
- private
48
-
49
- def fixture_file(filename)
50
- File.join(File.dirname(__FILE__), "../fixtures/integration", filename)
51
- end
52
-
53
- def signon_path
54
- Rails.root.join("..", "..", "tmp", "signon").to_s
55
- end
56
- end