mirror of https://github.com/shred/acme4j
Return external account binding key identifier
parent
d02746156d
commit
210b2aa453
|
@ -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}.
|
||||
* <p>
|
||||
|
|
|
@ -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}.
|
||||
*
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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<Order> orderIt = account.getOrders();
|
||||
assertThat(orderIt, not(nullValue()));
|
||||
|
|
|
@ -112,7 +112,6 @@ public class JSONBuilderTest {
|
|||
* Test JWK.
|
||||
*/
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testKey() throws IOException, JoseException {
|
||||
KeyPair keyPair = TestUtils.createKeyPair();
|
||||
|
||||
|
|
|
@ -105,7 +105,7 @@ public class JSONTest {
|
|||
|
||||
assertThat(json.keySet(), containsInAnyOrder(
|
||||
"text", "number", "boolean", "uri", "url", "date", "array",
|
||||
"collect", "status", "binary", "duration", "problem"));
|
||||
"collect", "status", "binary", "duration", "problem", "encoded"));
|
||||
assertThat(json.contains("text"), is(true));
|
||||
assertThat(json.contains("music"), is(false));
|
||||
assertThat(json.get("text"), is(notNullValue()));
|
||||
|
@ -233,6 +233,9 @@ public class JSONTest {
|
|||
JSON sub = array.get(3).asObject();
|
||||
assertThat(sub.get("test").asString(), is("ok"));
|
||||
|
||||
JSON encodedSub = json.get("encoded").asEncodedObject();
|
||||
assertThat(encodedSub.toString(), is(sameJSONAs("{\"key\":\"value\"}")));
|
||||
|
||||
Problem problem = json.get("problem").asProblem(BASE_URL);
|
||||
assertThat(problem, is(notNullValue()));
|
||||
assertThat(problem.getType(), is(URI.create("urn:ietf:params:acme:error:rateLimited")));
|
||||
|
@ -294,6 +297,13 @@ public class JSONTest {
|
|||
// expected
|
||||
}
|
||||
|
||||
try {
|
||||
json.get("none").asEncodedObject();
|
||||
fail("asEncodedObject did not fail");
|
||||
} catch (AcmeProtocolException ex) {
|
||||
// expected
|
||||
}
|
||||
|
||||
try {
|
||||
json.get("none").asStatus();
|
||||
fail("asStatus did not fail");
|
||||
|
@ -344,6 +354,13 @@ public class JSONTest {
|
|||
// expected
|
||||
}
|
||||
|
||||
try {
|
||||
json.get("text").asEncodedObject();
|
||||
fail("no exception was thrown");
|
||||
} catch (AcmeProtocolException ex) {
|
||||
// expected
|
||||
}
|
||||
|
||||
try {
|
||||
json.get("text").asArray();
|
||||
fail("no exception was thrown");
|
||||
|
|
|
@ -14,5 +14,6 @@
|
|||
"type": "urn:ietf:params:acme:error:rateLimited",
|
||||
"detail": "too many requests",
|
||||
"instance": "/documents/errors.html"
|
||||
}
|
||||
},
|
||||
"encoded": "eyJrZXkiOiJ2YWx1ZSJ9"
|
||||
}
|
||||
|
|
|
@ -4,5 +4,10 @@
|
|||
"mailto:foo2@example.com"
|
||||
],
|
||||
"termsOfServiceAgreed": true,
|
||||
"orders": "https://example.com/acme/acct/1/orders"
|
||||
"orders": "https://example.com/acme/acct/1/orders",
|
||||
"externalAccountBinding": {
|
||||
"protected": "eyJ1cmwiOiJodHRwOi8vZXhhbXBsZS5jb20vYWNtZS9yZXNvdXJjZSIsImtpZCI6Ik5DQy0xNzAxIiwiYWxnIjoiSFMyNTYifQ",
|
||||
"payload": "eyJrdHkiOiJSU0EiLCJuIjoicFpzVEtZNDF5X0N3Z0owVlg3Qm1tR3NfN1Vwcm1YUU1HUGNuU2JCZUpBalpIQTlTeXlKS2FXdjRmTlVkQklBWDNZMlFvWml4ajUwblFMeUx2Mm5nM3B2RW9STDBzeDlaSGdwNW5kQWpwSWlWUV84VjAxVFRZQ0VEVWM5aWk3YmpWa2dGQWI0VmFsWkdGSlo1NFBjQ25BSHZYaTVnMEVMT1J6R2NUdVJxSFZBVWNrTVYyb3RyMGcwdV81YldNbTZFTUFiQnJHUUNnVUdqYlpRSGphdmExWS01dEhYWmtQQmFoSjJMdktScU1tSlVscjBhbkt1Skp0SlVHMDNESllBeEFCdjhZQWFYRkJuR3c2a0tKUnBVRkFDNTVyeTRzcDRrR3kwTnJLMlRWV21aVzlrU3RuaVJ2NFJhSkdJOWFaR1l3UXkya1V5a2liQk5tV0VRVWxJd0l3IiwiZSI6IkFRQUIifQ",
|
||||
"signature": "skPdpjTgx8zIGsNRtvv4zNlfp-uidFDgCMY3Z3ONLgw"
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue