Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[VI-850] updates SiS session refresher to poll MPI for id theft & death flags #19752

Merged
merged 22 commits into from
Jan 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
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
7 changes: 7 additions & 0 deletions app/models/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,13 @@ def set_mhv_ids(mhv_id)

# Other MPI

def validate_mpi_profile
return unless mpi_profile?

raise MPI::Errors::AccountLockedError, 'Death Flag Detected' if mpi_profile.deceased_date
raise MPI::Errors::AccountLockedError, 'Theft Flag Detected' if mpi_profile.id_theft_flag
end

def invalidate_mpi_cache
return unless loa3? && mpi.mpi_response_is_cached? && mpi.mvi_response

Expand Down
1 change: 1 addition & 0 deletions app/services/sign_in/user_loader.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ def reload_user
current_user.session_handle = access_token.session_handle
current_user.save && user_identity.save
current_user.invalidate_mpi_cache
current_user.validate_mpi_profile
current_user.create_mhv_account_async

current_user
Expand Down
1 change: 1 addition & 0 deletions lib/mpi/errors/errors.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class InvalidResponseParamsError < StandardError; end
class RecordNotFound < MPI::Errors::Response; end
class ArgumentError < MPI::Errors::Response; end
class DuplicateRecords < MPI::Errors::Response; end
class AccountLockedError < StandardError; end
class Request < ServiceError; end
class FailedRequestError < MPI::Errors::Request; end
class InvalidRequestError < MPI::Errors::Request; end
Expand Down
32 changes: 32 additions & 0 deletions modules/mobile/spec/controllers/application_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -169,10 +169,14 @@ def append_info_to_payload(payload)
let(:access_token) { create(:access_token, audience: ['vamobile']) }
let(:bearer_token) { SignIn::AccessTokenJwtEncoder.new(access_token:).perform }
let!(:user) { create(:user, :loa3, uuid: access_token.user_uuid) }
let(:deceased_date) { nil }
let(:id_theft_flag) { false }
let(:mpi_profile) { build(:mpi_profile, deceased_date:, id_theft_flag:) }

before do
request.headers['Authorization'] = "Bearer #{bearer_token}"
request.headers['Authentication-Method'] = 'SIS'
allow_any_instance_of(MPIData).to receive(:profile).and_return(mpi_profile)
end

it 'uses SIS session authentication' do
Expand All @@ -194,6 +198,34 @@ def append_info_to_payload(payload)
expect(response).to have_http_status(:unauthorized)
end
end

context 'when validating the user\'s MPI profile' do
context 'and the MPI profile has a deceased date' do
let(:deceased_date) { '20020202' }
let(:expected_error) { 'Death Flag Detected' }

it 'raises an MPI locked account error' do
get :index

expect(response).to have_http_status(:internal_server_error)
error_body = JSON.parse(response.body)['errors'].first
expect(error_body['meta']['exception']).to eq(expected_error)
end
end

context 'and the MPI profile has an id theft flag' do
let(:id_theft_flag) { true }
let(:expected_error) { 'Theft Flag Detected' }

it 'raises an MPI locked account error' do
get :index

expect(response).to have_http_status(:internal_server_error)
error_body = JSON.parse(response.body)['errors'].first
expect(error_body['meta']['exception']).to eq(expected_error)
end
end
end
end
end
end
Expand Down
82 changes: 82 additions & 0 deletions spec/controllers/sign_in/application_controller_spec.rb
bramleyjl marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,34 @@ def service_account_auth
end
end

shared_context 'mpi profile validation' do
before { allow_any_instance_of(SignIn::UserLoader).to receive(:find_valid_user).and_return(nil) }
bramleyjl marked this conversation as resolved.
Show resolved Hide resolved

context 'and the MPI profile has a deceased date' do
let(:deceased_date) { '20020202' }
let(:expected_error) { 'Death Flag Detected' }

it 'raises an MPI locked account error' do
response = subject
expect(response).to have_http_status(:internal_server_error)
error_body = JSON.parse(response.body)['errors'].first
expect(error_body['meta']['exception']).to eq(expected_error)
end
end

context 'and the MPI profile has an id theft flag' do
let(:id_theft_flag) { true }
let(:expected_error) { 'Theft Flag Detected' }

it 'raises an MPI locked account error' do
response = subject
expect(response).to have_http_status(:internal_server_error)
error_body = JSON.parse(response.body)['errors'].first
expect(error_body['meta']['exception']).to eq(expected_error)
end
end
end

context 'when authorization header does not exist' do
let(:access_token) { nil }

Expand Down Expand Up @@ -166,9 +194,16 @@ def service_account_auth
end
let(:user_serializer) { SignIn::IntrospectSerializer.new(user) }
let(:expected_introspect_response) { JSON.parse(user_serializer.to_json) }
let(:deceased_date) { nil }
let(:id_theft_flag) { false }
let(:mpi_profile) { build(:mpi_profile, deceased_date:, id_theft_flag:) }

before { allow_any_instance_of(MPIData).to receive(:profile).and_return(mpi_profile) }

it_behaves_like 'user fingerprint validation'

it_behaves_like 'mpi profile validation'

it 'returns ok status' do
expect(subject).to have_http_status(:ok)
end
Expand Down Expand Up @@ -218,9 +253,16 @@ def service_account_auth
end
let(:user_serializer) { SignIn::IntrospectSerializer.new(user) }
let(:expected_introspect_response) { JSON.parse(user_serializer.to_json) }
let(:deceased_date) { nil }
let(:id_theft_flag) { false }
let(:mpi_profile) { build(:mpi_profile, deceased_date:, id_theft_flag:) }

