diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/Login.java b/acme4j-client/src/main/java/org/shredzone/acme4j/Login.java index 9ce189f8..a440c64b 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/Login.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/Login.java @@ -125,7 +125,7 @@ public class Login { * Creates a new instance of {@link Challenge} and binds it to this login. * * @param location - * Location URL of the order + * Location URL of the challenge * @return {@link Challenge} bound to the login * @since 2.8 */ @@ -139,6 +139,28 @@ public class Login { } } + /** + * Creates a new instance of a challenge and binds it to this login. + * + * @param location + * Location URL of the challenge + * @param type + * Expected challenge type + * @return Challenge bound to the login + * @throws AcmeProtocolException + * if the challenge found at the location does not match the expected + * challenge type. + * @since 2.12 + */ + public C bindChallenge(URL location, Class type) { + Challenge challenge = bindChallenge(location); + if (!type.isInstance(challenge)) { + throw new AcmeProtocolException("Challenge type " + challenge.getType() + + " does not match requested class " + type); + } + return type.cast(challenge); + } + /** * Creates a {@link Challenge} instance for the given challenge data. * diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/LoginTest.java b/acme4j-client/src/test/java/org/shredzone/acme4j/LoginTest.java index 42051f5d..03059eb6 100644 --- a/acme4j-client/src/test/java/org/shredzone/acme4j/LoginTest.java +++ b/acme4j-client/src/test/java/org/shredzone/acme4j/LoginTest.java @@ -15,6 +15,7 @@ package org.shredzone.acme4j; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; +import static org.junit.Assert.fail; import static org.mockito.Mockito.*; import static org.shredzone.acme4j.toolbox.TestUtils.getJSON; import static org.shredzone.acme4j.toolbox.TestUtils.url; @@ -27,7 +28,9 @@ import java.security.KeyPair; import org.junit.Test; import org.mockito.ArgumentMatchers; import org.shredzone.acme4j.challenge.Challenge; +import org.shredzone.acme4j.challenge.Dns01Challenge; import org.shredzone.acme4j.challenge.Http01Challenge; +import org.shredzone.acme4j.exception.AcmeProtocolException; import org.shredzone.acme4j.provider.AcmeProvider; import org.shredzone.acme4j.provider.TestableConnectionProvider; import org.shredzone.acme4j.toolbox.JSON; @@ -146,6 +149,7 @@ public class LoginTest { URL locationUrl = new URL("https://example.com/acme/challenge/1"); Http01Challenge mockChallenge = mock(Http01Challenge.class); + when(mockChallenge.getType()).thenReturn(Http01Challenge.TYPE); JSON httpChallenge = getJSON("httpChallenge"); TestableConnectionProvider provider = new TestableConnectionProvider() { @Override @@ -170,6 +174,17 @@ public class LoginTest { Challenge challenge = login.bindChallenge(locationUrl); assertThat(challenge, is(instanceOf(Http01Challenge.class))); assertThat(challenge, is(sameInstance(mockChallenge))); + + Http01Challenge challenge2 = login.bindChallenge(locationUrl, Http01Challenge.class); + assertThat(challenge2, is(sameInstance(mockChallenge))); + + try { + login.bindChallenge(locationUrl, Dns01Challenge.class); + fail("Could bind to a different challenge type"); + } catch (AcmeProtocolException ex) { + assertThat(ex.getMessage(), is("Challenge type http-01 does not match" + + " requested class class org.shredzone.acme4j.challenge.Dns01Challenge")); + } } }