hmac-otp Context Variables
Context variables for HMAC-based One-Time Password (HOTP and TOTP) authentication. These variables are populated by backends and used by hotp and totp authentication actions.
hmac-otp.secret
The shared secret used for generating one-time passwords. Required for both HOTP and TOTP authentication.
Type: String (hex or base32 encoded)
Set by: Backend mapping
Format: Determined by the secret_type parameter in the authentication action:
- Hexadecimal (default):
"0123456789ABCDEF" - Base32 (RFC 4648):
"JBSWY3DPEHPK3PXP" - Auto-detect: Automatically determines encoding
Example:
backends {
sqlite "USERS" {
query "FIND_USER" {
mapping {
hmac-otp.secret = totp_secret;
}
}
}
}
Security: The secret is the cryptographic key for OTP generation. It must be:
- Randomly generated (minimum 128 bits, preferably 160 bits for SHA1)
- Stored securely in the backend
- Never logged or transmitted in cleartext
- Unique per user
hmac-otp.counter
The current counter value for HOTP authentication. Required for HOTP, not used for TOTP.
Type: Integer (unsigned 64-bit)
Set by: Backend mapping (initial value), updated by system after successful authentication
Read after authentication: Contains the next counter value to persist
Example:
backends {
sqlite "USERS" {
query "FIND_USER" {
mapping {
hmac-otp.counter = hotp_counter;
}
}
query "UPDATE_HOTP_COUNTER" {
bindings {
hmac-otp.counter; # Updated counter after auth
user.username;
}
}
}
}
Important: Must be persisted after successful authentication to prevent replay attacks and enable subsequent logins.
hmac-otp.digits
The number of digits in the one-time password code.
Type: Integer (typically 6-8)
Default: 6
Set by: Backend mapping (optional)
Example:
mapping {
hmac-otp.digits = otp_digits; # 6, 7, or 8
}
Standards:
- RFC 4226 (HOTP) recommends 6 digits minimum
- RFC 6238 (TOTP) uses 6 digits by default
- 8 digits provides higher security but requires more storage/display
hmac-otp.timestep
The time window duration in seconds for TOTP authentication. Not used for HOTP.
Type: Integer (seconds)
Default: 30
Set by: Backend mapping (optional)
Example:
mapping {
hmac-otp.timestep = totp_timestep; # 30, 60, etc.
}
Common values:
- 30 seconds (RFC 6238 default, used by Google Authenticator, Microsoft Authenticator)
- 60 seconds (some corporate systems)
Operational impact: Shorter timesteps provide better security but require tighter clock synchronization.
hmac-otp.timestep.origin
The Unix timestamp origin for TOTP counter calculation (T0 in RFC 6238).
Type: Integer (Unix timestamp)
Default: 0 (January 1, 1970 00:00:00 UTC)
Set by: Backend mapping (optional, rarely changed)
Example:
mapping {
hmac-otp.timestep.origin = totp_origin;
}
Usage: Rarely modified. The default of 0 is compatible with all standard TOTP implementations. Custom origins are used only in specialized scenarios with non-standard TOTP implementations.
hmac-otp.timestep.last
The last successfully used timestep value for TOTP replay attack prevention.
Type: Integer (timestep counter)
Set by: Backend mapping (initial value), updated by system after successful authentication
Read after authentication: Contains the timestep value that was just used
Example:
# Load previous timestep
mapping {
hmac-otp.timestep.last = totp_last_timestep;
}
# In policy - prevent replay
authentication {
if any {
cache.last_timestep[aaa.identity] != none;
} then {
modify {
hmac-otp.timestep.last = cache.last_timestep[aaa.identity][0];
}
}
totp {
resync_window 1 0;
}
# Save current timestep
modify {
cache.last_timestep[aaa.identity] = hmac-otp.timestep.last;
}
}
# Or persist to database
query "UPDATE_TOTP_TIMESTEP" {
bindings {
hmac-otp.timestep.last;
user.username;
}
}
Replay protection: Tracking the last used timestep prevents an attacker from reusing a captured TOTP code within the same time window.
Context Variable Lifecycle
HOTP Flow
- Backend populates
hmac-otp.secretandhmac-otp.counter - Authentication validates code against current counter and lookahead window
- On success,
hmac-otp.counteris incremented - Updated counter must be persisted to backend in
post-authentication
TOTP Flow
- Backend populates
hmac-otp.secret(and optionallyhmac-otp.timestep,hmac-otp.timestep.last) - Authentication validates code against current time window and resync windows
- On success,
hmac-otp.timestep.lastis updated to current timestep - Optionally persist timestep to backend or cache for replay protection
Security Considerations
Secret Management
- Generate secrets with cryptographic random number generators
- Minimum 128-bit entropy (160 bits recommended for SHA1)
- Store encrypted in backend if possible
- Rotate secrets periodically (requires user re-enrollment)
Counter/Timestep Protection
- HOTP: Always persist counter after successful authentication
- TOTP: Persist or cache last timestep to prevent replay within same window
- Use database transactions to ensure atomicity
Resync Windows
- HOTP: Larger windows (10-20) tolerate missed button presses but increase attack surface
- TOTP: Larger windows (2-3) tolerate clock drift but allow longer replay windows
- Balance security and usability based on deployment requirements