passwordConfirmationSessionKey(), 0); return $at > 0 && (time() - $at) < $this->confirmationWindow(); } /** * Which guard's record this component confirms against. * * Overridden to 'operator' by the console components. A default of 'web' * keeps the portal working unchanged — and an override is explicit, where * sniffing the request would be one more thing to get wrong on a page that * gates access to credentials. */ protected function confirmationGuard(): string { return 'web'; } public function confirmPassword(): void { $account = auth()->guard($this->confirmationGuard())->user(); $key = 'confirm-password:'.$this->confirmationGuard().'|'.$account?->getAuthIdentifier().'|'.request()->ip(); if (RateLimiter::tooManyAttempts($key, 5)) { $this->addError('confirmablePassword', __('auth.throttle', [ 'seconds' => RateLimiter::availableIn($key), ])); return; } if ($account === null || ! Hash::check($this->confirmablePassword, $account->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([$this->passwordConfirmationSessionKey() => time()]); } /** Give up the confirmation early — leaving a page should not keep it open. */ public function forgetPasswordConfirmation(): void { session()->forget($this->passwordConfirmationSessionKey()); } /** * The one place this marker's session key is computed. * * passwordRecentlyConfirmed(), confirmPassword() and * forgetPasswordConfirmation() all go through this rather than each * building the string themselves, so they cannot drift apart from one * another — which is exactly how the guard-agnostic key this replaces * came to be read by one guard and written by another. */ private function passwordConfirmationSessionKey(): string { $guard = $this->confirmationGuard(); $identity = auth()->guard($guard)->user()?->getAuthIdentifier() ?? 'guest'; return "auth.password_confirmed_at.{$guard}.{$identity}"; } /** * 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); } }