Skip to content

Commit

Permalink
Merge pull request #10624 from 18F/stages/rc-2024-05-14
Browse files Browse the repository at this point in the history
Deploy RC 379 to Production
  • Loading branch information
amirbey authored May 14, 2024
2 parents 0f0c08d + f9cc372 commit 14c584c
Show file tree
Hide file tree
Showing 347 changed files with 11,173 additions and 13,975 deletions.
3 changes: 2 additions & 1 deletion .prettierrc
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"singleQuote": true,
"trailingComma": "all",
"printWidth": 100
"printWidth": 100,
"proseWrap": "never"
}
24 changes: 24 additions & 0 deletions app/controllers/concerns/openid_connect_redirect_concern.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# frozen_string_literal: true

module OpenidConnectRedirectConcern
def oidc_redirect_method(issuer:, user_uuid:)
user_redirect_method_override =
IdentityConfig.store.openid_connect_redirect_uuid_override_map[user_uuid]

sp_redirect_method_override =
IdentityConfig.store.openid_connect_redirect_issuer_override_map[issuer]

user_redirect_method_override || sp_redirect_method_override ||
IdentityConfig.store.openid_connect_redirect
end

# We do not include Content-Security-Policy form-action headers if they are
# configured to be disabled and we are not using a server-side redirect.
def form_action_csp_disabled_and_not_server_side_redirect?(issuer:, user_uuid:)
!IdentityConfig.store.openid_connect_content_security_form_action_enabled &&
oidc_redirect_method(
issuer: issuer,
user_uuid: user_uuid,
) != 'server_side'
end
end
8 changes: 8 additions & 0 deletions app/controllers/concerns/recaptcha_concern.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,14 @@ module RecaptchaConcern
'https://recaptcha.google.com/recaptcha/',
].freeze

def add_recaptcha_resource_hints
response.headers['Link'] = [
response.headers['Link'],
'<https://www.google.com>;rel=preconnect',
'<https://www.gstatic.com>;rel=preconnect;crossorigin',
].compact.join(',')
end

def allow_csp_recaptcha_src
policy = current_content_security_policy
policy.script_src(*policy.script_src, *RECAPTCHA_SCRIPT_SRC)
Expand Down
7 changes: 6 additions & 1 deletion app/controllers/concerns/secure_headers_concern.rb
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
# frozen_string_literal: true

module SecureHeadersConcern
include OpenidConnectRedirectConcern
extend ActiveSupport::Concern

def apply_secure_headers_override
return if stored_url_for_user.blank?
return unless IdentityConfig.store.openid_connect_content_security_form_action_enabled

authorize_form = OpenidConnectAuthorizeForm.new(authorize_params)
return unless authorize_form.valid?

return if form_action_csp_disabled_and_not_server_side_redirect?(
issuer: authorize_form.service_provider.issuer,
user_uuid: current_user&.uuid,
)

override_form_action_csp(csp_uris)
end

Expand Down
10 changes: 10 additions & 0 deletions app/controllers/concerns/sign_in_duration_concern.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# frozen_string_literal: true

module SignInDurationConcern
extend ActiveSupport::Concern

def sign_in_duration_seconds
return unless session[:sign_in_page_visited_at]
(Time.zone.now - Time.zone.parse(session[:sign_in_page_visited_at])).seconds.to_f
end
end
10 changes: 0 additions & 10 deletions app/controllers/idv/cancellations_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,6 @@ def destroy
end
end

def exit
analytics.idv_cancellation_confirmed(step: params[:step])
cancel_session
if hybrid_session?
render :destroy
else
redirect_to cancelled_redirect_path
end
end

private

def barcode_step?
Expand Down
1 change: 1 addition & 0 deletions app/controllers/idv/document_capture_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ def extra_view_variables
sp_name: decorated_sp_session.sp_name,
failure_to_proof_url: return_to_sp_failure_to_proof_url(step: 'document_capture'),
skip_doc_auth: idv_session.skip_doc_auth,
skip_doc_auth_from_how_to_verify: false,
skip_doc_auth_from_handoff: idv_session.skip_doc_auth_from_handoff,
opted_in_to_in_person_proofing: idv_session.opted_in_to_in_person_proofing,
doc_auth_selfie_capture:,
Expand Down
17 changes: 9 additions & 8 deletions app/controllers/idv/in_person/state_id_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,17 @@ def update

pii_from_user = flow_session[:pii_from_user]
initial_state_of_same_address_as_id = pii_from_user[:same_address_as_id]
Idv::StateIdForm::ATTRIBUTES.each do |attr|
pii_from_user[attr] = flow_params[attr]
end
form_result = form.submit(flow_params)

analytics.idv_in_person_proofing_state_id_submitted(
**analytics_arguments.merge(**form_result.to_h),
)
form_result = form.submit(flow_params)

if form_result.success?
Idv::StateIdForm::ATTRIBUTES.each do |attr|
pii_from_user[attr] = flow_params[attr]
end

