Skip to content

Commit

Permalink
Add oauth error handling
Browse files Browse the repository at this point in the history
Sometimes an error arises during the omniauth libary's communication
with the auth provider (DSI in this case). In those cases, we need some
kind of basic error handling.

Here we:

- Add an AuthFailuresController
- Configure omniauth to use it as a failure app
- Add specific handling for "sessionexpired" errors
- Add generic error handling for anything else
- Add a FlashMessageComponent so we can present a generic error message
  to the user
  • Loading branch information
malcolmbaig committed Nov 1, 2023
1 parent e45e798 commit 33c7a0a
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 0 deletions.
8 changes: 8 additions & 0 deletions app/components/flash_message_component.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<%= govuk_notification_banner(
title_text: title,
classes: classes,
html_attributes: { role: role },
) do |notification_banner| %>
<% notification_banner.with_heading(text: heading) %>
<%= body %>
<% end %>
50 changes: 50 additions & 0 deletions app/components/flash_message_component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# frozen_string_literal: true
class FlashMessageComponent < ViewComponent::Base
ALLOWED_PRIMARY_KEYS = %i[info warning success].freeze
DEVISE_PRIMARY_KEYS = { alert: :warning, notice: :info }.freeze

def initialize(flash:)
super
@flash = flash.to_hash.symbolize_keys!
end

def message_key
key =
flash.keys.detect do |k|
ALLOWED_PRIMARY_KEYS.include?(k) || DEVISE_PRIMARY_KEYS.keys.include?(k)
end
DEVISE_PRIMARY_KEYS[key] || key
end

def title
I18n.t(message_key, scope: :notification_banner)
end

def classes
"govuk-notification-banner--#{message_key}"
end

def role
%i[warning success].include?(message_key) ? "alert" : "region"
end

def heading
messages.is_a?(Array) ? messages[0] : messages
end

def body
tag.p(messages[1], class: "govuk-body") if messages.is_a?(Array) && messages.count >= 2
end

def render?
!flash.empty? && message_key
end

private

def messages
flash[message_key] || flash[DEVISE_PRIMARY_KEYS.key(message_key)]
end

attr_reader :flash
end
29 changes: 29 additions & 0 deletions app/controllers/auth_failures_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
class AuthFailuresController < ApplicationController
class OpenIdConnectProtocolError < StandardError; end

def failure
return redirect_to(dsi_sign_out_path(id_token_hint: session[:id_token])) if session_expired?
handle_failure_then_redirect_to sign_in_path(oauth_failure: true)
end

private

def handle_failure_then_redirect_to(path)
oidc_error = OpenIdConnectProtocolError.new(error_message)
unless Rails.env.development?
Sentry.capture_exception(oidc_error)
flash[:warning] = I18n.t("generic_oauth_failure")
redirect_to(path) and return
end

raise oidc_error
end

def error_message
@error_message ||= request.env["omniauth.error"]&.message
end

def session_expired?
error_message == "sessionexpired"
end
end
1 change: 1 addition & 0 deletions app/views/layouts/base.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
<%= govuk_back_link(href: yield(:back_link_url)) if content_for?(:back_link_url) %>
<%= yield(:breadcrumbs) if content_for?(:breadcrumbs) %>
<main class="govuk-main-wrapper" id="main-content" role="main">
<%= render(FlashMessageComponent.new(flash: flash)) %>
<%= yield :content %>
</main>
</div>
Expand Down
1 change: 1 addition & 0 deletions config/initializers/omniauth.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

OmniAuth.config.logger = Rails.logger
OmniAuth.config.add_camelization('dfe_openid_connect', 'DfEOpenIDConnect')
OmniAuth.config.on_failure = proc { |env| AuthFailuresController.action(:failure).call(env) }

if DfESignIn.bypass?
Rails.application.config.middleware.use OmniAuth::Builder do
Expand Down
1 change: 1 addition & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ en:
name: Check the Children’s Barred List
email: [email protected]
dbs_email: [email protected]
generic_oauth_failure: There was a problem signing you in. Please try again.
activemodel:
errors:
models:
Expand Down

0 comments on commit 33c7a0a

Please sign in to comment.