) meta);
+ metaMap.remove("externalAccountRequired");
+ metaMap.put("externalAccountRequired", true);
+ }
+ return JSON.fromMap(directory);
+ }
+
}
diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/toolbox/JSON.java b/acme4j-client/src/main/java/org/shredzone/acme4j/toolbox/JSON.java
index d7b2c2b0..6f06baba 100644
--- a/acme4j-client/src/main/java/org/shredzone/acme4j/toolbox/JSON.java
+++ b/acme4j-client/src/main/java/org/shredzone/acme4j/toolbox/JSON.java
@@ -118,6 +118,21 @@ public final class JSON implements Serializable {
}
}
+ /**
+ * Creates a JSON object from a map.
+ *
+ * The map's content is deeply copied. Changes to the map won't reflect in the created
+ * JSON structure.
+ *
+ * @param data
+ * Map structure
+ * @return {@link JSON} of the map's content.
+ * @since 3.2.0
+ */
+ public static JSON fromMap(Map data) {
+ return JSON.parse(JsonUtil.toJson(data));
+ }
+
/**
* Returns a {@link JSON} of an empty document.
*
diff --git a/acme4j-it/src/test/java/org/shredzone/acme4j/it/ProviderIT.java b/acme4j-it/src/test/java/org/shredzone/acme4j/it/ProviderIT.java
index 952c95da..5fcc024b 100644
--- a/acme4j-it/src/test/java/org/shredzone/acme4j/it/ProviderIT.java
+++ b/acme4j-it/src/test/java/org/shredzone/acme4j/it/ProviderIT.java
@@ -74,26 +74,33 @@ public class ProviderIT {
var sessionEcc = new Session("acme://ssl.com/ecc");
assertThat(sessionEcc.getMetadata().getWebsite()).hasValue(new URL("https://www.ssl.com"));
assertThatNoException().isThrownBy(() -> sessionEcc.resourceUrl(Resource.NEW_ACCOUNT));
- assertThat(sessionEcc.getMetadata().isExternalAccountRequired()).isFalse();
+ assertThat(sessionEcc.getMetadata().isExternalAccountRequired()).isTrue();
assertThat(sessionEcc.getMetadata().isAutoRenewalEnabled()).isFalse();
var sessionRsa = new Session("acme://ssl.com/rsa");
assertThat(sessionRsa.getMetadata().getWebsite()).hasValue(new URL("https://www.ssl.com"));
assertThatNoException().isThrownBy(() -> sessionRsa.resourceUrl(Resource.NEW_ACCOUNT));
- assertThat(sessionRsa.getMetadata().isExternalAccountRequired()).isFalse();
+ assertThat(sessionRsa.getMetadata().isExternalAccountRequired()).isTrue();
assertThat(sessionRsa.getMetadata().isAutoRenewalEnabled()).isFalse();
var sessionEccStage = new Session("acme://ssl.com/staging/ecc");
assertThat(sessionEccStage.getMetadata().getWebsite()).hasValue(new URL("https://www.ssl.com"));
assertThatNoException().isThrownBy(() -> sessionEccStage.resourceUrl(Resource.NEW_ACCOUNT));
- assertThat(sessionEccStage.getMetadata().isExternalAccountRequired()).isFalse();
+ assertThat(sessionEccStage.getMetadata().isExternalAccountRequired()).isTrue();
assertThat(sessionEccStage.getMetadata().isAutoRenewalEnabled()).isFalse();
var sessionRsaStage = new Session("acme://ssl.com/staging/rsa");
assertThat(sessionRsaStage.getMetadata().getWebsite()).hasValue(new URL("https://www.ssl.com"));
assertThatNoException().isThrownBy(() -> sessionRsaStage.resourceUrl(Resource.NEW_ACCOUNT));
- assertThat(sessionRsaStage.getMetadata().isExternalAccountRequired()).isFalse();
+ assertThat(sessionRsaStage.getMetadata().isExternalAccountRequired()).isTrue();
assertThat(sessionRsaStage.getMetadata().isAutoRenewalEnabled()).isFalse();
+
+ // If these tests fail, the metadata have been fixed on server side. Then remove
+ // the patch at ZeroSSLAcmeProvider, and update the documentation.
+ var sessionEABCheck = new Session("https://acme.ssl.com/sslcom-dv-ecc");
+ assertThat(sessionEABCheck.getMetadata().isExternalAccountRequired()).isFalse();
+ var sessionEABCheckStage = new Session("https://acme-try.ssl.com/sslcom-dv-ecc");
+ assertThat(sessionEABCheckStage.getMetadata().isExternalAccountRequired()).isFalse();
}
/**
diff --git a/src/doc/docs/ca/sslcom.md b/src/doc/docs/ca/sslcom.md
index 0f49ad27..7fcd537d 100644
--- a/src/doc/docs/ca/sslcom.md
+++ b/src/doc/docs/ca/sslcom.md
@@ -13,7 +13,7 @@ Available since acme4j 3.2.0
## Note
-* This CA requires [External Account Binding (EAB)](../usage/account.md#external-account-binding) for account creation. However `Metadata.isExternalAccountRequired()` returns `false` due to an error in the CA's directory resource.
+* This CA requires [External Account Binding (EAB)](../usage/account.md#external-account-binding) for account creation. However, the CA's directory resource returns `externalAccountRequired` as `false`, which is incorrect. If you use one of the `acme:` URIs above, _acme4j_ will patch the metadata transparently. If you directly connect to SSL.com via `https:` URI though, `Metadata.isExternalAccountRequired()` could return a wrong value. (As of February 2024)
## Disclaimer