mpociot/reauthenticate
Laravel package for reauthentication: middleware and traits that require users to re-enter their password before sensitive actions such as changing an email or deleting an account, with a built-in confirmation view and configurable timeout.
Architecture fit. The package is a textbook Laravel HTTP-kernel citizen: one middleware, a service provider, a config file, and a published Blade view. It works by setting a single session key on successful password confirmation and comparing that key against a timeout on each request. That session key is the entire contract — everything downstream (redirect-back, timeout semantics, guard resolution) hangs off it. Architecturally it is a clean fit for a server-rendered Blade monolith with session auth, and a poor fit for anything else: the failure path is an HTML redirect, so Inertia, Livewire, and XHR clients will follow it into a page they cannot render. It also assumes exactly one guard and one password field, which excludes API-token auth, multi-guard tenant apps, and any SSO/passkey population.
Integration feasibility. Installing is trivial; sustaining the integration is the question. The last release (2019-10-08) added Laravel 6 support and nothing since. On Laravel 7+ you should expect dependency-resolution friction and unvalidated runtime behavior; on PHP 8.1+ expect deprecations and possible null-to-non-nullable type errors, since Laravel 6 only ever exercised PHP up to 8.0. Feasibility therefore collapses to a single gate: which framework version are we on? On 6.2+ the honest answer is that native Illuminate\Auth\Middleware\RequirePassword plus the password.confirmation route delivers the same UX with zero third-party surface, and this package's only defensible role is as an MIT-licensed reference implementation to read and copy.
Technical risk. The dominant risk is not code quality, it is ownership: password-handling logic with no maintainer, no CI matrix, no disclosure process, and zero listed dependents (i.e., no crowd-sourced maintenance and no ecosystem signal). Secondary risks are concrete and testable:
reauthenticate route name and publishes a Blade view; auth-scaffolding upgrades can shadow either without error.Key questions for the decision meeting.
Stack fit and the primary recommendation. If the estate is Laravel 6.2+, do not adopt this as a dependency — use native password.confirm with Breeze/Fortify/laravel/ui scaffolding, and treat the package as a design reference (a few hundred readable lines). If the estate is genuinely pinned to Laravel 5.x with an upgrade out of scope this quarter, adopt it only under a fork-and-own plan: vendor the middleware into app/Http/Middleware/, delete the Composer entry, and carry the tests yourself. Carrying an unowned dependency on password code is a net-negative for security review regardless of how small the code is.
Compatibility work before any route changes. Pin the exact version explicitly. Read the middleware line by line to pin down three undocumented facts: the timeout unit (minutes vs. seconds), the comparison operator at the boundary, and the exact session key written. Run php artisan route:list | grep -i reauth after install and after every auth-scaffolding upgrade, and verify what actually landed in config/reauthenticate.php. Run the full flow on the real production runtime — do not infer PHP compatibility from composer.json constraints.
Sequencing. The order matters more than the code:
travel(timeout) prompts again and timeout - 1 passes; each guard tested separately. These are both your safety net and your exit suite.'sudo' => \App\Http\Middleware\Reauthenticate::class) and never reference the vendor alias in routes/web.php. This makes the migration to password.confirm, or to a fork, a one-line change in Kernel.php.sudo and password.confirm on the same group produces two session keys and a loop users cannot exit.Effort envelope. Legacy-path integration with tests, JSON handling, and audit logging is roughly 3–5 engineer-days; the native path is closer to one sprint day plus existing scaffolding. The sensitive-action registry and window policy is product work measured in hours, not days — and it is worth producing whether or not this code ships.
Maintenance. This is the deciding cost. Upstream is dormant, has no CI matrix, no security disclosure path, and zero dependents to absorb a fix. The fork burden itself is small (the code is short and MIT), but the attention burden is not: someone must own review when PHP or Laravel moves, and that ownership must be named before install, not after. An unowned dependency gating sensitive operations is a finding in a security review, not an inconvenience.
Support. There is no vendor and no upstream escalation route. Internal support depends on the team's own tests and on captured knowledge — the undocumented timeout unit and comparison operator must be recorded as a comment at the fork point and pinned by tests, or the next engineer will re-derive it from behavior. Onboarding is genuinely cheap: an afternoon of reading plus the feature suite.
Scaling. No datastore, no network hop, no measurable cost. The one scaling hazard is session topology: with file sessions behind a load balancer that does not pin, a user confirmed on node A can be rejected by node B, presenting as an inexplicable re-auth prompt immediately after a successful one. Redis/DB sessions make this a non-issue — verify before rollout and document the dependency.
Failure modes and mitigations.
| Failure | User/system impact | Mitigation |
|---|---|---|
| Fail-open (bad route group, unresolvable guard) | Silent bypass of a security control | Assertion test that a protected route rejects an unconfirmed user; wrapper throws rather than skipping |
| Wrong-guard password comparison | Always-fails (visible) or cross-user hash check (incident) | Per-guard tests with the same password form |
| SSO/magic-link/passkey user hits the form | Dead end, support ticket | Check $user->password; skip with a compensating challenge or a clear escalation path |
| Open redirect via intended URL | Phishing vector | Relative-path or allowlisted-host validation; test ?redirect=https://evil.example and //evil.example |
Coexistence with password.confirm |
Infinite prompt loop | Migrate group-by-group; never overlap |
| Route name / view shadowing | Silent, hard-to-trace behavior change | route:list check after every scaffolding upgrade |
| PHP 8.1+ deprecations | Noisy logs, possible type errors | Full-flow test on the actual runtime before commitment |
The general principle: the failure mode to design against is the silent pass, because it is the one that turns a maintenance annoyance into a security event.
Ramp-up and product framing. Engineering ramp-up is low; the real ramp is product-side — defining "sensitive action" as a reviewable concept, choosing a re-auth window and mapping it to action risk, and naming what this control is not (MFA, WebAuthn, per-action authorization, risk-based step-up, audit log, passwordless support). Its near-term commercial value is disproportionate to its effort: it gives a demonstrable, screenshottable control that closes a line item on security questionnaires and enterprise deals in a sprint rather than a security epic — provided no one oversells it internally as "we shipped step-up authentication."
How can I help you explore Laravel packages today?