user(); if ($user === null || $user->hasTwoFactorEnabled()) { return $next($request); } $value = $this->settings->get(Setting::TwoFactorEnforcement); $enforcement = (is_string($value) ? TwoFactorEnforcement::tryFrom($value) : null) ?? TwoFactorEnforcement::None; if (! $enforcement->appliesTo($user->type)) { return $next($request); } // password.confirm* is on this list because the two-factor mutation // routes now require it: without the exemption, enrolling would // redirect to the confirm-password screen, which this middleware // would redirect straight back to two-factor.show — a loop that // locks the user out of the only exit. // // The pattern covers both halves of that screen. Naming only the // GET left the form rendering and its submission redirected away, // so the password was never confirmed and the loop stayed shut // one step further along than before. // password.edit/update is on it for the same shape of reason, one // step further out: an account provisioned by a provider has no // password to confirm with, so the confirm screen sends it to set // one — and without this, that screen was redirected back here // too. The loop then had no exit at all, which is how an // installation that made two-factor compulsory locked out // everybody who signs in with Microsoft. if ($request->routeIs('two-factor.*', 'password.confirm*', 'password.edit', 'password.update', 'logout', 'locale.update')) { return $next($request); } return WriteSafeRedirect::apply($request, redirect()->route('two-factor.show')->with('two_factor_enforced_notice', true)); } }