Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
2b5c62d
Add README files for all JavaScript packages (#9853)
aduth Jan 4, 2024
427ba61
LG-11962 return 406 if biometric selected in production (#9837)
jmax-gsa Jan 4, 2024
b733821
LG-11777: Handle logout request as already logged out if concurrent s…
aduth Jan 4, 2024
cb71bcb
Add Puma configuration (#9848)
Jan 4, 2024
ad9fad8
LG-11695 enforce selfie capture performed (#9846)
soniaconnolly Jan 4, 2024
c459137
LG-11916: Acuant SDK 11.9.2. (#9844)
dawei-nava Jan 4, 2024
c6bb216
LG 11763 Include new device in MFA analytics (#9784)
kevinsmaster5 Jan 5, 2024
37677c2
Update form_component gem to 3.9 (#9864)
jmax-gsa Jan 5, 2024
6007bca
Spec fix: Expect 406 when selfie flag is off because of production bl…
soniaconnolly Jan 5, 2024
b33dc15
LG-11698 Write that selfie check was performed in user's profile (#9858)
theabrad Jan 5, 2024
9a3703e
Remove unused USWDS utility classes (#9868)
aduth Jan 5, 2024
143d573
build-sass: Support optional out-dir option (#9866)
aduth Jan 5, 2024
2b286f9
Convert status-message component from JS to TS (#9865)
amirbey Jan 5, 2024
cf851c8
Fix missing require for OTP deliveries script (#9872)
zachmargolis Jan 5, 2024
bafa646
Use testing-library ESLint plugin (#9870)
aduth Jan 8, 2024
e138a49
Remove Double Address Verification from jobs - Deploy First (#9854)
jack-ryan-nava-pbc Jan 8, 2024
2cf87fe
analytics_spec: remove unneeded allow_browser_log from two specs (#9874)
soniaconnolly Jan 8, 2024
f1c4dc1
Configure default Dependabot security updates (#9877)
aduth Jan 8, 2024
89593de
Revert "Try configuring Dependabot for security updates" (#9879)
aduth Jan 8, 2024
221fc61
changelog: Internal, CI, Populate the tmp/pids directory for puma (#9…
stephencshelton Jan 8, 2024
dd963f1
Update Puma to 6.4.2 (#9880)
aduth Jan 9, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 13 additions & 11 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"plugin:react-hooks/recommended",
"plugin:react/jsx-runtime"
],
"plugins": ["@18f/eslint-plugin-identity"],
"plugins": ["@18f/eslint-plugin-identity", "testing-library"],
"env": {
"browser": true,
"commonjs": true
Expand All @@ -20,10 +20,6 @@
{
"selector": "AssignmentExpression[left.property.name='href'][right.type=/(Template)?Literal/]",
"message": "Do not assign window.location.href to a string or string template to avoid losing i18n parameters"
},
{
"selector": "ExpressionStatement[expression.callee.object.name='userEvent']",
"message": "Await the promised result of a userEvent interaction"
}
]
},
Expand All @@ -44,11 +40,17 @@
"devDependencies": true,
"packageDir": "."
}
]
],
"testing-library/await-async-events": "error",
"testing-library/await-async-queries": "error",
"testing-library/await-async-utils": "error",
"testing-library/no-await-sync-events": "error",
"testing-library/no-await-sync-queries": "error",
"testing-library/no-debugging-utils": "error"
}
},
{
// Turn off react linting rules for most packages/files
// Turn off react linting rules for most packages/files
"files": [
"spec/**",
"app/javascript/packs/**",
Expand All @@ -63,8 +65,8 @@
"app/javascript/packages/validated-field/**",
"app/javascript/packages/verify-flow/**",
// In progress: enabling these rules for all files in packages/document-capture
"app/javascript/packages/document-capture/context/**",
"app/javascript/packages/document-capture/higher-order/**",
"app/javascript/packages/document-capture/context/**",
"app/javascript/packages/document-capture/higher-order/**",
"app/javascript/packages/document-capture/hooks/**",
// Comment out a file to enable react lint rules for that file only
"app/javascript/packages/document-capture/components/acuant-camera.tsx",
Expand Down Expand Up @@ -113,6 +115,6 @@
"react-hooks/exhaustive-deps": "off",
"react-hooks/rules-of-hooks": "off"
}
},
}
]
}
}
10 changes: 5 additions & 5 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ GEM
erubi (~> 1.4)
parser (>= 2.4)
smart_properties
bigdecimal (3.1.4)
bigdecimal (3.1.5)
bindata (2.4.15)
bootsnap (1.17.0)
msgpack (~> 1.2)
Expand Down Expand Up @@ -427,7 +427,7 @@ GEM
net-ssh (6.1.0)
newrelic_rpm (9.6.0)
base64
nio4r (2.6.1)
nio4r (2.7.0)
nokogiri (1.14.5)
mini_portile2 (~> 2.8.0)
racc (~> 1.4)
Expand Down Expand Up @@ -472,7 +472,7 @@ GEM
psych (5.1.1.1)
stringio
public_suffix (5.0.3)
puma (6.4.0)
puma (6.4.2)
nio4r (~> 2.0)
raabro (1.4.0)
racc (1.7.3)
Expand Down Expand Up @@ -561,7 +561,7 @@ GEM
activerecord (>= 5.0)
rgeo (>= 1.0.0)
rotp (6.2.0)
rouge (4.1.3)
rouge (4.2.0)
rqrcode (2.1.0)
chunky_png (~> 1.0)
rqrcode_core (~> 1.0)
Expand Down Expand Up @@ -684,7 +684,7 @@ GEM
activemodel
mail (>= 2.6.1)
simpleidn
view_component (3.8.0)
view_component (3.9.0)
activesupport (>= 5.2.0, < 8.0)
concurrent-ruby (~> 1.0)
method_source (~> 1.0)
Expand Down
2 changes: 0 additions & 2 deletions app/assets/stylesheets/_uswds-core.scss
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
'border-color',
'border-style',
'border-width',
'clearfix',
'color',
'display',
'flex',
Expand All @@ -30,7 +29,6 @@
'margin',
'margin-horizontal',
'margin-vertical',
'maxw',
'padding',
'position',
'text-align',
Expand Down
1 change: 1 addition & 0 deletions app/controllers/concerns/idv/document_capture_concern.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ def extract_pii_from_doc(user, response, store_in_session: false)
if store_in_session
idv_session.pii_from_doc ||= {}
idv_session.pii_from_doc.merge!(pii_from_doc)
idv_session.selfie_check_performed = response.selfie_check_performed
end
end

Expand Down
14 changes: 14 additions & 0 deletions app/controllers/openid_connect/authorization_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class AuthorizationController < ApplicationController
include BillableEventTrackable
include ForcedReauthenticationConcern

before_action :block_biometric_requests_in_production, only: [:index]
before_action :build_authorize_form_from_params, only: [:index]
before_action :pre_validate_authorize_form, only: [:index]
before_action :sign_out_if_prompt_param_is_login_and_user_is_signed_in, only: [:index]
Expand All @@ -28,6 +29,7 @@ def index
return redirect_to reactivate_account_url if user_needs_to_reactivate_account?
return redirect_to url_for_pending_profile_reason if user_has_pending_profile?
return redirect_to idv_url if identity_needs_verification?
return redirect_to idv_url if selfie_needed?
end
return redirect_to sign_up_completed_url if needs_completion_screen_reason
link_identity_to_service_provider
Expand All @@ -44,6 +46,13 @@ def index

private

def block_biometric_requests_in_production
if params['biometric_comparison_required'] == 'true' &&
FeatureManagement.idv_block_biometrics_requests?
render_not_acceptable
end
end

def check_sp_active
return if @authorize_form.service_provider&.active?
redirect_to sp_inactive_error_url
Expand Down Expand Up @@ -99,6 +108,11 @@ def identity_needs_verification?
current_user.reproof_for_irs?(service_provider: current_sp)
end

def selfie_needed?
decorated_sp_session.selfie_required? &&
!current_user.identity_verified_with_selfie?
end

def build_authorize_form_from_params
@authorize_form = OpenidConnectAuthorizeForm.new(authorization_params)
end
Expand Down
5 changes: 5 additions & 0 deletions app/controllers/openid_connect/logout_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ class LogoutController < ApplicationController
include SecureHeadersConcern
include FullyAuthenticatable

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

def index
Expand Down Expand Up @@ -39,6 +40,10 @@ def delete

private

def set_devise_failure_redirect_for_concurrent_session_logout
request.env['devise_session_limited_failure_redirect_url'] = request.url
end

def redirect_user(redirect_uri, user_uuid)
redirect_method = IdentityConfig.store.openid_connect_redirect_uuid_override_map.fetch(
user_uuid,
Expand Down
5 changes: 5 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

skip_before_action :verify_authenticity_token
before_action :require_path_year
before_action :set_devise_failure_redirect_for_concurrent_session_logout, only: :logout
before_action :handle_banned_user
before_action :bump_auth_count, only: :auth
before_action :redirect_to_sign_in, only: :auth, unless: :user_signed_in?
Expand Down Expand Up @@ -105,6 +106,10 @@ def prompt_for_password_if_ial2_request_and_pii_locked
redirect_to capture_password_url
end

def set_devise_failure_redirect_for_concurrent_session_logout
request.env['devise_session_limited_failure_redirect_url'] = request.url
end

def pii_requested_but_locked?
if (sp_session && sp_session_ial > 1) || ial_context.ialmax_requested?
current_user.identity_verified? &&
Expand Down
13 changes: 11 additions & 2 deletions app/controllers/sign_up/completions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ class CompletionsController < ApplicationController
include SecureHeadersConcern

before_action :confirm_two_factor_authenticated
before_action :verify_confirmed, if: :ial2?
before_action :confirm_identity_verified, if: :ial2?
before_action :confirm_selfie_captured, if: :selfie_required?
before_action :apply_secure_headers_override, only: [:show, :update]
before_action :verify_needs_completions_screen

Expand Down Expand Up @@ -31,10 +32,14 @@ def update

private

def verify_confirmed
def confirm_identity_verified
redirect_to idv_url if current_user.identity_not_verified?
end

def confirm_selfie_captured
redirect_to idv_url if !current_user.identity_verified_with_selfie?
end

def verify_needs_completions_screen
return_to_account unless needs_completion_screen_reason
end
Expand Down Expand Up @@ -62,6 +67,10 @@ def ial2_requested?
!!(ial2? || (ial_max? && current_user.identity_verified?))
end

def selfie_required?
decorated_sp_session.selfie_required?
end

def return_to_account
track_completion_event('account-page')
redirect_to account_url
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ def show
def create
@backup_code_form = BackupCodeVerificationForm.new(current_user)
result = @backup_code_form.submit(backup_code_params)
analytics.track_mfa_submit_event(result.to_h)
analytics.track_mfa_submit_event(
result.to_h.merge(new_device: user_session[:new_device]),
)
irs_attempts_api_tracker.mfa_login_backup_code(success: result.success?)
handle_result(result)
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ def form_params
end

def post_analytics(result)
properties = result.to_h.merge(analytics_properties)
properties = result.to_h.merge(analytics_properties, new_device: user_session[:new_device])
analytics.multi_factor_auth_setup(**properties) if context == 'confirmation'

analytics.track_mfa_submit_event(properties)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ def track_analytics(result)
analytics_hash = result.to_h.merge(
multi_factor_auth_method: 'personal-key',
multi_factor_auth_method_created_at: mfa_created_at&.strftime('%s%L'),
new_device: user_session[:new_device],
)

analytics.track_mfa_submit_event(analytics_hash)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ def analytics_properties
context: context,
multi_factor_auth_method: 'piv_cac',
piv_cac_configuration_id: piv_cac_verification_form&.piv_cac_configuration&.id,
new_device: user_session[:new_device],
}
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ def show

def create
result = TotpVerificationForm.new(current_user, params.require(:code).strip).submit

analytics.track_mfa_submit_event(result.to_h)
analytics.track_mfa_submit_event(result.to_h.merge(new_device: user_session[:new_device]))
irs_attempts_api_tracker.mfa_login_totp(success: result.success?)

if result.success?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ def confirm
**analytics_properties,
multi_factor_auth_method_created_at:
webauthn_configuration_or_latest.created_at.strftime('%s%L'),
new_device: user_session[:new_device],
)

if analytics_properties[:multi_factor_auth_method] == 'webauthn_platform'
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 @@ -115,6 +115,7 @@ def process_locked_out_user
def handle_valid_authentication
sign_in(resource_name, resource)
cache_profiles(auth_params[:password])
user_session[:new_device] = current_user.new_device?(cookie_uuid: cookies[:device])
create_user_event(:sign_in_before_2fa)
EmailAddress.update_last_sign_in_at_on_user_id_and_email(
user_id: current_user.id,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ describe('AddressSearch', () => {
const locationsURL = 'https://localhost:3000/locations/endpoint';

context('Page Heading and PO Search About Message', () => {
it('both render when handleLocationSelect is not null', async () => {
it('both render when handleLocationSelect is not null', () => {
const handleLocationsFound = sandbox.stub();
const onSelect = sinon.stub();
const { queryByText, queryByRole } = render(
Expand All @@ -25,8 +25,8 @@ describe('AddressSearch', () => {
</SWRConfig>,
);

const heading = await queryByText('in_person_proofing.headings.po_search.location');
const aboutMessage = await queryByText(
const heading = queryByText('in_person_proofing.headings.po_search.location');
const aboutMessage = queryByText(
'in_person_proofing.body.location.po_search.po_search_about',
);

Expand All @@ -37,7 +37,7 @@ describe('AddressSearch', () => {
).to.exist();
});

it('both do not render when handleLocationSelect is null', async () => {
it('both do not render when handleLocationSelect is null', () => {
const handleLocationsFound = sandbox.stub();
const onSelect = sinon.stub();
const { queryByText } = render(
Expand All @@ -53,8 +53,8 @@ describe('AddressSearch', () => {
</SWRConfig>,
);

const heading = await queryByText('in_person_proofing.headings.po_search.location');
const aboutMessage = await queryByText(
const heading = queryByText('in_person_proofing.headings.po_search.location');
const aboutMessage = queryByText(
'in_person_proofing.body.location.po_search.po_search_about',
);
expect(heading).to.be.empty;
Expand Down
Loading