# HOTPVerify()

Verifies a counter-based One-Time Password (HOTP) against a secret and expected counter value.

Supports a window parameter to handle counter desync when users generate codes without submitting them.

**Requires Extension:** [Crypto Extension](https://download.lucee.org/#17AB52DE-B300-A94B-E058FC978BE4542D)

```
HOTPVerify( secret=string, code=string, counter=numeric, options=struct );
```

**Returns:** boolean

# Arguments

| Argument | Type | Required | Description | Default |
|----------|------|----------|-------------|---------|
| secret | string | Yes | Base32-encoded secret |  |
| code | string | Yes | The HOTP code to verify |  |
| counter | numeric | Yes | Expected counter value |  |
| options | struct | No | Optional struct: window (default 0 — exact match), digits (default 6), algorithm (SHA1\|SHA256\|SHA512, default SHA1) |  |

# Usage Notes

After a successful verification, always increment the server-side counter to prevent code reuse. The `window` parameter checks a range of counter values ahead of the expected counter to handle cases where the user generated codes without submitting them (counter desync).

# Examples

```cfml
// Verify an HOTP code against a secret and expected counter value
secret = TOTPSecret();
code = HOTPGenerate( secret, 5 );

// Verify at the exact counter
isValid = HOTPVerify( secret, code, 5 ); // true
isWrong = HOTPVerify( secret, code, 6 ); // false - wrong counter

// Use a window to handle counter desync (e.g. user requested a code but didn't submit it)
// window=5 checks counter values 3 through 8
isValid = HOTPVerify( secret, code, 3, { window: 5 } ); // true - counter 5 is within window

// In a real app, increment the server counter after each successful verification
// to prevent code reuse
```







# Categories

[Cryptography](../../categories/crypto.md)

# See Also

[HOTPGenerate()](hotpgenerate.md), [TOTPVerify()](totpverify.md)