diff --git a/core/src/main/java/google/registry/flows/domain/token/AllocationTokenFlowUtils.java b/core/src/main/java/google/registry/flows/domain/token/AllocationTokenFlowUtils.java index 7f7831f7f..2b687e3a0 100644 --- a/core/src/main/java/google/registry/flows/domain/token/AllocationTokenFlowUtils.java +++ b/core/src/main/java/google/registry/flows/domain/token/AllocationTokenFlowUtils.java @@ -17,6 +17,7 @@ package google.registry.flows.domain.token; import static com.google.common.base.Preconditions.checkArgument; import static google.registry.model.ofy.ObjectifyService.ofy; +import com.google.common.base.Strings; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; @@ -24,7 +25,7 @@ import com.google.common.net.InternetDomainName; import com.googlecode.objectify.Key; import google.registry.flows.EppException; import google.registry.flows.EppException.AssociationProhibitsOperationException; -import google.registry.flows.EppException.ParameterValueSyntaxErrorException; +import google.registry.flows.EppException.AuthorizationErrorException; import google.registry.flows.EppException.StatusProhibitsOperationException; import google.registry.model.domain.DomainCommand; import google.registry.model.domain.token.AllocationToken; @@ -137,6 +138,12 @@ public class AllocationTokenFlowUtils { /** Loads a given token and validates that it is not redeemed */ private AllocationToken loadToken(String token) throws EppException { + if (Strings.isNullOrEmpty(token)) { + // We load the token directly from the input XML. If it's null or empty we should throw + // an InvalidAllocationTokenException before the Datastore load attempt fails. + // See https://tools.ietf.org/html/draft-ietf-regext-allocation-token-04#section-2.1 + throw new InvalidAllocationTokenException(); + } AllocationToken tokenEntity = ofy().load().key(Key.create(AllocationToken.class, token)).now(); if (tokenEntity == null) { throw new InvalidAllocationTokenException(); @@ -181,7 +188,7 @@ public class AllocationTokenFlowUtils { } /** The allocation token is invalid. */ - public static class InvalidAllocationTokenException extends ParameterValueSyntaxErrorException { + public static class InvalidAllocationTokenException extends AuthorizationErrorException { public InvalidAllocationTokenException() { super("The allocation token is invalid"); } diff --git a/core/src/test/java/google/registry/flows/domain/token/AllocationTokenFlowUtilsTest.java b/core/src/test/java/google/registry/flows/domain/token/AllocationTokenFlowUtilsTest.java index da51518e4..b636e4d7a 100644 --- a/core/src/test/java/google/registry/flows/domain/token/AllocationTokenFlowUtilsTest.java +++ b/core/src/test/java/google/registry/flows/domain/token/AllocationTokenFlowUtilsTest.java @@ -90,6 +90,22 @@ public class AllocationTokenFlowUtilsTest extends ShardableTestCase { assertValidateThrowsEppException(InvalidAllocationTokenException.class); } + @Test + public void test_validateToken_failsOnNullToken() { + assertAboutEppExceptions() + .that( + assertThrows( + InvalidAllocationTokenException.class, + () -> + flowUtils.loadTokenAndValidateDomainCreate( + createCommand("blah.tld"), + null, + Registry.get("tld"), + "TheRegistrar", + DateTime.now(UTC)))) + .marshalsToXml(); + } + @Test public void test_validateToken_callsCustomLogic() { AllocationTokenFlowUtils failingFlowUtils = diff --git a/docs/flows.md b/docs/flows.md index 02b680492..287646778 100644 --- a/docs/flows.md +++ b/docs/flows.md @@ -324,7 +324,6 @@ An EPP flow that creates a new domain resource. * The checksum in the specified TCNID does not validate. * Domain name is under tld which doesn't exist. * 2005 - * The allocation token is invalid. * Domain name must have exactly one part above the TLD. * Domain name must not equal an existing multi-part TLD. * The requested fee is expressed in a scale that is invalid for the given @@ -337,6 +336,7 @@ An EPP flow that creates a new domain resource. * 2103 * Specified extension is not implemented. * 2201 + * The allocation token is invalid. * Only a tool can pass a metadata extension. * Registrar is not authorized to access this TLD. * Registrar must be active in order to perform this operation.