gds-sso 17.1.1 → 18.0.0

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