-
Notifications
You must be signed in to change notification settings - Fork 55
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
Suppressing unexpected error with WebAuthn::PublicKeyCredentialWithAttestation#verify
#413
Suppressing unexpected error with WebAuthn::PublicKeyCredentialWithAttestation#verify
#413
Conversation
…Attestation#verify`
I wonder how it is possible in a real scenario for the challenge to be Code looks good to me 🙂 |
Thank you for review. Yes, this issue is an approach to a phenomenon that occurs when operating a production environment. For example, if you are using external storage for session store. When using an in-memory data store, data This is to help troubleshoot unforeseen circumstances and is not something that occurs in routine scenarios. |
def self.response_class | ||
WebAuthn::AuthenticatorAttestationResponse | ||
end | ||
|
||
def verify(challenge, user_verification: nil) | ||
challenge.is_a?(String) || raise(InvalidChallengeError, "challenge must be a String. input challenge class: #{challenge.class}") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think about using the already existent ChallengeVerificationError
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, I think it is reasonable to handle WebAuthn::ChallengeVerificationError
because the meaning of ChallengeVerificationError
and the defined level are directly under WebAuthn
.
- The name and responsibility of
ChallengeVerificationError
is broad. TheWebAuthn::PublicKeyCredentialWithAttestation::InvalidChallengeError
added this time has a limitedclass
definition and naming, so it helps detailed error analysis. - The usage of
ChallengeVerificationError
is unified in that theclass
is dynamically selected by theverify_item
method. This time, explicitly specifying a differentclass
for a different purpose may cause confusion for users.
After that, I recommend defining a new class
like the current implementation.
And, either choice makes sense, so I respect your opinion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair enough, there are other cases where we are raising a custom error, for example in https://github.com/cedarcode/webauthn-ruby/blob/23f3be4/lib/webauthn/attestation_statement/base.rb#L163
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thank you. In that case, for the reasons mentioned above, I thought it would be better to add a custom error, which is the current modification content.
What do you think after sharing my opinion?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some part of me thinks that receiving a nil
challenge in some sense it is a challenge verification error, thus my initial idea of just re-using the ChallengeVerificationError
and, as you are correctly doing, use the message to be specific about what was the underlying issue with the challenge
.
However, I do see how using VerificationError
classes could cause confusion given that, as you correctly pointed out, VerificationError
s are dynamically raised depending on which verification was the one that failed.
Furthermore, we are already using the pattern of raising an error if there's a validation error, so I'm okay with the approach.
The If necessary, squash all commits after all reviews are complete. |
I'm just realizing that we should do this same check in |
2fb9f92
to
9f86fe4
Compare
of course. Thank you for letting me know. I fixed it with the commit bellow:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Just one minor comment and I'll proceed to merge it 🙂
Thank you so much! 🙌
@@ -36,7 +38,13 @@ def initialize( | |||
@relying_party = relying_party | |||
end | |||
|
|||
def verify(*_args) | |||
def verify(challenge, *_args) | |||
unless valid_class?(challenge) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not just:
unless valid_class?(challenge) | |
unless challenge.is_a?(String) |
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It follows the existing check processes valid_type?
and valid_id?
.
For example, valid_type?
is a simple value comparison, but it is implemented as a private
method.
Therefore, following the implementation of the entire class
, we also extracted the method as valid_class?
when checking the class
this time.
However, as you suspected, I think it is also more readable to use is_a?
in the verify
method without extracting it to the method. If you need it, please let me know so I can move it.
def self.response_class | ||
WebAuthn::AuthenticatorAttestationResponse | ||
end | ||
|
||
def verify(challenge, user_verification: nil) | ||
challenge.is_a?(String) || raise(InvalidChallengeError, "challenge must be a String. input challenge class: #{challenge.class}") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some part of me thinks that receiving a nil
challenge in some sense it is a challenge verification error, thus my initial idea of just re-using the ChallengeVerificationError
and, as you are correctly doing, use the message to be specific about what was the underlying issue with the challenge
.
However, I do see how using VerificationError
classes could cause confusion given that, as you correctly pointed out, VerificationError
s are dynamically raised depending on which verification was the one that failed.
Furthermore, we are already using the pattern of raising an error if there's a validation error, so I'm okay with the approach.
Thank you very much for giving me a good time with this PR. Also, does this PR commit require squash? Looking at other PRs, it seems that squash of commits is not necessary, but if it is necessary, please let me know. |
The same goes for you! Sorry for the back and forth, I'm lately getting back to maintaining the gem, so I'm still a little bit rough 🙂
I can just |
WebAuthn::PublicKeyCredentialWithAttestation#verify
causesNoMethodError
ifchallenge
isnil
. as below:Since
challenge
is assumed to refer to a value stored in temporary storage such assession
, there may be cases where it does not exist by accident.This change will make the error messages that occur when the above problem occurs more user-friendly and will help users of this library understand the errors.