0 && (time() - $at) < $this->confirmationWindow(); } public function confirmPassword(): void { $key = 'confirm-password:'.auth()->id().'|'.request()->ip(); if (RateLimiter::tooManyAttempts($key, 5)) { $this->addError('confirmablePassword', __('auth.throttle', [ 'seconds' => RateLimiter::availableIn($key), ])); return; } if (! Hash::check($this->confirmablePassword, auth()->user()->password)) { RateLimiter::hit($key, 60); $this->addError('confirmablePassword', __('admin_settings.password_wrong')); $this->reset('confirmablePassword'); return; } RateLimiter::clear($key); $this->reset('confirmablePassword'); // Regenerated first: a confirmation raises what this session can do, and // a session id that was already known to someone else must not be the // one that gets the extra authority. session()->regenerate(); session(['auth.password_confirmed_at' => time()]); } /** Give up the confirmation early — leaving a page should not keep it open. */ public function forgetPasswordConfirmation(): void { session()->forget('auth.password_confirmed_at'); } /** * A value shown only in outline: the last four characters, and nothing else. * * Enough to tell two keys apart, useless to anyone reading over a shoulder * or scrolling back through a screen recording. */ protected function outline(?string $value, int $keep = 4): ?string { if ($value === null || $value === '') { return null; } return Str::length($value) <= $keep ? str_repeat('•', Str::length($value)) : str_repeat('•', 8).Str::substr($value, -$keep); } }