Skip to content

Commit b729e55

Browse files
committed
fix: normalize recovery code server-side before hash check
Hash::check() compared the raw submitted code against the dash-less uppercase hash, so the "strip separators + uppercase" contract was only enforced by the login.js client. Any other consumer submitting a code exactly as displayed (XXXX-XXXX) would fail verification on this lockout-critical path. Apply the same normalization in AbstractMFAChallengeStrategy::verifyRecoveryCode() before Hash::check.
1 parent 7fbff84 commit b729e55

1 file changed

Lines changed: 5 additions & 0 deletions

File tree

app/Strategies/MFA/AbstractMFAChallengeStrategy.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,11 @@ public function clearPendingState(): void
4848

4949
public function verifyRecoveryCode(User $user, string $code): void
5050
{
51+
// Recovery codes are hashed without the "-" separator; it is added only
52+
// for on-screen readability (XXXX-XXXX). Normalize here so a code typed
53+
// or pasted exactly as displayed still matches the stored hash.
54+
$code = strtoupper(preg_replace('/[^A-Za-z0-9]/', '', $code));
55+
5156
foreach ($this->recovery_code_repository->getUnusedByUser($user) as $recoveryCode) {
5257
if (Hash::check($code, $recoveryCode->getCodeHash())) {
5358
// Concurrency: acquire a PESSIMISTIC_WRITE row lock and re-hydrate

0 commit comments

Comments
 (0)