diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/Account.java b/acme4j-client/src/main/java/org/shredzone/acme4j/Account.java index b5307ec2..60c20fb7 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/Account.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/Account.java @@ -54,6 +54,7 @@ public class Account extends AcmeJsonResource { private static final String KEY_ORDERS = "orders"; private static final String KEY_CONTACT = "contact"; private static final String KEY_STATUS = "status"; + private static final String KEY_EXTERNAL_ACCOUNT_BINDING = "externalAccountBinding"; protected Account(Login login) { super(login, login.getAccountLocation()); @@ -91,6 +92,30 @@ public class Account extends AcmeJsonResource { return getJSON().get(KEY_STATUS).asStatus(); } + /** + * Returns {@code true} if the account is bound to an external non-ACME account. + * + * @since 2.8 + */ + public boolean hasExternalAccountBinding() { + return getJSON().contains(KEY_EXTERNAL_ACCOUNT_BINDING); + } + + /** + * Returns the key identifier of the external non-ACME account. If this account is + * not bound to an external account, {@code null} is returned instead. + * + * @since 2.8 + */ + @CheckForNull + public String getKeyIdentifier() { + return getJSON().get(KEY_EXTERNAL_ACCOUNT_BINDING) + .optional().map(Value::asObject) + .map(j -> j.get("protected")).map(Value::asEncodedObject) + .map(j -> j.get("kid")).map(Value::asString) + .orElse(null); + } + /** * Returns an {@link Iterator} of all {@link Order} belonging to this {@link Account}. *
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 8e31577d..3dfe47d3 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
@@ -27,6 +27,7 @@ import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
+import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.time.Instant;
import java.util.Collections;
@@ -347,6 +348,21 @@ public final class JSON implements Serializable {
}
}
+ /**
+ * Returns the value as JSON object that was Base64 URL encoded.
+ *
+ * @since 2.8
+ */
+ public JSON asEncodedObject() {
+ required();
+ try {
+ byte[] raw = AcmeUtils.base64UrlDecode(val.toString());
+ return new JSON(path, JsonUtil.parseJson(new String(raw, StandardCharsets.UTF_8)));
+ } catch (IllegalArgumentException | JoseException ex) {
+ throw new AcmeProtocolException(path + ": expected an encoded object", ex);
+ }
+ }
+
/**
* Returns the value as {@link Problem}.
*
diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/AccountBuilderTest.java b/acme4j-client/src/test/java/org/shredzone/acme4j/AccountBuilderTest.java
index dadbcc7f..7a59346b 100644
--- a/acme4j-client/src/test/java/org/shredzone/acme4j/AccountBuilderTest.java
+++ b/acme4j-client/src/test/java/org/shredzone/acme4j/AccountBuilderTest.java
@@ -13,8 +13,7 @@
*/
package org.shredzone.acme4j;
-import static org.hamcrest.Matchers.is;
-import static org.hamcrest.Matchers.notNullValue;
+import static org.hamcrest.Matchers.*;
import static org.junit.Assert.assertThat;
import static org.shredzone.acme4j.toolbox.TestUtils.getJSON;
import static org.shredzone.acme4j.toolbox.TestUtils.url;
@@ -100,6 +99,8 @@ public class AccountBuilderTest {
Account account = login.getAccount();
assertThat(account.getTermsOfServiceAgreed(), is(true));
assertThat(account.getLocation(), is(locationUrl));
+ assertThat(account.hasExternalAccountBinding(), is(false));
+ assertThat(account.getKeyIdentifier(), is(nullValue()));
provider.close();
}
diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/AccountTest.java b/acme4j-client/src/test/java/org/shredzone/acme4j/AccountTest.java
index b74a229b..56fd1f21 100644
--- a/acme4j-client/src/test/java/org/shredzone/acme4j/AccountTest.java
+++ b/acme4j-client/src/test/java/org/shredzone/acme4j/AccountTest.java
@@ -115,6 +115,8 @@ public class AccountTest {
assertThat(account.getContacts(), hasSize(1));
assertThat(account.getContacts().get(0), is(URI.create("mailto:foo2@example.com")));
assertThat(account.getStatus(), is(Status.VALID));
+ assertThat(account.hasExternalAccountBinding(), is(true));
+ assertThat(account.getKeyIdentifier(), is("NCC-1701"));
Iterator