Use java.time classes for stored verification code expiration; add tests.
This commit is contained in:
		
							parent
							
								
									ce3fb7fa99
								
							
						
					
					
						commit
						111f5ba024
					
				| 
						 | 
					@ -8,12 +8,14 @@ package org.whispersystems.textsecuregcm.auth;
 | 
				
			||||||
import com.fasterxml.jackson.annotation.JsonCreator;
 | 
					import com.fasterxml.jackson.annotation.JsonCreator;
 | 
				
			||||||
import com.fasterxml.jackson.annotation.JsonProperty;
 | 
					import com.fasterxml.jackson.annotation.JsonProperty;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.google.common.annotations.VisibleForTesting;
 | 
				
			||||||
import org.whispersystems.textsecuregcm.util.Util;
 | 
					import org.whispersystems.textsecuregcm.util.Util;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import javax.annotation.Nullable;
 | 
					import javax.annotation.Nullable;
 | 
				
			||||||
import java.security.MessageDigest;
 | 
					import java.security.MessageDigest;
 | 
				
			||||||
 | 
					import java.time.Duration;
 | 
				
			||||||
 | 
					import java.time.Instant;
 | 
				
			||||||
import java.util.Optional;
 | 
					import java.util.Optional;
 | 
				
			||||||
import java.util.concurrent.TimeUnit;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class StoredVerificationCode {
 | 
					public class StoredVerificationCode {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,6 +32,8 @@ public class StoredVerificationCode {
 | 
				
			||||||
  @Nullable
 | 
					  @Nullable
 | 
				
			||||||
  private final String twilioVerificationSid;
 | 
					  private final String twilioVerificationSid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public static final Duration EXPIRATION = Duration.ofMinutes(10);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @JsonCreator
 | 
					  @JsonCreator
 | 
				
			||||||
  public StoredVerificationCode(
 | 
					  public StoredVerificationCode(
 | 
				
			||||||
      @JsonProperty("code") final String code,
 | 
					      @JsonProperty("code") final String code,
 | 
				
			||||||
| 
						 | 
					@ -60,7 +64,12 @@ public class StoredVerificationCode {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  public boolean isValid(String theirCodeString) {
 | 
					  public boolean isValid(String theirCodeString) {
 | 
				
			||||||
    if (timestamp + TimeUnit.MINUTES.toMillis(10) < System.currentTimeMillis()) {
 | 
					    return isValid(theirCodeString, Instant.now());
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @VisibleForTesting
 | 
				
			||||||
 | 
					  boolean isValid(String theirCodeString, Instant currentTime) {
 | 
				
			||||||
 | 
					    if (Instant.ofEpochMilli(timestamp).plus(EXPIRATION).isBefore(currentTime)) {
 | 
				
			||||||
      return false;
 | 
					      return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,37 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright 2013-2021 Signal Messenger, LLC
 | 
				
			||||||
 | 
					 * SPDX-License-Identifier: AGPL-3.0-only
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package org.whispersystems.textsecuregcm.auth;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.junit.jupiter.api.Test;
 | 
				
			||||||
 | 
					import org.junit.jupiter.params.ParameterizedTest;
 | 
				
			||||||
 | 
					import org.junit.jupiter.params.provider.Arguments;
 | 
				
			||||||
 | 
					import org.junit.jupiter.params.provider.MethodSource;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.time.Duration;
 | 
				
			||||||
 | 
					import java.time.Instant;
 | 
				
			||||||
 | 
					import java.util.stream.Stream;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import static org.junit.jupiter.api.Assertions.*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class StoredVerificationCodeTest {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @ParameterizedTest
 | 
				
			||||||
 | 
					  @MethodSource
 | 
				
			||||||
 | 
					  void isValid(final StoredVerificationCode storedVerificationCode, final String code, final Instant currentTime, final boolean expectValid) {
 | 
				
			||||||
 | 
					    assertEquals(expectValid, storedVerificationCode.isValid(code, currentTime));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private static Stream<Arguments> isValid() {
 | 
				
			||||||
 | 
					    final Instant now = Instant.now();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return Stream.of(
 | 
				
			||||||
 | 
					        Arguments.of(new StoredVerificationCode("code", now.toEpochMilli(), null, null), "code", now, true),
 | 
				
			||||||
 | 
					        Arguments.of(new StoredVerificationCode("code", now.toEpochMilli(), null, null), "incorrect", now, false),
 | 
				
			||||||
 | 
					        Arguments.of(new StoredVerificationCode("code", now.toEpochMilli(), null, null), "code", now.plus(Duration.ofHours(1)), false),
 | 
				
			||||||
 | 
					        Arguments.of(new StoredVerificationCode("", now.toEpochMilli(), null, null), "", now, false)
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
		Reference in New Issue