Reimplement security-webauthn on top of webauthn4j#44105
Reimplement security-webauthn on top of webauthn4j#44105sberyozkin merged 9 commits intoquarkusio:mainfrom
Conversation
|
Huh, I had completely forgotten I added |
|
And quickstarts are at quarkusio/quarkus-quickstarts#1470 |
|
WebAuthnHelper part is #44106 |
|
🙈 The PR is closed and the preview is expired. |
This comment has been minimized.
This comment has been minimized.
|
Sorry I'm noob in webauthn - does this break users or allow them to coexist ? And what kind of users are affected - Quarkus app devs or/and ext dev? |
|
The compatibility breakage is for users, but the module is in preview so we can break. |
|
Quickstarts break is handled by the PR. The native one I need to look at. |
|
Native should pass now. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
Will check tomorrow evening. |
|
Hi Steph, @FroMage, thanks for this major enhancement/refactoring, I have to do some homework to do a proper review, need to refresh some WebAuthn concepts and check webauthn4j docs, may take a bit of time, but I'm on it, cheers |
| && config.attestation().get() == WebAuthnRunTimeConfig.Attestation.ENTERPRISE) { | ||
| TrustAnchorAsyncRepository something; | ||
| // FIXME: make config name configurable? | ||
| Optional<TlsConfiguration> webauthnTlsConfiguration = certificates.get("webauthn"); |
There was a problem hiding this comment.
WebAuthn attestation certificate is not related to TLS.
Is it appropriate to use TlsConfigurationRegistry for webauthn attestation certificate?
There was a problem hiding this comment.
It's definitely not related to TLS, but for some reason the Quarkus certificate registry is called the TLS registry https://quarkus.io/guides/tls-registry-reference
This is just how every certificate list (and trust stores, private, public keys) are configured in Quarkus.
I do agree that the name implies a single purpose that is limiting, @cescoffier
There was a problem hiding this comment.
Ha ha, @sberyozkin stopped me from using it from anything that is not TLS when I integrated this registry to OIDC. I agree, it would be nice to have Quarkus certificate registry, but there are things that doesn't make sense when you use it this way. Like handshakeTimeout, alpn and other stuff. I suppose it is fine for your use case because I think users does not configure this, right?
There was a problem hiding this comment.
Well, @cescoffier himself told me to use this, to centralise everything 🤷
There was a problem hiding this comment.
@FroMage TLS registry entries have properties related to TLS like handshake timeout, host verification options, reload related one, etc. If the attestation is not happening on the TLS path, it can be confusing for Quarkus WebAuthn users having to refer to TLS registry...
TLS registry is a great concept, but perhaps it can be enhanced over time to extend say TrustStoreRegistry instead of having to refer to it on the non-TLS paths
|
Sorry, it has been hectic week I must look later. But since @ynojima and @sberyozkin are going to have a look, I think it's not an issue. Great PR. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
…security/webauthn/WebAuthnUserProvider.java Co-authored-by: Sergey Beryozkin <sberyozkin@gmail.com>
…security/webauthn/WebAuthnUserProvider.java Co-authored-by: Sergey Beryozkin <sberyozkin@gmail.com>
Status for workflow
|
Status for workflow
|
| Status | Name | Step | Failures | Logs | Raw logs | Build scan |
|---|---|---|---|---|---|---|
| ✖ | Quickstarts Compilation - JDK 17 | Compile Quickstarts |
Failures | Logs | Raw logs | 🚧 |
| ✖ | Native Tests - Virtual Thread - Messaging | Build |
Logs | Raw logs | 🔍 |
You can consult the Develocity build scans.
Failures
⚙️ Quickstarts Compilation - JDK 17 #
- Failing: security-webauthn-quickstart security-webauthn-reactive-quickstart
📦 security-webauthn-quickstart
✖ Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.11.0:compile (default-compile) on project security-webauthn-quickstart: Compilation failure
📦 security-webauthn-reactive-quickstart
✖ Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.11.0:compile (default-compile) on project security-webauthn-reactive-quickstart: Compilation failure
Flaky tests - Develocity
⚙️ Native Tests - Messaging1
📦 integration-tests/reactive-messaging-kafka
✖ io.quarkus.it.kafka.KafkaConnectorIT.testRequestReply - History
iterable contents differ at index [2], expected: <reply-3> but was: <{"details":"Error id edb8cb3a-bc93-4331-ae9f-aa3fb9ba0561-1","stack":""}>-org.opentest4j.AssertionFailedError
Details
org.opentest4j.AssertionFailedError: iterable contents differ at index [2], expected: <reply-3> but was: <{"details":"Error id edb8cb3a-bc93-4331-ae9f-aa3fb9ba0561-1","stack":""}>
at io.quarkus.it.kafka.KafkaConnectorTest.testRequestReply(KafkaConnectorTest.java:112)
at java.base/java.lang.reflect.Method.invoke(Method.java:569)
at io.quarkus.test.junit.QuarkusTestExtension.interceptTestMethod(QuarkusTestExtension.java:788)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
|
Thanks. |
|
I was going to ask for integrating something in the migration guide but it's already done! Thanks! |
These default value was introduced in quarkusio#44105, but the doc was not aligned.
These default values were introduced in quarkusio#44105, but the doc was not aligned.
These default values were introduced in quarkusio#44105, but the doc was not aligned.
These default values were introduced in quarkusio#44105, but the doc was not aligned.
This is following in the footsteps of the new vertx-auth-webauthn4j, which we're not using here because there was no point in converting our config to vertx config which converts to webauthn4j config.
I also took the opportunity to improve the docs and fix the API and endpoints to remove confusion.
As a result, this is not compatible with the previous API, here's the proposed migration guide, which I'll add in the migration notes as soon as we know where we merge this.
== Migration Guide
The
quarkus-security-webauthnmodule has been reimplemented on top of WebAuthn4J. As a result, it is not binary or source compatible with the previous versions, and you must update the following code:AuthenticatortypeAuthenticatorclass (from Vert.x) is no longer used, and has been replaced functionally withWebAuthnCredentialRecord. It holds similar data to the previous class, but as it is a subtype of a WebAuthn4J type, accessing its content is slightly different.WebAuthnCredentialRecordnow has agetRequiredPersistedData()method which returns aRequiredPersistedDatarecord holding all the data you need to persist to your data source (database, or anything persistent), to make it easier.WebAuthnCredentialRecord.fromRequiredPersistedData(RequiredPersistedData)allows you to turn your stored data into aWebAuthnCredentialRecordfor the opposite operation.Authenticatorformat of data, you will need to update them to the new set of data. Open an issue if you need help for that.WebAuthnUserProvidertype that you had to implement has been restructured:findWebAuthnCredentialsByUserName()was renamed tofindByUserName()findWebAuthnCredentialsByCredID()was renamed tofindByCredentialId()updateOrStoreWebAuthnCredentialswas split into the two methods it represented:update(String credentialId, long counter)andstore(WebAuthnCredentialRecord credentialRecord)/q/webauthn/loginwas renamed to/q/webauthn/login-options-challenge/q/webauthn/registerwas renamed to/q/webauthn/register-options-challenge/q/webauthn/callbackwas split into the two operations it represented:/q/webauthn/loginand/q/webauthn/register. These endpoints are now disabled by default (for security reasons) and can be enabled using thequarkus.webauthn.enable-registration-endpointandquarkus.webauthn.enable-login-endpointconfiguration properties./q/webauthn/registernow requires ausernamequery parameter./.well-known/webauthnwas added to return the list of allowed related originsloginandlogin-options-challengeis now optionalWebAuthnSecurityWebAuthnSecurity:getLoginOptionsChallenge()andgetRegisterOptionsChallenge()to make it easier to call and customise them.login()andloginOptionsChallenge()is now optionalregister()method now takes an additionaluserNameparameter (due to the removal of the username cookie)quarkus.webauthn.require-resident-key(boolean defaulting tofalse) setting has been replaced by thequarkus.webauthn.resident-key(enum defaulting toREQUIRED)quarkus.webauthn.challenge-username-cookie-namesetting has been removed along with its related cookie.quarkus.webauthn.load-metadata(boolean defaulting tofalse) setting has been added to control loading of FIDO metadata.quarkus.webauthn.user-presence-required(boolean defaulting totrue) setting has been added to control the requirement of user presence.quarkus.webauthn.user-verificationsetting has changed default fromDISCOURAGEDtoREQUIRED.quarkus.webauthn.timeoutdefault has increased from1 minuteto5 minutesas specified in the WebAuthn standardquarkus.webauthn.pub-key-cred-paramssetting has been renamed toquarkus.webauthn.public-key-credential-parametersquarkus.webauthn.originsetting has been renamed toquarkus.webauthn.origins(plural) and now allows more than one origin (as required by spec)quarkus.webauthn.enable-registration-endpointboolean configuration (defaults tofalse) enables the default registration endpoint.quarkus.webauthn.enable-login-endpointboolean configuration (defaults tofalse) enables the default login endpoint.quarkus.security.webauthn.attestationother thanNONE(the default).quarkus-test-security-webauthntest module:WebAuthnHardwarecontructor now requires aURLto represent the location of your endpoints, you can obtain in your test classes it using@TestHTTPResource URL urlWebAuthnEndpointHelper.invokeRegistrationmethod was renamed toobtainRegistrationChallengeWebAuthnEndpointHelper.invokeLoginmethod was renamed toobtainLoginChallengeWebAuthnEndpointHelper.invokeCallbackmethod was split into the two operations it represented:WebAuthnEndpointHelper.invokeRegistrationandWebAuthnEndpointHelper.invokeLoginWebAuthnEndpointHelper.invokeLoginandWebAuthnEndpointHelper.obtainLoginChallengeuser name parameter is now optionalWebAuthnEndpointHelper.invokeRegistrationmethod now takes auserNameparameterregisterOnlymethod has been renamed toregisterClientStepsloginOnlymethod has been renamed tologinClientStepsloginandloginClientStepsmethod'suserparameter is now optionalregisterPathhas been renamed toregisterOptionsChallengePathand has the default value/q/webauthn/register-options-challengeloginPathhas been renamed tologinOptionsChallengePathand has the default value/q/webauthn/login-options-challengecallbackPathhas been split into its two componentsregisterPath(default value/q/webauthn/register) andloginPath(default value/q/webauthn/logincsrfoption of typeJsonObjectwith two keys:headerfor the header name to use to add the CSRF token, andvaluefor the CSRF token value. This is mostly useful when usingquarkus-csrfand using custom endpoints that are protected by CSRF (unlike the default endpoints).