analytics.idv_in_person_proofing_state_id_submitted(
**analytics_arguments.merge(**form_result.to_h),
)
# Accept Date of Birth from both memorable date and input date components
formatted_dob = MemorableDateComponent.extract_date_param flow_params&.[](:dob)
pii_from_user[:dob] = formatted_dob if formatted_dob
Expand Down Expand Up @@ -130,7 +131,7 @@ def copy_state_id_address_to_residential_address(pii_from_user)
end

def updating_state_id?
pii_from_user.has_key?(:first_name)
user_session.dig(:idv, :ssn).present?
end

def parsed_dob
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# frozen_string_literal: true

module Idv
class CaptureDocStatusController < ApplicationController
class LinkSentPollController < ApplicationController
include Idv::AvailabilityConcern

before_action :confirm_two_factor_authenticated
Expand Down
22 changes: 9 additions & 13 deletions app/controllers/openid_connect/authorization_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ class AuthorizationController < ApplicationController
include AuthorizationCountConcern
include BillableEventTrackable
include ForcedReauthenticationConcern
include OpenidConnectRedirectConcern
include SignInDurationConcern

before_action :build_authorize_form_from_params, only: [:index]
before_action :block_biometric_requests_in_production, only: [:index]
Expand Down Expand Up @@ -137,7 +139,11 @@ def build_authorize_form_from_params
end

def secure_headers_override
return unless IdentityConfig.store.openid_connect_content_security_form_action_enabled
return if form_action_csp_disabled_and_not_server_side_redirect?(
issuer: @authorize_form.service_provider.issuer,
user_uuid: current_user&.uuid,
)

csp_uris = SecureHeadersAllowList.csp_with_sp_redirect_uris(
@authorize_form.redirect_uri,
@authorize_form.service_provider.redirect_uris,
Expand Down Expand Up @@ -210,29 +216,19 @@ def track_events
service_provider: @authorize_form.service_provider,
user: current_user,
)

analytics.sp_redirect_initiated(
ial: event_ial_context.ial,
billed_ial: event_ial_context.bill_for_ial_1_or_2,
sign_in_flow: session[:sign_in_flow],
vtr: sp_session[:vtr],
acr_values: sp_session[:acr_values],
sign_in_duration_seconds:,
)
track_billing_events
end

def redirect_user(redirect_uri, issuer, user_uuid)
user_redirect_method_override =
IdentityConfig.store.openid_connect_redirect_uuid_override_map[user_uuid]

sp_redirect_method_override =
IdentityConfig.store.openid_connect_redirect_issuer_override_map[issuer]

redirect_method =
user_redirect_method_override || sp_redirect_method_override ||
IdentityConfig.store.openid_connect_redirect

