Add flexible biometric proofing service selection (OIDC)#10948
Add flexible biometric proofing service selection (OIDC)#10948
Conversation
Sgtpluck
left a comment
There was a problem hiding this comment.
i'm still working through the changes, but here are some nitpicks to start
app/services/vot/parser.rb
Outdated
There was a problem hiding this comment.
same Data.define comment as above
There was a problem hiding this comment.
I don't think the same case can be made here given how complex it is already.
There was a problem hiding this comment.
This probably should have an initializer as well. Thoughts?
There was a problem hiding this comment.
if it's being turned into a class, then yes i think we should have a real initializer rather than using Data.define. my personal preference would be to leave it alone for this PR, but the complexity comment is valid, so up to you whether to pull out the initializer or revert it to a class-like object!
There was a problem hiding this comment.
ok, sorry thinking through this a little more:
as mentioned, the Data class was explicitly defined for use on class-like objects. it was not designed to be used in a class inheritance way as is being used here. if we wanted to fully convert the class, that would require removing this and updating all the references from using result.with.
i do not think we should do that as part of this PR (which is complicated enough already), so i'd like to more strongly encourage reverting this to Result = Data.define for the purposes of this PR, and adding a ticket to evaluate this more fully as part of next steps. i don't think converting this into a full class has any particularly strong benefits for the purpose of this change.
vrajmohan
left a comment
There was a problem hiding this comment.
Made a first pass at a code review.
87c7eac to
5854808
Compare
There was a problem hiding this comment.
If :biometric_comparison is marked as false, then :two_pieces_of_fair_evidence should also be false and vice versa.
(This is partially why I started with string substitution, so I could avoid having that type of business logic in the resolver.)
There was a problem hiding this comment.
ah great point! we can add that while we pair (or feel free to add it while applying other changes)
that makes sense, although having had a chat with hooper, it sounds like he intended the resolver to be the place to put that kind of logic, so that we can flexibly apply things depending on user/service provider (maybe other) context when necessary. let's definitely talk about the approach, i ended up changing more than i thought i was going to b/c i ran with hooper's suggestion and i want to make sure you're comfortable with it!
There was a problem hiding this comment.
Okay, I'll make those changes and see if anything breaks (😅)
There was a problem hiding this comment.
this method has gotten a lot more complicated with the inclusion of the meta-programming. i understand the desire to be explicit about what's in the result, but this has become harder for me to reason about in the process.
my personal preference would be closer to my original implementation (where we were just changing the values that needed to be changed, since we know, for instance, if the result is asking for biometric_comparison and it's required, we are not doing any data transformation on the result).
however, if you want to avoid making assumptions/keeping it explicit (which is fair), i would remove the self.method call and just call the methods directly. ruby automatically returns the last statement, so the correct result will be returned. the final line could be no_identity_proofing_acr_result(result) in order to capture any cases not found. this will make this method more direct and easier to reason about (imo).
There was a problem hiding this comment.
other things i personally might consider is pulling all the asserted_ial_acr logic into a separate decorator (decorate_result_with_ial_acr), but that may be an optimization for another day.
There was a problem hiding this comment.
I agree with Davida that the meta-programming may be a bit much for this implementation.
There was a problem hiding this comment.
Re: meta-programming. That's fair, I was trying to solve for not having a million base case statements returning the IAL1 acr result. I'll try a different approach.
I don't know that it would be feasible to move the asserted_ial_acr logic separate from the updating the result attributes as they are tightly coupled.
There was a problem hiding this comment.
i had a thought: this asserted_ial_acr is explicilty for dermining the return ial value.
for the purposes of actually answering the question "what is info[:ial]", we'll never be answering that question unless there is no identity profile. which means we should only be figuring out what the asserted_ial_acr if it's identity proofed. so i think we should be able to make this a lot less complicted knowing that use case?
There was a problem hiding this comment.
I had forgotten while in the weeds of the code that the vtr param is used as a logic gate. A number of specs were failing because I wasn't looking at the full resolution graph of for biometric proofing, but rather only places where AuthnContextResolver#resolve and Vot::Parser::Result were being directly utilized.
I changed the behavior of the resolver with that narrow focus in mind, which meant absorbing some business logic around IAL level assertion.
I'm going to unpublish the PR and attempt to streamline the changes further.
app/services/vot/parser.rb
Outdated
There was a problem hiding this comment.
why did this type value get added?
There was a problem hiding this comment.
I had a thought about the reporting on this, but it doesn't seem needed, so will remove.
app/services/vot/parser.rb
Outdated
There was a problem hiding this comment.
When I am using this class downstream to determine if I should perform biometric comparison what am I to make of biometric_comparison? and biometric_comparison_required?? Which one should I inspect to determine if I should perform biometric comparison or both? Is there something in the design of this that I am missing that should signal the answer to that question?
There was a problem hiding this comment.
The idea is that if the SP wants to require a user to complete proofing with biometric comparison (instead of preferring it when the user has already completed biometric comparison), this would be used as opposed to testing the asserted_ial_acr value directly. I can revert this as it seems to confuse the issue.
app/services/vot/component_value.rb
Outdated
There was a problem hiding this comment.
Is the only real change here adding default values for these (and perhaps some documentation)? If so, does that makes sense as a separate pull request so it does not distract from the crux of the change here?
app/services/vot/component_value.rb
Outdated
There was a problem hiding this comment.
Where is this REQUIREMENTS constant used?
There was a problem hiding this comment.
No where, I can remove this. I just needed to map the requirements in my head.
There was a problem hiding this comment.
please remove the commented out code!
There was a problem hiding this comment.
please remove the commented out code
app/services/id_token_builder.rb
Outdated
There was a problem hiding this comment.
please remove commented out code
Sgtpluck
left a comment
There was a problem hiding this comment.
I'm really excited about these changes! The things that need to happen for this to be ready to go for me are:
- removing commented out code
- remove metaprogramming from the decorator method
and i would strongly recommend:
- reverting the classes that were created out of the class-like objects to make this PR more compact and readable, along with a ticket to evaluate that change.
thanks! glad to see it's looking so good, excited to merge it in.
There was a problem hiding this comment.
the original implementation of info[:ial] only returned either Saml::Idp::Constants::IAL1_AUTHN_CONTEXT_CLASSREF or Saml::Idp::Constants::IAL2_AUTHN_CONTEXT_CLASSREF. we should not be changing that implementation, it may break partners expecting a specific value back
**Why?** This is the initial work to replace our public-facing Vectors of Trust (VOT) API interface(s). See: https://gitlab.login.gov/lg-people/lg-people-appdev/Melba/backlog-fy24/-/issues/39 **How?** * Maintains the current VoT implementation and API for current SPs * Adds support for selecting proofing with biometric comparison using new Authentication Context Class Reference values (ACR values) in our OIDC API * Unlike IALMax, the new ACR values are not a step-up flow. Instead, SPs will be able to fallback to a lower level of identity proofing for their current users that have successfully proofed in the past. [skip changelog] contributors: davida marion <davida.marion@gsa.gov>
contributor: davida marion <davida.marion@gsa.gov> - Clean up some logic - Fix tests - Add AuthnContextResolver specs - Experiment with decorator rather than string replacement - Clean up method placement - Add condition that checks if biometrics is required
- Store acr_results in in assertion logic instance variable for performance - PR feedback: made component descriptions more specific and some rubocop fixes - wip: updated IAL ACR assertion logic, fixed broken tests, rubocop - wip: Fixed all broken tests except services/analytics.rb - PR fixes: fixed analytics tests - vtr handling updated
66e6418 to
dda9131
Compare
Why?
This is the initial work to replace our public-facing Vectors of Trust (VOT) API interface(s).
See: https://gitlab.login.gov/lg-people/lg-people-appdev/Melba/backlog-fy24/-/issues/39
How?
[skip changelog]
🛠 Summary of changes
The primary changes live in
AuthnContextResolver.It mimics the service selection logic of
#selected_vtr_parser_result_from_vtr_listwith the important caveat of only handling theial2?bio=preferredACR value. The AAL and other IAL ACR values are handled the same as before.No new logic was added to replace/refactor how IAL ACR values are used except in
OpenidConnectUserInfoPresenter, where the actual identity proofing ACR value is used instead of always mapping toIAL2_AUTHN_CONTEXT_CLASSREF.