user(); assert($user !== null); return Inertia::render('auth/confirm-password', [ // An account provisioned by a provider has no password to // confirm with — its stored hash is a generated string nobody // has seen. The screen offers to set one instead of asking for // it, which is the only way past this for those accounts, and // this screen stands in front of two-factor enrolment. // // Social, not "anything but Local": a directory account has a // password -- the directory's -- and store() accepts it. Asking // whether the account was Local told those accounts to set one // here instead, which /settings/password refuses them, and left // them no way past this screen at all. 'has_password' => $user->auth_source !== AuthSource::Social, ]); } /** * Confirm the user's password. * * Through PasswordVerification, so this asks the same question the * sign-in form asks: is this the account's password, from wherever * that account's password lives. Checking only the local hash refused * every directory-provisioned account the password it actually has -- * their local hash is a Str::password(64) nobody has ever seen -- and * this screen stands in front of enrolling in two-factor, so those * accounts could not enrol at all. * * Asked for JSON, it answers with a bare 204: that is the password * dialog (RequirePasswordConfirmation), which stays on the page and * sends the refused request again itself, so there is nowhere to go. */ public function store(Request $request, PasswordVerification $passwords): RedirectResponse|HttpResponse { $user = $request->user(); assert($user !== null); if (! $passwords->verify($user, (string) $request->string('password'))) { throw ValidationException::withMessages([ 'password' => __('auth.password'), ]); } $request->session()->put('auth.password_confirmed_at', time()); if ($request->expectsJson()) { return response()->noContent(); } return redirect()->intended(route('dashboard', absolute: false)); } }