Yubico / java-webauthn-server

Server-side Web Authentication library for Java https://www.w3.org/TR/webauthn/#rp-operations
Other
469 stars 143 forks source link

How to set authenticatorSelection and excludeCredentials before startRegistration will used #182

Closed igorlogvin closed 2 years ago

igorlogvin commented 2 years ago

Hello, dear developers. I need to get the following values ​​from the PublicKeyCredentialCreationOptions that the rp.startRegistration method returns:

//some properties
"excludeCredentials": [
    {
      "id": "...",
      "type": "public-key",
      "transports": [
        "internal"
      ]
    }
"authenticatorSelection": {
    "authenticatorAttachment": "platform",
    "userVerification": "required"
  }

But i see empty exclude credentials into PublicKeyCredentialCreationOptions. Who can tell me how to control that properties before PublicKeyCredentialCreationOptions was created? Thanks for your time.

emlun commented 2 years ago

Hi!

You can set authenticatorSelection directly in StartRegistrationOptions:

UserId userId = /* ... */;
RelyingParty rp = /* ... */;

PublicKeyCredentialCreationOptions pkcco = rp.startRegistration(
  StartRegistrationOptions.builder()
    .user(userId)
    .authenticatorSelection(AuthenticatorSelectionCriteria.builder()
      .authenticatorAttachment(AuthenticatorAttachment.PLATFORM)
      .residentKey(ResidentKeyRequirement.REQUIRED)
      .build())
    .build()
)

excludeCredentials will be set automatically to contain all credentials returned by CredentialRepository.getCredentialIdsForUsername(String). You can't set it directly before calling RelyingParty.startRegistration(), but you can modify it afterwards if you need to. RelyingParty keeps no internal state, so you can just pass the modified PublicKeyCredentialCreationOptions in as a parameter:

RelyingParty rp = /* ... */;
PublicKeyCredentialCreationOptions pkcco = rp.startRegistration(/* ... */)
  .toBuilder()
  .excludeCredentials(Collections.singleton(
    PublicKeyCredentialDescriptor.builder()
      .id(ByteArray.fromHex("aabbccddeeff"))
      .build()
    ))
  .build();

PublicKeyCredential pkc = /* ... */;

RegistrationResult = rp.finishRegistration(FinishRegistrationOptions.builder()
  .request(pkcco)
  .response(pkc)
  .build()
);

But the recommended way to set excludeCredentials is to simply implement CredentialRepository.getCredentialIdsForUsername(String) to return a PublicKeyCredentialDescriptor for each credential registered to that username.

igorlogvin commented 2 years ago

Hello, emlun! Thanks for the detailed answer to my question. I did not immediately understand all the constructors and builders. Thanks for the tip I learned everything I wanted. Have a nice day!

Hi!

You can set authenticatorSelection directly in StartRegistrationOptions:

UserId userId = /* ... */;
RelyingParty rp = /* ... */;

PublicKeyCredentialCreationOptions pkcco = rp.startRegistration(
  StartRegistrationOptions.builder()
    .user(userId)
    .authenticatorSelection(AuthenticatorSelectionCriteria.builder()
      .authenticatorAttachment(AuthenticatorAttachment.PLATFORM)
      .residentKey(ResidentKeyRequirement.REQUIRED)
      .build())
    .build()
)

excludeCredentials will be set automatically to contain all credentials returned by CredentialRepository.getCredentialIdsForUsername(String). You can't set it directly before calling RelyingParty.startRegistration(), but you can modify it afterwards if you need to. RelyingParty keeps no internal state, so you can just pass the modified PublicKeyCredentialCreationOptions in as a parameter:

RelyingParty rp = /* ... */;
PublicKeyCredentialCreationOptions pkcco = rp.startRegistration(/* ... */)
  .toBuilder()
  .excludeCredentials(Collections.singleton(
    PublicKeyCredentialDescriptor.builder()
      .id(ByteArray.fromHex("aabbccddeeff"))
      .build()
    ))
  .build();

PublicKeyCredential pkc = /* ... */;

RegistrationResult = rp.finishRegistration(FinishRegistrationOptions.builder()
  .request(pkcco)
  .response(pkc)
  .build()
);

But the recommended way to set excludeCredentials is to simply implement CredentialRepository.getCredentialIdsForUsername(String) to return a PublicKeyCredentialDescriptor for each credential registered to that username.

emlun commented 2 years ago

Great, glad I could help!