validateCode method

Future<bool> validateCode(
  1. String inputCode
)

Validates TOTP code with ±1 time window (90-second tolerance).

Implementation

Future<bool> validateCode(String inputCode) async {
  final secret = (await _resolveSecret())?.toUpperCase();

  if (secret == null || secret.isEmpty) {
    log('No TOTP secret found.');
    return false;
  }

  final cleanCode = inputCode.trim();
  if (cleanCode.length != _digits || !RegExp(r'^\d+$').hasMatch(cleanCode)) {
    log('Invalid code format: $cleanCode');
    return false;
  }

  // Use milliseconds since epoch (most otp packages expect ms)
  final nowMs = DateTime.now().millisecondsSinceEpoch;

  // check -1, 0, +1 windows
  for (int offset = -1; offset <= 1; offset++) {
    final testTimeMs = nowMs + (offset * _period * 1000);
    final expected = OTP.generateTOTPCodeString(
      secret,
      testTimeMs, // milliseconds
      interval: _period,
      length: _digits,
      algorithm: Algorithm.SHA1,
      isGoogle: true,
    );

    log('offset=$offset, testTimeMs=$testTimeMs, expected=$expected');
    if (_constantTimeEquals(expected, cleanCode)) {
      log('TOTP valid (offset $offset)');
      return true;
    }
  }

  log('TOTP code invalid. Current nowMs=$nowMs, entered=$cleanCode');
  return false;
}