case redirect_method
case oidc_redirect_method(issuer: issuer, user_uuid: user_uuid)
when 'client_side'
@oidc_redirect_uri = redirect_uri
render(
Expand Down
70 changes: 38 additions & 32 deletions app/controllers/openid_connect/logout_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,37 @@ module OpenidConnect
class LogoutController < ApplicationController
include SecureHeadersConcern
include FullyAuthenticatable
include OpenidConnectRedirectConcern

before_action :set_devise_failure_redirect_for_concurrent_session_logout, only: [:index]
before_action :set_devise_failure_redirect_for_concurrent_session_logout,
only: [:logout]
before_action :confirm_two_factor_authenticated, only: [:delete]

def index
# Handle logout (with confirmation if initiated by relying partner)
def logout
@logout_form = build_logout_form

result = @logout_form.submit
analytics.oidc_logout_requested(**result.to_h.except(:redirect_uri))
redirect_uri = result.extra[:redirect_uri]

analytics.oidc_logout_requested(**to_event(result))

if result.success? && result.extra[:redirect_uri]
handle_successful_logout_request(result, result.extra[:redirect_uri])
if result.success? && redirect_uri
handle_successful_logout_request(result, redirect_uri)
else
render :error
end
end

# Sign out without confirmation
def delete
@logout_form = build_logout_form
result = @logout_form.submit
redirect_uri = result.extra[:redirect_uri]

analytics.oidc_logout_submitted(**result.to_h.except(:redirect_uri))
analytics.oidc_logout_submitted(**to_event(result))

if result.success? && (redirect_uri = result.extra[:redirect_uri])
analytics.logout_initiated(**result.to_h.except(:redirect_uri))
irs_attempts_api_tracker.logout_initiated(success: result.success?)

redirect_user(redirect_uri, @logout_form.service_provider&.issuer, current_user&.uuid)
sign_out
if result.success? && redirect_uri
handle_logout(result, redirect_uri)
else
render :error
end
Expand All @@ -45,17 +47,7 @@ def set_devise_failure_redirect_for_concurrent_session_logout
end

def redirect_user(redirect_uri, issuer, user_uuid)
user_redirect_method_override =
IdentityConfig.store.openid_connect_redirect_uuid_override_map[user_uuid]

sp_redirect_method_override =
IdentityConfig.store.openid_connect_redirect_issuer_override_map[issuer]

redirect_method =
user_redirect_method_override || sp_redirect_method_override ||
IdentityConfig.store.openid_connect_redirect

case redirect_method
case oidc_redirect_method(issuer: issuer, user_uuid: user_uuid)
when 'client_side'
@oidc_redirect_uri = redirect_uri
render(
Expand All @@ -78,7 +70,10 @@ def redirect_user(redirect_uri, issuer, user_uuid)

def apply_logout_secure_headers_override(redirect_uri, service_provider)
return if service_provider.nil? || redirect_uri.nil?
return unless IdentityConfig.store.openid_connect_content_security_form_action_enabled
return if form_action_csp_disabled_and_not_server_side_redirect?(
issuer: service_provider.issuer,
user_uuid: current_user&.id,
)

uris = SecureHeadersAllowList.csp_with_sp_redirect_uris(
redirect_uri,
Expand All @@ -104,7 +99,8 @@ def build_logout_form
def handle_successful_logout_request(result, redirect_uri)
apply_logout_secure_headers_override(redirect_uri, @logout_form.service_provider)
if require_logout_confirmation?
analytics.oidc_logout_visited(**result.to_h.except(:redirect_uri))
analytics.oidc_logout_visited(**to_event(result))

@params = {
client_id: logout_params[:client_id],
post_logout_redirect_uri: logout_params[:post_logout_redirect_uri],
Expand All @@ -113,15 +109,25 @@ def handle_successful_logout_request(result, redirect_uri)
@service_provider_name = @logout_form.service_provider&.friendly_name
delete_branded_experience(logout: true)

render :index
render :confirm_logout
else
analytics.logout_initiated(**result.to_h.except(:redirect_uri))
irs_attempts_api_tracker.logout_initiated(success: result.success?)
handle_logout(result, redirect_uri)
end
end

sign_out
def handle_logout(result, redirect_uri)
analytics.logout_initiated(**to_event(result))
irs_attempts_api_tracker.logout_initiated(success: result.success?)

redirect_user(redirect_uri, @logout_form.service_provider&.issuer, current_user&.uuid)
end
sign_out

redirect_user(redirect_uri, @logout_form.service_provider&.issuer, current_user&.uuid)
end

# Convert FormResponse into loggable analytics event
# @param [FormResponse] result
def to_event(result)
result.to_h.except(:redirect_uri)
end

def logout_params
Expand Down
2 changes: 2 additions & 0 deletions app/controllers/saml_idp_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class SamlIdpController < ApplicationController
include AuthorizationCountConcern
include BillableEventTrackable
include SecureHeadersConcern
include SignInDurationConcern

prepend_before_action :skip_session_load, only: [:metadata, :remotelogout]
prepend_before_action :skip_session_expiration, only: [:metadata, :remotelogout]
Expand Down Expand Up @@ -187,6 +188,7 @@ def track_events
sign_in_flow: session[:sign_in_flow],
vtr: sp_session[:vtr],
acr_values: sp_session[:acr_values],
sign_in_duration_seconds:,
)
track_billing_events
end
Expand Down
2 changes: 2 additions & 0 deletions app/controllers/users/phone_setup_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ class PhoneSetupController < ApplicationController
before_action :confirm_recently_authenticated_2fa
before_action :check_max_phone_numbers_per_account, only: %i[index create]

after_action :add_recaptcha_resource_hints, if: :recaptcha_enabled?

helper_method :in_multi_mfa_selection_flow?

def index
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/users/piv_cac_login_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,14 @@ def render_prompt

def process_piv_cac_login
result = piv_cac_login_form.submit
analytics.piv_cac_login(**result.to_h)
clear_piv_cac_information
clear_piv_cac_nonce
if result.success?
process_valid_submission
else
process_invalid_submission
end
analytics.piv_cac_login(**result.to_h)
end

def piv_cac_login_form
Expand Down
1 change: 1 addition & 0 deletions app/controllers/users/sessions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ def new
issuer: decorated_sp_session.sp_issuer,
)
analytics.sign_in_page_visit(flash: flash[:alert])
session[:sign_in_page_visited_at] = Time.zone.now.to_s
super
end

Expand Down
1 change: 1 addition & 0 deletions app/helpers/script_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ def render_javascript_pack_once_tags(...)
**attributes,
crossorigin: local_crossorigin_sources? ? true : nil,
integrity: asset_sources.get_integrity(source),
nopush: false,
)
end
end
Expand Down
2 changes: 1 addition & 1 deletion app/helpers/stylesheet_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ def stylesheet_tag_once(*names)
def render_stylesheet_once_tags(*names)
stylesheet_tag_once(*names) if names.present?
return if @stylesheets.blank?
safe_join(@stylesheets.map { |stylesheet| stylesheet_link_tag(stylesheet) })
safe_join(@stylesheets.map { |stylesheet| stylesheet_link_tag(stylesheet, nopush: false) })
end
end
# rubocop:enable Rails/HelperInstanceVariable
Loading

0 comments on commit 14c584c

Please sign in to comment.