Tiger_Model_AuthChallenge

@api · extends Tiger_Model_Table

AuthChallenge — transient, single-use auth proofs (OTP codes, reset/verify/magic tokens). See migration 0005 for the security rationale.

The PK is a v4 UUID (opaque) — challenge ids can appear in URLs, so they must not leak timing. Codes are stored HASHED and compared with hash_equals(); reuse, expiry, and brute-force are all enforced here so callers can't forget them.

Methods

issue()

issue($userId, $type, $plainCode, $ttlSeconds = 600)

Issue a challenge: store the HASH of the code and a TTL. The plaintext code is the caller's to deliver (SMS/email) and is never persisted.

  • $userId string|null — may be null in pre-login flows
  • $type string — sms_otp | email_verify | password_reset | magic_link
  • $plainCode string — the code/token delivered out-of-band
  • $ttlSeconds int — lifetime (default 10 min)

Returns string — challenge_id

redeem()

redeem($challengeId, $plainCode)

Verify and CONSUME a challenge (single-use). Returns the challenge row on success, or null on any failure (missing / already used / expired / locked / wrong code). A wrong code increments the attempt counter.

  • $challengeId string — the challenge id (v4 UUID)
  • $plainCode string — the code/token to verify

Returns Zend_Db_Table_Row_Abstract|null — the consumed challenge row, or null on failure

latestActive()

latestActive($userId, $type)

The newest still-usable challenge for a user+type (not consumed, not expired, not attempt-locked), or null. Used to verify a code by email (no id in the URL).

  • $userId string — the user id
  • $type string — the challenge type

Returns Zend_Db_Table_Row_Abstract|null — the newest usable challenge, or null

invalidateActive()

invalidateActive($userId, $type)

Invalidate (consume) a user's outstanding challenges of a type — call before issuing a fresh one so only the newest code is ever valid, which also keeps latestActive() unambiguous.

  • $userId string — the user id
  • $type string — the challenge type

Returns int — rows invalidated

countRecent()

countRecent($userId, $type, $seconds)

Count how many challenges of a type a user got in the last $seconds (send-rate guard).

  • $userId string — the user id
  • $type string — the challenge type
  • $seconds int — the look-back window in seconds

Returns int — the count of matching challenges

purgeExpired()

purgeExpired()

Delete expired/consumed challenges. Call periodically (cron / bin/tiger). Hard delete — dead challenges have no audit value.

Returns int — rows removed