java-webauthn-server
java-webauthn-server copied to clipboard
Persist CredentialRegistration
This is more a best-practice question than an issue.
I followed the examples and demo code and am currently struggling to switch from an InMemoryStorageRegistration to a persistent one. CredentialRegistration is a quite complex object and not serializable which makes persistence nearly impossible.
Any suggestions on how to permanently persist CredentialRegistration are highly appreciated. Thanks.
Hi! The CredentialRegistration
type isn't meant to be used directly in downstream projects, it's rather intended as an example, which is why it's in the demo subproject. The actual integration point with the library is the RegisteredCredential
type in the core module, which is what's used as a return type in CredentialRepository
. We don't want to tie ourselves to any particular serialization or persistence framework, so the idea is that downstream projects can store the data however they want, and transform the stored data into RegisteredCredential
objects when needed for the CredentialRepository
. See for example the implementation of lookup()
in InMemoryRegistrationStorage
, which transforms the storage type on the fly as needed.
Does that help?
I should add some javadoc to CredentialRegistration
and InMemoryRegistrationStorage
, as well as the "getting started" docs, to try to make this a bit clearer. Maybe also rewrite InMemoryRegistrationStorage
to use an in-memory SQL database to get closer to what it's likely to look like in a real project.
Hey! Abstracting the actual way of persisting makes total sense. I think i was struggling with the examples, as even the InMemoryRegistrationStorage has references to the CredentialRegistration. It makes it hard to understand of what exactly needs to be stored and how.
Even the example on the tutorial
storeCredential( // Some database access method of your own design
"alice", // Username or other appropriate user identifier
result.getKeyId(), // Credential ID and transports for allowCredentials
result.getPublicKeyCose(), // Public key for verifying authentication signatures
result.isDiscoverable(), // Can this key be used for username-less auth?
result.signatureCount(), // Initial signature counter value
pkc.getResponse().getAttestationObject(), // Store attestation object for future reference
pkc.getResponse().getClientDataJSON() // Store client data for re-verifying signature if needed
);
brings at least two data types (pkc.getResponse().getAttestationObject()
and pkc.getResponse().getClientDataJSON()
) which you need to work around to get them stored. BTW result.signatureCount()
is result.getSignatureCount()
😉
I ended up disassembling CredentialRegistration into storable data through DAOs and assembling it again when needed. Lots of code with conversions, but it works 😄
Sorry to asked another question on top of this, but the one thing I couldn't figure out is how to store and handle multiple credentials for the same user. Is there any example on that?
I think i was struggling with the examples, as even the InMemoryRegistrationStorage has references to the CredentialRegistration.
Yeah, I'll take a new pass later at touching up the demo examples a bit. Your feedback is much appreciated!
BTW
result.signatureCount()
isresult.getSignatureCount()
Thanks!
Sorry to asked another question on top of this, but the one thing I couldn't figure out is how to store and handle multiple credentials for the same user. Is there any example on that?
In the current InMemoryRegistrationStorage
it's done by simply storing credentials in a Set
per user account.
In a different project where we used this library, we stored credentials in an SQL table (using jOOQ for database mapping) with columns including user ID, credential ID, public key (the raw result.getPublicKeyCose()
bytes), signature counter and raw attestation object, I think. Important to note is that we did not set a unique constraint on the user ID column.