diff --git a/app/controllers/concerns/verify_sp_attributes_concern.rb b/app/controllers/concerns/verify_sp_attributes_concern.rb
index 65db253fbd0..6a168bb07b8 100644
--- a/app/controllers/concerns/verify_sp_attributes_concern.rb
+++ b/app/controllers/concerns/verify_sp_attributes_concern.rb
@@ -8,6 +8,8 @@ def needs_completion_screen_reason
:new_sp
elsif !requested_attributes_verified?(sp_session_identity)
:new_attributes
+ elsif reverified_after_consent?(sp_session_identity)
+ :reverified_after_consent
elsif consent_has_expired?(sp_session_identity)
:consent_expired
elsif consent_was_revoked?(sp_session_identity)
@@ -30,10 +32,9 @@ def update_verified_attributes
def consent_has_expired?(sp_session_identity)
return false unless sp_session_identity
return false if sp_session_identity.deleted_at.present?
- last_estimated_consent = sp_session_identity.last_consented_at || sp_session_identity.created_at
+ last_estimated_consent = last_estimated_consent_for(sp_session_identity)
!last_estimated_consent ||
- last_estimated_consent < ServiceProviderIdentity::CONSENT_EXPIRATION.ago ||
- verified_after_consent?(last_estimated_consent)
+ last_estimated_consent < ServiceProviderIdentity::CONSENT_EXPIRATION.ago
end
def consent_was_revoked?(sp_session_identity)
@@ -41,8 +42,20 @@ def consent_was_revoked?(sp_session_identity)
sp_session_identity.deleted_at.present?
end
+ def reverified_after_consent?(sp_session_identity)
+ return false unless sp_session_identity
+ return false if sp_session_identity.deleted_at.present?
+ last_estimated_consent = last_estimated_consent_for(sp_session_identity)
+ return false if last_estimated_consent.nil?
+ verified_after_consent?(last_estimated_consent)
+ end
+
private
+ def last_estimated_consent_for(sp_session_identity)
+ sp_session_identity.last_consented_at || sp_session_identity.created_at
+ end
+
def verified_after_consent?(last_estimated_consent)
verification_timestamp = current_user.active_profile&.verified_at
diff --git a/app/presenters/completions_presenter.rb b/app/presenters/completions_presenter.rb
index 47fbe124289..f913f3ab9d2 100644
--- a/app/presenters/completions_presenter.rb
+++ b/app/presenters/completions_presenter.rb
@@ -50,6 +50,11 @@ def heading
if ial2_requested?
if consent_has_expired?
I18n.t('titles.sign_up.completion_consent_expired_ial2')
+ elsif reverified_after_consent?
+ I18n.t(
+ 'titles.sign_up.completion_reverified_consent',
+ sp: sp_name,
+ )
else
I18n.t('titles.sign_up.completion_ial2', sp: sp_name)
end
@@ -71,6 +76,11 @@ def intro
'help_text.requested_attributes.ial2_consent_reminder_html',
sp: sp_name,
)
+ elsif reverified_after_consent?
+ I18n.t(
+ 'help_text.requested_attributes.ial2_reverified_consent_info',
+ sp: sp_name,
+ )
else
I18n.t(
'help_text.requested_attributes.ial2_intro_html',
@@ -121,6 +131,10 @@ def consent_has_expired?
completion_context == :consent_expired
end
+ def reverified_after_consent?
+ completion_context == :reverified_after_consent
+ end
+
def displayable_attribute_keys
sorted_attribute_mapping = if ial2_requested?
SORTED_IAL2_ATTRIBUTE_MAPPING
diff --git a/config/locales/help_text/en.yml b/config/locales/help_text/en.yml
index d6ad8eaf5cb..a5169c9caaa 100644
--- a/config/locales/help_text/en.yml
+++ b/config/locales/help_text/en.yml
@@ -18,6 +18,8 @@ en:
information with %{sp}. We’ll share this information: '
ial2_intro_html: '%{sp} needs to know who you are to connect your
account. We’ll share this information with %{sp}: '
+ ial2_reverified_consent_info: 'Because you verified your identity again, we need
+ your permission to share this information with %{sp}: '
phone: Phone number
social_security_number: Social Security number
verified_at: Updated on
diff --git a/config/locales/help_text/es.yml b/config/locales/help_text/es.yml
index c4f596f906c..21090ee05a0 100644
--- a/config/locales/help_text/es.yml
+++ b/config/locales/help_text/es.yml
@@ -19,6 +19,8 @@ es:
información:'
ial2_intro_html: '%{sp} necesita saber quién es para conectar su cuenta.
Compartiremos esta información con el organismo asociado: '
+ ial2_reverified_consent_info: 'Como volvió a verificar su identidad, necesitamos
+ su permiso para compartir esta información con %{sp}: '
phone: Teléfono
social_security_number: Número de Seguro Social
verified_at: Actualizado en
diff --git a/config/locales/help_text/fr.yml b/config/locales/help_text/fr.yml
index e39fae0ced1..3f3d539f854 100644
--- a/config/locales/help_text/fr.yml
+++ b/config/locales/help_text/fr.yml
@@ -21,6 +21,9 @@ fr:
ial2_intro_html: '%{sp} a besoin de savoir qui vous êtes pour connecter
votre compte. Nous partagerons ces informations avec l’agence
partenaire:'
+ ial2_reverified_consent_info: 'Puisque vous avez à nouveau vérifié votre
+ identité, nous avons besoin de votre autorisation pour partager ces
+ informations avec %{sp}:'
phone: Numéro de téléphone
social_security_number: Numéro de sécurité sociale
verified_at: Mis à jour le
diff --git a/config/locales/titles/en.yml b/config/locales/titles/en.yml
index bf277e6f84e..a50677038a1 100644
--- a/config/locales/titles/en.yml
+++ b/config/locales/titles/en.yml
@@ -75,6 +75,7 @@ en:
completion_ial2: Connect your verified information to %{sp}
completion_new_attributes: '%{sp} is requesting new information'
completion_new_sp: You are now signing in for the first time
+ completion_reverified_consent: Update your verified information with %{sp}
confirmation: Continue to sign in
spam_protection: Protecting against spam
totp_setup:
diff --git a/config/locales/titles/es.yml b/config/locales/titles/es.yml
index ede5b863559..ed9b7a7ff02 100644
--- a/config/locales/titles/es.yml
+++ b/config/locales/titles/es.yml
@@ -77,6 +77,7 @@ es:
completion_ial2: Conecte su información verificada a %{sp}
completion_new_attributes: '%{sp} está solicitando nueva información'
completion_new_sp: Acabas de iniciar sesión por primera vez
+ completion_reverified_consent: Actualice su información verificados con %{sp}
confirmation: Continuar para iniciar sesión
spam_protection: Protección contra el correo no deseado
totp_setup:
diff --git a/config/locales/titles/fr.yml b/config/locales/titles/fr.yml
index 94a79aa4070..739fa7374eb 100644
--- a/config/locales/titles/fr.yml
+++ b/config/locales/titles/fr.yml
@@ -77,6 +77,7 @@ fr:
completion_ial2: Connectez vos informations vérifiées à %{sp}
completion_new_attributes: '%{sp} demande de nouvelles informations'
completion_new_sp: Vous vous connectez pour la première fois
+ completion_reverified_consent: Mettez à jour vos informations vérifiées avec %{sp}
confirmation: Continuer à vous connecter
spam_protection: Protection contre les pourriels
totp_setup:
diff --git a/spec/controllers/concerns/verify_sp_attributes_concern_spec.rb b/spec/controllers/concerns/verify_sp_attributes_concern_spec.rb
index d6be336fdfa..1d6977ecd62 100644
--- a/spec/controllers/concerns/verify_sp_attributes_concern_spec.rb
+++ b/spec/controllers/concerns/verify_sp_attributes_concern_spec.rb
@@ -80,30 +80,6 @@
expect(consent_has_expired?).to eq(false)
end
end
-
- context 'when there is an active profile' do
- let(:sp_session_identity) do
- create(:service_provider_identity, last_consented_at: 15.days.ago, user: user)
- end
-
- before do
- create(:profile, :active, verified_at: verified_at, user: user)
- end
-
- context 'when the active profile was verified after last_consented_at' do
- let(:verified_at) { 5.days.ago }
- it 'is true because the new verified data needs to be consented to sharing' do
- expect(consent_has_expired?).to eq(true)
- end
- end
-
- context 'when the active profile was verified before last_consented_at' do
- let(:verified_at) { 20.days.ago }
- it 'is false' do
- expect(consent_has_expired?).to eq(false)
- end
- end
- end
end
describe '#consent_was_revoked?' do
@@ -199,6 +175,23 @@
expect(needs_completion_screen_reason).to be_nil
end
end
+
+ context 'when user is reverified' do
+ let(:verified_at) { 5.days.ago }
+ let(:sp_session_identity) do
+ build(
+ :service_provider_identity,
+ user: user,
+ last_consented_at: 15.days.ago,
+ )
+ end
+ before do
+ create(:profile, :active, verified_at: verified_at, user: user)
+ end
+ it 'is reverified_after_consent' do
+ expect(needs_completion_screen_reason).to eq(:reverified_after_consent)
+ end
+ end
end
end
@@ -208,4 +201,107 @@
end
end
end
+
+ describe '#reverified_after_consent?' do
+ let(:sp_session_identity) { build(:service_provider_identity, user: user) }
+ let(:user) { build(:user) }
+
+ before do
+ allow(controller).to receive(:current_user).and_return(user)
+ allow(controller).to receive(:sp_session_identity).and_return(sp_session_identity)
+ end
+
+ subject(:reverified_after_consent?) do
+ controller.reverified_after_consent?(sp_session_identity)
+ end
+
+ context 'when there is no sp_session_identity' do
+ let(:sp_session_identity) { nil }
+ it 'is false' do
+ expect(reverified_after_consent?).to eq(false)
+ end
+ end
+
+ context 'when there is no last_consented_at' do
+ it 'is false' do
+ expect(reverified_after_consent?).to eq(false)
+ end
+ end
+
+ context 'when last_consented_at within one year' do
+ let(:sp_session_identity) { build(:service_provider_identity, last_consented_at: 5.days.ago) }
+
+ it 'is false' do
+ expect(reverified_after_consent?).to eq(false)
+ end
+ end
+
+ context 'when the last_consented_at is older than a year ago' do
+ let(:sp_session_identity) do
+ build(:service_provider_identity, last_consented_at: 2.years.ago)
+ end
+
+ it 'is false' do
+ expect(reverified_after_consent?).to eq(false)
+ end
+ end
+
+ context 'when last_consented_at is nil but created_at is within a year' do
+ let(:sp_session_identity) do
+ build(:service_provider_identity, last_consented_at: nil, created_at: 4.days.ago)
+ end
+
+ it 'is false' do
+ expect(reverified_after_consent?).to eq(false)
+ end
+ end
+
+ context 'when last_consented_at is nil and created_at is older than a year' do
+ let(:sp_session_identity) do
+ build(:service_provider_identity, last_consented_at: nil, created_at: 4.years.ago)
+ end
+
+ it 'is false' do
+ expect(reverified_after_consent?).to eq(false)
+ end
+ end
+
+ context 'when the identity has been soft-deleted (consent has been revoked)' do
+ let(:sp_session_identity) do
+ build(
+ :service_provider_identity,
+ deleted_at: 1.day.ago,
+ last_consented_at: 2.years.ago,
+ )
+ end
+
+ it 'is false' do
+ expect(reverified_after_consent?).to eq(false)
+ end
+ end
+
+ context 'when there is an active profile' do
+ let(:sp_session_identity) do
+ create(:service_provider_identity, last_consented_at: 15.days.ago, user: user)
+ end
+
+ before do
+ create(:profile, :active, verified_at: verified_at, user: user)
+ end
+
+ context 'when the active profile was verified after last_consented_at' do
+ let(:verified_at) { 5.days.ago }
+ it 'is true because the new verified data needs to be consented to sharing' do
+ expect(reverified_after_consent?).to eq(true)
+ end
+ end
+
+ context 'when the active profile was verified before last_consented_at' do
+ let(:verified_at) { 20.days.ago }
+ it 'is false' do
+ expect(reverified_after_consent?).to eq(false)
+ end
+ end
+ end
+ end
end
diff --git a/spec/presenters/completions_presenter_spec.rb b/spec/presenters/completions_presenter_spec.rb
index 48e75c79b70..2265157fbbe 100644
--- a/spec/presenters/completions_presenter_spec.rb
+++ b/spec/presenters/completions_presenter_spec.rb
@@ -224,6 +224,27 @@
end
end
+ context 'user has reverified since last consent for sp' do
+ let(:identities) do
+ [
+ build(
+ :service_provider_identity,
+ service_provider: current_sp.issuer,
+ last_consented_at: 2.months.ago,
+ ),
+ ]
+ end
+ let(:completion_context) { :reverified_after_consent }
+ it 'renders the reverified IAL2 consent intro message' do
+ expect(presenter.intro).to eq(
+ I18n.t(
+ 'help_text.requested_attributes.ial2_reverified_consent_info',
+ sp: current_sp.friendly_name,
+ ),
+ )
+ end
+ end
+
context 'when consent has not expired' do
it 'renders the standard intro message' do
expect(presenter.intro).to eq(