LG-7012 LG-7010 Add/Integrate new DDP Proofer#6684
Conversation
jskinne3
left a comment
There was a problem hiding this comment.
I like the idea of self-documenting code as much as the next person, but I don't think we have achieved that here. I don't know what, for example, metric_name and stage :resolution designate. The code's purpose is also not explained; there is no mention of device fingerprinting, for example. Could we clarify with code comments?
app/jobs/resolution_proofing_job.rb
Outdated
There was a problem hiding this comment.
this will return for network failures only right? (we still want to continue with the proofing process if we successfully hear back from LN but get a negative result)
There was a problem hiding this comment.
ah yes. we spoke about this today. it should always continue if fraud check fails and no it doesn't return on network failures because all exceptions are caught. i'll change it so it proceeds on failure. let me know if threatmetrix network failures should stop instant verify and I'll add that too.
spec/services/proofing/lexis_nexis/ddp/verification_request_spec.rb
Outdated
Show resolved
Hide resolved
…piggyback async results back up the chain
|
|
||
| threatmetrix_result = nil | ||
| if use_lexisnexis_ddp_threatmetrix_before_rdp_instant_verify? | ||
| user = User.find_by(id: user_id) |
There was a problem hiding this comment.
so I see that we're passing user_id, but I think that ActiveJob will correctly serialize/deserialize ActiveRecord models, we should just pass user if we wanted to I think
There was a problem hiding this comment.
I modeled it after AddressProofingJob which takes user_id
| def logger_info_hash(hash) | ||
| logger.info(hash.to_json) | ||
| end |
There was a problem hiding this comment.
I am not convinced this helper method is worth it?
There was a problem hiding this comment.
was difficult to test multiple logger calls especially because old instant verify code was doing a partial check. this made it much more simple to test
There was a problem hiding this comment.
it's also a tad bit DRYer
jskinne3
left a comment
There was a problem hiding this comment.
I'm approving this with the proviso that we need to document the testing process at a minimum, and ideally write broader documentation
| account_telephone: '', # applicant[:phone], decision was made not to send phone | ||
| drivers_license_number_hash: applicant[:state_id_number] ? | ||
| OpenSSL::Digest::SHA256.hexdigest(applicant[:state_id_number].gsub(/\W/, '')) : '', | ||
| event_type: 'ACCOUNT_CREATION', |
There was a problem hiding this comment.
is there a list of other event types? this is more like an account upgrade typically than an account create
There was a problem hiding this comment.
seems to be the best option. ie create a verified profile
| @@ -0,0 +1,20 @@ | |||
| { | |||
There was a problem hiding this comment.
My earlier comment was made for the request fixture, not the response fixture (oops)
But maybe would our specs be easier to maintain if we inlined this into the spec file instead of putting it in a fixture? JSON is easier to inspect than XML
| drivers_license_number_hash: applicant[:state_id_number] ? | ||
| OpenSSL::Digest::SHA256.hexdigest(applicant[:state_id_number].gsub(/\W/, '')) : '', |
There was a problem hiding this comment.
I'd consider extracting methods for these _hash attributes so we could unit test them, which would allow us to check and verify the regexes like state_id_number_for_hash or ssn_for_hash
There was a problem hiding this comment.
Agree. This particular code is covered but it's quick and dirty.

Why: To add several lexis nexis fraud based indicators via products such as fraudpoint, EmailAge, device fingerprinting, etc. and eventually have the DDP proofer be a drop in replacement for RDP proofer used at the InstantVerify step (so we would not have to make 2 api calls). Initially this call will be made before InstantVerify and the RDP instantverify step will be left alone. Note that DDP and threatmetrix are sometimes used synonymously. RDP is the legacy platform that runs instant verify, phone finder, true id. DDP is their new platform where we will call threatmetrix.
How: Use the proofing framework provided in
Proofing::BaseandProofing::LexisNexis:Proofer. The proofing call will call all the relevant products behind the scenes via one API call in DDP using the Session Query API https://portal.threatmetrix.us/kb/implementation/apis/session_query_api.htm . It will piggyback on the existing asyncResolutionProofingJobadding new params:user_id(to get email), andthreatmetrix_session_idfrom #6694 for device profiling. Add a feature flaglexisnexis_threatmetrix_enabledto call threatmetrix before instant verify. Note the new fields added to resolution proofing will be:threatmetrix_session_id(a unique session identifier created with the front end added LexisNexis javascript for device profiling, etc.),email, and the PII packet now usesdrivers_license_number(like the previous AAMVA document check which validates the actual drivers license info with the state if the state supports it). We dup the instant verify PII packet and add in the extra PII values and package it up for the call to DDP. All this info allows lexis to formulate a risk score. The job will continue to instant verify regardless of if the threatmetrix results or score and further on in the flow the user will face a sad screen upon fraud detection.How to test this locally:
Update application.yml to:
The proofers: document (trueid), resolution (instant verify), address (phone finder) are mocked by default (proofer_mock_fallback: true) so you can go through the verification process with bogus data (images,etc.). But we want the threatmetrix live locally so just hardcode out that mock on the lexisnexis_ddp_proofer memoization line:
Probably unwise to add in code to make it run locally (and override the global mock flag) with another feature flag as we might accidentally set one live in the lower environments where mocking is necessary.
Create an account and on the account screen type in the path
/verifyand verify your identity up to the confirm information screen.After submitting there you should see an entry in (async jobs) workers.log:
Note: request_id can be used with LN to track individual calls. In costing it's added to transaction_id. On Lexis legacy system this was conversation_id.
Remember that not all test data in idv is equal. You can feed it specific scenarios to generate pass/fail conditions noted here: https://developers.login.gov/testing/
Assumptions: a decision was made not to send phone even though we have it with users that have a phone mfa already configured.
Notes: username, password are part of the legacy rdp that used basic auth. the new ddp uses api keys and org id. Also workflow modified the path associated with the request in the legacy rdp system (instant verify, etc.). We are calling one endpoint here so no workflow is required.