Class InMemoryReplayGuard

java.lang.Object
io.github.pratiyush.totp.InMemoryReplayGuard
All Implemented Interfaces:
ReplayGuard, AutoCloseable

public final class InMemoryReplayGuard extends Object implements ReplayGuard, AutoCloseable
Thread-safe in-memory implementation of ReplayGuard.

This implementation stores used codes in a ConcurrentHashMap with automatic expiration. Suitable for single-instance deployments.

Features

  • Thread-safe concurrent access
  • Automatic time-based expiration
  • Configurable retention period
  • Background cleanup thread

Limitations

  • Not suitable for clustered deployments (use Redis-backed implementation)
  • Data lost on JVM restart

Usage Example


 // Create with 2-minute retention (covers 30s period + drift)
 ReplayGuard guard = new InMemoryReplayGuard(Duration.ofMinutes(2));
 
 // Use with TOTP verification
 TOTP totp = TOTP.builder().replayGuard(guard).build();
 
See Also:
  • Constructor Details

    • InMemoryReplayGuard

      public InMemoryReplayGuard(Duration retention)
      Creates a new in-memory replay guard with the specified retention period.

      The retention period should be at least: period * (1 + 2 * drift) to ensure codes remain tracked for their entire validity window.

      Parameters:
      retention - how long to track used codes
      Throws:
      NullPointerException - if retention is null
      IllegalArgumentException - if retention is negative or zero
  • Method Details

    • withDefaultRetention

      public static InMemoryReplayGuard withDefaultRetention()
      Creates a replay guard with default retention of 2 minutes.

      This default covers the standard 30-second period with drift of 1, plus additional margin for clock skew.

      Returns:
      new replay guard with default settings
    • forConfig

      public static InMemoryReplayGuard forConfig(TOTPConfig config)
      Creates a replay guard configured for a specific TOTP configuration.
      Parameters:
      config - the TOTP configuration
      Returns:
      new replay guard with appropriate retention
    • markUsed

      public boolean markUsed(String key)
      Description copied from interface: ReplayGuard
      Attempts to mark a code as used.

      This method should be called after successful TOTP verification. Returns true only if the code was not previously used.

      Specified by:
      markUsed in interface ReplayGuard
      Parameters:
      key - unique key combining user identifier and code
      Returns:
      true if the code was successfully marked as used (first use), false if the code was already used
    • wasUsed

      public boolean wasUsed(String key)
      Description copied from interface: ReplayGuard
      Checks if a code has been used without marking it.
      Specified by:
      wasUsed in interface ReplayGuard
      Parameters:
      key - the key to check
      Returns:
      true if the code was previously used
    • clear

      public void clear()
      Description copied from interface: ReplayGuard
      Clears all tracked codes.

      Use with caution - this resets replay protection.

      Specified by:
      clear in interface ReplayGuard
    • size

      public int size()
      Description copied from interface: ReplayGuard
      Returns the number of codes currently tracked.
      Specified by:
      size in interface ReplayGuard
      Returns:
      count of tracked codes
    • getRetention

      public Duration getRetention()
      Returns the configured retention period.
      Returns:
      the retention duration
    • close

      public void close()
      Shuts down the background cleanup thread.
      Specified by:
      close in interface AutoCloseable