Used cookbook Tutorial for Customer Login in frontend. Works Fine!
Now i activated 2fa via Mail in config, works for Login via Panel. But not on frontend, Herr the Mail with Code Vers Not delivered…
Do you have a hint?
<?php
return function ($kirby) {
// don't show the login screen to already logged in users
if ($kirby->user()) {
go('/panel');
}
$error = false;
$step = 'login';
$email = get('email');
$session = $kirby->session();
// Step 1: Handle login form
if ($kirby->request()->is('POST') && get('login')) {
// try to log the user in with the provided credentials
try {
$user = $kirby->user($email);
if (!$user) throw new Exception('User not found');
// Validate password only, do not log in
if (method_exists($user, 'validatePassword')) {
$valid = $user->validatePassword(get('password'));
} else {
// Fallback for older Kirby: check hash manually
$valid = password_verify(get('password'), $user->password());
}
if ($valid) {
// Use Kirby's official 2FA
$user->send2faCode();
$session->set('2fa.email', $email);
$session->set('2fa.password', get('password'));
$step = '2fa';
} else {
$error = 'Falsches Passwort.';
}
} catch (Exception $e) {
$error = $e->getMessage();
}
}
// Step 2: Handle 2FA code form
if ($kirby->request()->is('POST') && get('verify')) {
$email = $session->get('2fa.email');
$password = $session->get('2fa.password');
$user = $kirby->user($email);
if ($user && $password) {
try {
if ($user->verify2faCode(get('code'))) {
$kirby->auth()->login($email, $password);
$session->remove('2fa.email');
$session->remove('2fa.password');
go('/panel');
} else {
$error = 'Der Code ist ungültig oder abgelaufen.';
$step = '2fa';
}
} catch (Exception $e) {
$error = $e->getMessage();
$step = '2fa';
}
} else {
$error = 'Unbekannter Benutzer.';
$step = 'login';
}
}
// Resend code logic
if (get('resend') && $session->get('2fa.email')) {
$email = $session->get('2fa.email');
$user = $kirby->user($email);
if ($user) {
try {
$user->send2faCode();
$step = '2fa';
} catch (Exception $e) {
$error = $e->getMessage();
}
}
}
return [
'error' => $error,
'step' => $step,
'email' => $email
];
};
<?php
return function ($kirby) {
// don't show the login screen to already logged in users
if ($kirby->user()) {
go('/panel');
}
$error = false;
$step = 'login';
$email_param = get('email'); // Renamed to avoid conflict with $email variable later
$session = $kirby->session();
// Step 1: Handle login form
if ($kirby->request()->is('POST') && get('login')) {
$email = $email_param; // Use the email from the form
$password = get('password');
try {
// Attempt to log in. If 2FA is required, this will throw an AuthException.
$kirby->auth()->login($email, $password);
// If login is successful without 2FA (should not happen with current config but good practice)
$session->remove('2fa.email'); // Clean up session just in case
go('/panel');
} catch (Kirby\Exception\AuthException $e) {
if ($e->isChallenge()) {
// 2FA is required. Kirby's Auth system should have sent the code.
$session->set('2fa.email', $email); // Store email for the next step
$step = '2fa';
} elseif ($e->getType() === 'user') {
$error = 'Benutzer nicht gefunden (AuthException).';
} elseif ($e->getType() === 'password') {
$error = 'Falsches Passwort (AuthException).';
} else {
// Other AuthException types, not a challenge
$error = 'Authentifizierungsfehler: Typ ' . $e->getType() . ' - ' . $e->getMessage();
}
} catch (Exception $e) {
// Other unexpected errors (NOT AuthException)
$error = 'Allgemeiner Fehler: ' . $e->getMessage() . ' (Typ: ' . get_class($e) . ')';
}
}
// Step 2: Handle 2FA code form
if ($kirby->request()->is('POST') && get('verify')) {
$email_from_session = $session->get('2fa.email');
$code = get('code');
if ($email_from_session && $code) {
try {
// Attempt to log in using the email from session and the 2FA code. Password is null.
$kirby->auth()->login($email_from_session, null, $code);
// Login successful
$session->remove('2fa.email');
go('/panel');
} catch (Kirby\Exception\AuthException $e) {
// Invalid code or other auth issue
$error = 'Der Code ist ungültig oder abgelaufen.';
$step = '2fa'; // Stay on 2FA step
} catch (Exception $e) {
$error = $e->getMessage();
$step = '2fa';
}
} else {
// Session expired or code not provided
$error = 'Sitzung abgelaufen oder Code fehlt. Bitte versuchen Sie es erneut.';
$step = 'login'; // Send back to login step
$session->remove('2fa.email'); // Clear session
}
}
// Resend code logic
if ($kirby->request()->is('POST') && get('resend')) { // Ensure it's a POST request for resend
$email_from_session = $session->get('2fa.email');
if ($email_from_session) {
$user = $kirby->user($email_from_session);
if ($user) {
try {
$user->send2faCode(); // This should use the configured template
// Optionally, add a success message here if your template supports it
// $success = 'Ein neuer Code wurde gesendet.';
$step = '2fa';
} catch (Exception $e) {
$error = 'Fehler beim Senden des Codes: ' . $e->getMessage();
$step = '2fa'; // Stay on 2FA step, show error
}
} else {
$error = 'Benutzer für erneutes Senden nicht gefunden.';
$step = 'login';
$session->remove('2fa.email');
}
} else {
$error = 'Sitzung für erneutes Senden abgelaufen.';
$step = 'login';
}
}
return [
'error' => $error,
'step' => $step,
'email' => $email_param // Pass the original email attempt back to the form
];
};
could you have a look?
now the 2fa is not asked, the login workes with just mail and pw; even i have set it true global on the config. in the /panel it woirks but not on the /login frontend
See the docs I linked to, you have to use the login2Fa() method here, instead of the login method! And then the $kirby->auth()-> verifyChallenge()` method after the code is entered.