Closed rksk closed 11 months ago
Hi! This sounds like you are giving each credential a unique user handle, even credentials that belong to the same user. Is that the case? The user handle should be unique per user but shared between all credentials for that user.
Thanks a lot for the quick reply.
I believe we can use the same UserHandle during the registration if credentialRepository.getUserHandleForUsername() returns a value for the given user.
Sorry, I don't understand what you mean by that. Could you elaborate?
Sorry, let me add more information.
Currently, in our application, we assign a new random value for user handle for each registration request. Therefore, if a single user registers multiple devices, they will get assigned with different user handle values.
As per your suggestion, my understanding is that we can first search for existing records in the credentialRepository for the same user and use the existing user handle instead of a random value.
I just noticed that the same is included in this sample in the readme.
Optional<UserIdentity> findExistingUser(String username) { /* ... */ }
PublicKeyCredentialCreationOptions request = rp.startRegistration(
StartRegistrationOptions.builder()
.user(
findExistingUser("alice")
.orElseGet(() -> {
byte[] userHandle = new byte[64];
random.nextBytes(userHandle);
return UserIdentity.builder()
.name("alice")
.displayName("Alice Hypothetical")
.id(new ByteArray(userHandle))
.build();
})
)
.build());
Yes, that is how the WebAuthn API (not just this library) is intended to be used. And yes, setting different user handles for different credentials for the same user will cause issues like the one you're seeing.
Thank you very much for the quick help on this 🤝
Happy to help, I'm glad it worked out!
During the device registration, userHandle is populated with the userEntity.id as mentioned here. But it is possible to get userHandle as null during the authentication for FIDO U2F devices as mentioned here.
In the current implementation, it tires to get the userHandle from credentialRepository via getUserHandleForUsername() if the userHandle was null, ref. But when there are multiple devices registered under the same username, it the credentialRepository might return one of them. Now when credentialRepository.lookup() is invoked with credential id and userHandle from here, it won't match with any entry in the credentialRepository due to incorrect userHandle.
W3 says following here.
But as far as I read the code, it seems we are always trying to validate both credentialId and userHandle.
It would be really great if you could help understanding whether this flow can be handled in a different way or needs to be fixed in the library.