From 111f5ba0242d6138686a4fcd6abf45dba8074794 Mon Sep 17 00:00:00 2001 From: Jon Chambers Date: Fri, 18 Jun 2021 11:50:28 -0400 Subject: [PATCH] Use java.time classes for stored verification code expiration; add tests. --- .../auth/StoredVerificationCode.java | 13 ++++++- .../auth/StoredVerificationCodeTest.java | 37 +++++++++++++++++++ 2 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 service/src/test/java/org/whispersystems/textsecuregcm/auth/StoredVerificationCodeTest.java diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/auth/StoredVerificationCode.java b/service/src/main/java/org/whispersystems/textsecuregcm/auth/StoredVerificationCode.java index 1f7f043cc..40db52c7f 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/auth/StoredVerificationCode.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/auth/StoredVerificationCode.java @@ -8,12 +8,14 @@ package org.whispersystems.textsecuregcm.auth; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; +import com.google.common.annotations.VisibleForTesting; import org.whispersystems.textsecuregcm.util.Util; import javax.annotation.Nullable; import java.security.MessageDigest; +import java.time.Duration; +import java.time.Instant; import java.util.Optional; -import java.util.concurrent.TimeUnit; public class StoredVerificationCode { @@ -30,6 +32,8 @@ public class StoredVerificationCode { @Nullable private final String twilioVerificationSid; + public static final Duration EXPIRATION = Duration.ofMinutes(10); + @JsonCreator public StoredVerificationCode( @JsonProperty("code") final String code, @@ -60,7 +64,12 @@ public class StoredVerificationCode { } 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; } diff --git a/service/src/test/java/org/whispersystems/textsecuregcm/auth/StoredVerificationCodeTest.java b/service/src/test/java/org/whispersystems/textsecuregcm/auth/StoredVerificationCodeTest.java new file mode 100644 index 000000000..4403ec292 --- /dev/null +++ b/service/src/test/java/org/whispersystems/textsecuregcm/auth/StoredVerificationCodeTest.java @@ -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 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) + ); + } +}