Skip to content

Commit e9acc65

Browse files
committed
Handle post logout callback from One Login
When One Login redirects the user back to us after logging out, retrieve the form path parameters from the session to redirect to the submitted page. If the user's session cookie has been lost and we're unable to determine the form path parameters, let an exception bubble up and show an internal error page for now. We'll probably update this to show something more user friendly in a future commit.
1 parent d7cba7a commit e9acc65

3 files changed

Lines changed: 74 additions & 20 deletions

File tree

app/controllers/users/omniauth_controller.rb

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,35 +4,39 @@ class OmniAuthLoggedInDataMissingError < StandardError; end
44

55
class OmniAuthFailure < StandardError; end
66

7-
rescue_from Store::ReturnFromOneLoginStore::MissingReturnParamsError do
8-
Rails.logger.warn("Missing return params in session for One Login callback")
9-
redirect_to error_404_path
10-
end
11-
127
def callback
138
auth_hash = request.env["omniauth.auth"]
149
raise OmniAuthLoggedInDataMissingError, "Auth hash is missing on request" if auth_hash.blank?
1510

1611
email = auth_hash.dig("info", "email")
1712
raise OmniAuthLoggedInDataMissingError, "Email is missing in OmniAuth auth hash" if email.blank?
1813

19-
token = auth_hash.dig("credentials", "token")
14+
token = auth_hash.dig("credentials", "id_token")
2015
raise OmniAuthLoggedInDataMissingError, "Token is missing in OmniAuth auth hash" if token.blank?
2116

2217
auth_store.store_token(token)
2318

24-
return_from_one_login_store = Store::ReturnFromOneLoginStore.new(session)
2519
form_id = return_from_one_login_store.form_id
2620
path_params = return_from_one_login_store.get_path_params
2721

2822
Store::ConfirmationDetailsStore.new(session, form_id).save_copy_of_answers_email_address(email)
2923

3024
redirect_to check_your_answers_path(**path_params)
25+
rescue Store::ReturnFromOneLoginStore::MissingReturnParamsError
26+
Rails.logger.warn("Missing return params in session for One Login callback")
27+
redirect_to error_404_path
3128
end
3229

3330
def failure
3431
error = request.env["omniauth.error"]
3532
raise OmniAuthFailure, error
3633
end
34+
35+
def logged_out
36+
auth_store.clear
37+
38+
path_params = return_from_one_login_store.get_path_params
39+
redirect_to form_submitted_path(**path_params)
40+
end
3741
end
3842
end

app/lib/store/auth_store.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ def get_token
1717
@store.dig(AUTH_KEY, TOKEN_KEY)
1818
end
1919

20+
def clear
21+
@store.delete(AUTH_KEY)
22+
end
23+
2024
def logged_in?
2125
get_token.present?
2226
end

spec/requests/users/omniauth_controller_spec.rb

Lines changed: 59 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,28 @@
11
require "rails_helper"
22

33
RSpec.describe Users::OmniauthController, type: :request do
4+
let(:form_id) { 42 }
5+
let(:form_slug) { "test-form" }
6+
let(:mode) { "preview-draft" }
7+
let(:locale) { "cy" }
8+
let(:return_from_one_login_session) do
9+
{
10+
"last_form_id" => form_id,
11+
"last_form_slug" => form_slug,
12+
"last_mode" => mode,
13+
"last_locale" => locale,
14+
}
15+
end
16+
417
describe "GET #callback" do
5-
let(:form_id) { 42 }
6-
let(:form_slug) { "test-form" }
7-
let(:mode) { "preview-draft" }
8-
let(:locale) { "cy" }
918
let(:store) do
1019
{
11-
"return_from_one_login" => {
12-
"last_form_id" => form_id,
13-
"last_form_slug" => form_slug,
14-
"last_mode" => mode,
15-
"last_locale" => locale,
16-
},
20+
"return_from_one_login" => return_from_one_login_session,
1721
}.with_indifferent_access
1822
end
1923

2024
let(:email) { "test@example.com" }
21-
let(:token) { Faker::Alphanumeric.alphanumeric }
25+
let(:id_token) { Faker::Alphanumeric.alphanumeric }
2226
let(:auth_hash) do
2327
{
2428
provider: :govuk_one_login,
@@ -27,7 +31,7 @@
2731
email:,
2832
},
2933
credentials: {
30-
token: token,
34+
id_token:,
3135
},
3236
}.with_indifferent_access
3337
end
@@ -61,7 +65,7 @@
6165
end
6266

6367
it "stores the token on the session" do
64-
expect(store["auth"]["token"]).to eq token
68+
expect(store["auth"]["token"]).to eq id_token
6569
end
6670
end
6771

@@ -98,4 +102,46 @@
98102
expect { get omniauth_failure_path, env: { "omniauth.error" => error_message } }.to raise_error(Users::OmniauthController::OmniAuthFailure, error_message)
99103
end
100104
end
105+
106+
describe "GET #logged_out" do
107+
let(:token) { Faker::Alphanumeric.alphanumeric }
108+
109+
before do
110+
allow(Store::ReturnFromOneLoginStore).to receive(:new).and_wrap_original do |original_method, *_args|
111+
original_method.call(store)
112+
end
113+
allow(Store::AuthStore).to receive(:new).and_wrap_original do |original_method, *_args|
114+
original_method.call(store)
115+
end
116+
end
117+
118+
context "when the return from one login params are set on the session" do
119+
let(:store) do
120+
{
121+
"return_from_one_login" => return_from_one_login_session,
122+
"auth": { "token": token },
123+
}.with_indifferent_access
124+
end
125+
126+
before do
127+
get omniauth_logged_out_path
128+
end
129+
130+
it "clears the auth details on the session" do
131+
expect(store).not_to have_key("auth")
132+
end
133+
134+
it "redirects to the form submitted page" do
135+
expect(response).to redirect_to(form_submitted_path(form_id:, form_slug:, mode:, locale:))
136+
end
137+
end
138+
139+
context "when the return from one login params are not set on the session" do
140+
let(:store) { {} }
141+
142+
it "raises a Store::ReturnFromOneLoginStore::MissingReturnParamsError error" do
143+
expect { get omniauth_logged_out_path }.to raise_error Store::ReturnFromOneLoginStore::MissingReturnParamsError
144+
end
145+
end
146+
end
101147
end

0 commit comments

Comments
 (0)