before { allow_any_instance_of(MPIData).to receive(:profile).and_return(mpi_profile) }

it_behaves_like 'user fingerprint validation'

it_behaves_like 'mpi profile validation'

it 'returns ok status' do
expect(subject).to have_http_status(:ok)
end
Expand Down Expand Up @@ -263,6 +305,32 @@ def service_account_auth
end
end

shared_context 'mpi profile validation' do
context 'and the MPI profile has a deceased date' do
let(:deceased_date) { '20020202' }
let(:expected_error) { 'Death Flag Detected' }

it 'raises an MPI locked account error' do
response = subject
expect(response).to have_http_status(:internal_server_error)
error_body = JSON.parse(response.body)['errors'].first
expect(error_body['meta']['exception']).to eq(expected_error)
end
end

context 'and the MPI profile has an id theft flag' do
let(:id_theft_flag) { true }
let(:expected_error) { 'Theft Flag Detected' }

it 'raises an MPI locked account error' do
response = subject
expect(response).to have_http_status(:internal_server_error)
error_body = JSON.parse(response.body)['errors'].first
expect(error_body['meta']['exception']).to eq(expected_error)
end
end
end

context 'when authorization header does not exist' do
let(:expected_error) { 'Access token JWT is malformed' }
let(:access_token) { nil }
Expand Down Expand Up @@ -311,9 +379,16 @@ def service_account_auth
end
let(:user_serializer) { SignIn::IntrospectSerializer.new(user) }
let(:expected_introspect_response) { JSON.parse(user_serializer.to_json) }
let(:deceased_date) { nil }
let(:id_theft_flag) { false }
let(:mpi_profile) { build(:mpi_profile, deceased_date:, id_theft_flag:) }

before { allow_any_instance_of(MPIData).to receive(:profile).and_return(mpi_profile) }

it_behaves_like 'user fingerprint validation'

it_behaves_like 'mpi profile validation'

it 'returns ok status' do
expect(subject).to have_http_status(:ok)
end
Expand Down Expand Up @@ -367,9 +442,16 @@ def service_account_auth
end
let(:user_serializer) { SignIn::IntrospectSerializer.new(user) }
let(:expected_introspect_response) { JSON.parse(user_serializer.to_json) }
let(:deceased_date) { nil }
let(:id_theft_flag) { false }
let(:mpi_profile) { build(:mpi_profile, deceased_date:, id_theft_flag:) }

before { allow_any_instance_of(MPIData).to receive(:profile).and_return(mpi_profile) }

it_behaves_like 'user fingerprint validation'

it_behaves_like 'mpi profile validation'

it 'returns ok status' do
expect(subject).to have_http_status(:ok)
end
Expand Down
44 changes: 44 additions & 0 deletions spec/models/user_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,50 @@
end
end

describe 'validate_mpi_profile' do
let(:loa) { loa_three }
let(:id_theft_flag) { false }
let(:deceased_date) { nil }

before { stub_mpi(build(:mpi_profile, icn: user.icn, deceased_date:, id_theft_flag:)) }

context 'when the user is not loa3' do
let(:loa) { loa_one }

it 'does not attempt to validate the user mpi profile' do
expect(subject.validate_mpi_profile).to be_nil
end
end

context 'when the MPI profile has a deceased date' do
let(:deceased_date) { '20020202' }
let(:expected_error_message) { 'Death Flag Detected' }

it 'raises an MPI Account Locked error' do
expect { subject.validate_mpi_profile }
.to raise_error(MPI::Errors::AccountLockedError)
.with_message(expected_error_message)
end
end

context 'when the MPI profile has an identity theft flag' do
let(:id_theft_flag) { true }
let(:expected_error_message) { 'Theft Flag Detected' }

it 'raises an MPI Account Locked error' do
expect { subject.validate_mpi_profile }
.to raise_error(MPI::Errors::AccountLockedError)
.with_message(expected_error_message)
end
end

context 'when the MPI profile has no issues' do
it 'returns a nil value' do
expect(subject.validate_mpi_profile).to be_nil
end
end
end

describe 'invalidate_mpi_cache' do
let(:cache_exists) { true }

Expand Down
26 changes: 25 additions & 1 deletion spec/services/sign_in/user_loader_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,11 @@
auth_broker:,
client_id: }
end
let(:deceased_date) { nil }
let(:id_theft_flag) { false }

before do
stub_mpi(build(:mpi_profile, edipi:, icn: user_icn, vha_facility_ids:))
stub_mpi(build(:mpi_profile, edipi:, icn: user_icn, deceased_date:, id_theft_flag:, vha_facility_ids:))
end

context 'and user is authenticated with dslogon' do
Expand All @@ -78,6 +80,28 @@
end
end

context 'when validating the user\'s MPI profile' do
context 'and the MPI profile has a deceased date' do
let(:deceased_date) { '20020202' }
let(:expected_error) { MPI::Errors::AccountLockedError }
let(:expected_error_message) { 'Death Flag Detected' }

it 'raises an MPI locked account error' do
expect { subject }.to raise_error(expected_error, expected_error_message)
end
end

context 'and the MPI profile has an id theft flag' do
let(:id_theft_flag) { true }
let(:expected_error) { MPI::Errors::AccountLockedError }
let(:expected_error_message) { 'Theft Flag Detected' }

it 'raises an MPI locked account error' do
expect { subject }.to raise_error(expected_error, expected_error_message)
end
end
end

it 'reloads user object with expected attributes' do
reloaded_user = subject

Expand Down
Loading