diff --git a/NEWS b/NEWS
index b413e25c2..4129d9baa 100644
--- a/NEWS
+++ b/NEWS
@@ -20,6 +20,11 @@ Fixes:
handle are both absent unless a user handle was returned by the authenticator.
This was originally released in pre-release `1.12.3-RC3`, but was accidentally
left out of the `1.12.3` release.
+* Fixed regression in
+ `PublicKeyCredentialCreationOptions.toCredentialsCreateJson()`, which has not
+ been emitting a `requireResidentKey` member since version `2.0.0`. This meant
+ the JSON output was not backwards compatible with browsers that only support
+ the Level 1 version of the WebAuthn spec.
New features:
diff --git a/doc/Migrating_from_v1.adoc b/doc/Migrating_from_v1.adoc
index eb19d0848..b8f04803b 100644
--- a/doc/Migrating_from_v1.adoc
+++ b/doc/Migrating_from_v1.adoc
@@ -26,10 +26,12 @@ Here is a high-level outline of what needs to be updated:
- Update `getUserVerification()` and `getResidentKey()` calls
to expect `Optional` values.
-This migration guide is written for version `2.0.0` of the
+Although the next section references version `2.4.0-RC2` for reasons detailed there,
+this migration guide is written for version `2.0.0` of the
`webauthn-server-core` module. Later `2.x` versions may introduce new features
-but should remain compatible without further changes; consult the release notes
-for a full list of new features.
+but should remain compatible without further changes; please consult the
+link:https://developers.yubico.com/java-webauthn-server/Release_Notes.html[release notes]
+for an up to date list of new features.
== Replace dependency on `webauthn-server-core-minimal`
@@ -46,7 +48,7 @@ Maven example:
- webauthn-server-core-minimal
- 1.12.2
+ webauthn-server-core
-+ 2.0.0
++ 2.4.0-RC2
compile
----------
@@ -56,10 +58,30 @@ Gradle:
[source,diff]
----------
-compile 'com.yubico:webauthn-server-core-minimal:1.12.2'
-+compile 'com.yubico:webauthn-server-core:2.0.0'
++compile 'com.yubico:webauthn-server-core:2.4.0-RC2'
----------
+[WARNING]
+.*Backwards-incompatible regression in versions 2.0.0 to 2.4.0-RC1*
+==========
+Versions in the inclusive range `2.0.0` to `2.4.0-RC1` have
+a backwards-incompatible regression in
+link:https://developers.yubico.com/java-webauthn-server/JavaDoc/webauthn-server-core/latest/com/yubico/webauthn/data/PublicKeyCredentialCreationOptions.html#toCredentialsCreateJson()[`PublicKeyCredentialCreationOptions.toCredentialsCreateJson()`]:
+When the
+link:https://developers.yubico.com/java-webauthn-server/JavaDoc/webauthn-server-core/2.3.0/com/yubico/webauthn/StartRegistrationOptions.StartRegistrationOptionsBuilder.html#authenticatorSelection(com.yubico.webauthn.data.AuthenticatorSelectionCriteria)[`authenticatorSelection`].link:https://developers.yubico.com/java-webauthn-server/JavaDoc/webauthn-server-core/2.3.0/com/yubico/webauthn/data/AuthenticatorSelectionCriteria.AuthenticatorSelectionCriteriaBuilder.html#residentKey(com.yubico.webauthn.data.ResidentKeyRequirement)[`residentKey`]
+parameter is set, a corresponding
+link:https://www.w3.org/TR/webauthn-2/#dom-authenticatorselectioncriteria-requireresidentkey[`requireResidentKey`]
+member is not emitted in the JSON output.
+This is not backwards compatible with browsers that only support the
+link:https://www.w3.org/TR/2019/REC-webauthn-1-20190304/#authenticatorSelection[Level 1 version of the WebAuthn spec].
+The regression is fixed in version `2.4.0-RC2` and greater.
+We therefore urge users to upgrade from versions `1.x` directly to `2.4.0-RC2` or greater to maintain backwards compatibility.
+Please consult the link:https://developers.yubico.com/java-webauthn-server/Release_Notes.html[release notes]
+for an up to date list of additional changes and new features added since version `2.0.0`.
+==========
+
+
== Add JCA provider for EdDSA
The library no longer depends explicitly on BouncyCastle for cryptography back-ends.
diff --git a/webauthn-server-core/src/main/java/com/yubico/webauthn/data/AuthenticatorSelectionCriteria.java b/webauthn-server-core/src/main/java/com/yubico/webauthn/data/AuthenticatorSelectionCriteria.java
index ec3566bd0..4fde736f2 100644
--- a/webauthn-server-core/src/main/java/com/yubico/webauthn/data/AuthenticatorSelectionCriteria.java
+++ b/webauthn-server-core/src/main/java/com/yubico/webauthn/data/AuthenticatorSelectionCriteria.java
@@ -100,6 +100,14 @@ public Optional getAuthenticatorAttachment() {
* By default, this is not set. When not set, the default in the browser is {@link
* ResidentKeyRequirement#DISCOURAGED}.
*
+ *
When this is set, {@link PublicKeyCredentialCreationOptions#toCredentialsCreateJson()} will
+ * also emit a
+ * requireResidentKey
member for backwards compatibility with WebAuthn Level 1.
+ * It will be set to true
if this is set to {@link ResidentKeyRequirement#REQUIRED
+ * REQUIRED} and false
if this is set to anything else. When this is not set, a
+ * requireResidentKey
will not be emitted.
+ *
* @see ResidentKeyRequirement
* @see ยง5.4.6.
@@ -112,6 +120,19 @@ public Optional getResidentKey() {
return Optional.ofNullable(residentKey);
}
+ /**
+ * For backwards compatibility with requireResidentKey
.
+ *
+ * @see 5.4.4.
+ * Authenticator Selection Criteria (dictionary AuthenticatorSelectionCriteria) member
+ * requireResidentKey
+ */
+ @JsonProperty
+ private Boolean isRequireResidentKey() {
+ return getResidentKey().map(rk -> rk == ResidentKeyRequirement.REQUIRED).orElse(null);
+ }
+
/**
* Describes the Relying Party's requirements regarding user
diff --git a/webauthn-server-core/src/test/scala/com/yubico/webauthn/RelyingPartyStartOperationSpec.scala b/webauthn-server-core/src/test/scala/com/yubico/webauthn/RelyingPartyStartOperationSpec.scala
index 2d7222bc0..7b491b189 100644
--- a/webauthn-server-core/src/test/scala/com/yubico/webauthn/RelyingPartyStartOperationSpec.scala
+++ b/webauthn-server-core/src/test/scala/com/yubico/webauthn/RelyingPartyStartOperationSpec.scala
@@ -24,6 +24,7 @@
package com.yubico.webauthn
+import com.yubico.internal.util.JacksonCodecs
import com.yubico.webauthn.Generators._
import com.yubico.webauthn.data.AssertionExtensionInputs
import com.yubico.webauthn.data.AttestationConveyancePreference
@@ -33,6 +34,7 @@ import com.yubico.webauthn.data.AuthenticatorTransport
import com.yubico.webauthn.data.ByteArray
import com.yubico.webauthn.data.Generators.Extensions.registrationExtensionInputs
import com.yubico.webauthn.data.Generators._
+import com.yubico.webauthn.data.PublicKeyCredentialCreationOptions
import com.yubico.webauthn.data.PublicKeyCredentialDescriptor
import com.yubico.webauthn.data.PublicKeyCredentialParameters
import com.yubico.webauthn.data.RegistrationExtensionInputs
@@ -454,18 +456,37 @@ class RelyingPartyStartOperationSpec
.build()
)
+ def jsonRequireResidentKey(
+ pkcco: PublicKeyCredentialCreationOptions
+ ): Option[Boolean] =
+ Option(
+ JacksonCodecs
+ .json()
+ .readTree(pkcco.toCredentialsCreateJson)
+ .get("publicKey")
+ .get("authenticatorSelection")
+ .get("requireResidentKey")
+ ).map(_.booleanValue)
+
pkccoDiscouraged.getAuthenticatorSelection.get.getResidentKey.toScala should be(
Some(ResidentKeyRequirement.DISCOURAGED)
)
+ jsonRequireResidentKey(pkccoDiscouraged) should be(Some(false))
+
pkccoPreferred.getAuthenticatorSelection.get.getResidentKey.toScala should be(
Some(ResidentKeyRequirement.PREFERRED)
)
+ jsonRequireResidentKey(pkccoPreferred) should be(Some(false))
+
pkccoRequired.getAuthenticatorSelection.get.getResidentKey.toScala should be(
Some(ResidentKeyRequirement.REQUIRED)
)
+ jsonRequireResidentKey(pkccoRequired) should be(Some(true))
+
pkccoUnspecified.getAuthenticatorSelection.get.getResidentKey.toScala should be(
None
)
+ jsonRequireResidentKey(pkccoUnspecified) should be(None)
}
it("respects the authenticatorAttachment parameter.") {