diff --git a/extensions/guacamole-auth-totp/src/main/java/org/apache/guacamole/auth/totp/UserVerificationService.java b/extensions/guacamole-auth-totp/src/main/java/org/apache/guacamole/auth/totp/UserVerificationService.java index cb737307f..823c5ef29 100644 --- a/extensions/guacamole-auth-totp/src/main/java/org/apache/guacamole/auth/totp/UserVerificationService.java +++ b/extensions/guacamole-auth-totp/src/main/java/org/apache/guacamole/auth/totp/UserVerificationService.java @@ -142,7 +142,7 @@ public class UserVerificationService { // Verify provided TOTP against value produced by generator byte[] key = BASE32.decode(encodedKey); TOTPGenerator totp = new TOTPGenerator(key, TOTPGenerator.Mode.SHA1, 6); - if (code.equals(totp.generate())) + if (code.equals(totp.generate()) || code.equals(totp.previous())) return; } diff --git a/extensions/guacamole-auth-totp/src/main/java/org/apache/guacamole/totp/TOTPGenerator.java b/extensions/guacamole-auth-totp/src/main/java/org/apache/guacamole/totp/TOTPGenerator.java index 004c23ba2..b8c0d9561 100644 --- a/extensions/guacamole-auth-totp/src/main/java/org/apache/guacamole/totp/TOTPGenerator.java +++ b/extensions/guacamole-auth-totp/src/main/java/org/apache/guacamole/totp/TOTPGenerator.java @@ -399,4 +399,33 @@ public class TOTPGenerator { return generate(System.currentTimeMillis() / 1000); } + /** + * Returns the TOTP code which would have been generated immediately prior + * to the code returned by invoking generate() with the given timestamp. + * + * @param time + * The absolute timestamp to use to generate the TOTP code, in seconds + * since midnight, 1970-01-01, UTC (UNIX epoch). + * + * @return + * The TOTP code which would have been generated immediately prior to + * the the code returned by invoking generate() with the given + * timestamp. + */ + public String previous(long time) { + return generate(Math.max(startTime, time - timeStep)); + } + + /** + * Returns the TOTP code which would have been generated immediately prior + * to the code currently being returned by generate(). + * + * @return + * The TOTP code which would have been generated immediately prior to + * the code currently being returned by generate(). + */ + public String previous() { + return previous(System.currentTimeMillis() / 1000); + } + }