fix(auth): surface email-not-verified error and detect needsVerification on signup

- mana-auth login route: catch Better Auth's email verification error and
  return 403 EMAIL_NOT_VERIFIED instead of 401 Invalid credentials
- shared-auth signUp: detect emailVerified:false in register response and
  return needsVerification:true so the UI shows the verification prompt
- shared-auth-ui LoginPage: map INVALID_CREDENTIALS error code to friendly message
- shared-i18n: add invalidCredentials translation (de/en)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Till JS 2026-03-31 17:52:47 +02:00
parent 999c54a5a1
commit b1af506b99
5 changed files with 15 additions and 5 deletions

View file

@ -169,13 +169,12 @@ export function createAuthService(config: AuthServiceConfig): AuthServiceInterfa
return { success: false, error: errorData.message || 'Sign up failed' };
}
// Consume response to avoid unhandled promise
await response.json();
const data = await response.json();
// Mana Core Auth returns user data immediately on registration
// User needs to sign in separately to get tokens
// If emailVerified is false, the user needs to verify their email before login
const needsVerification = data?.user?.emailVerified === false;
trackAuth('signup', { method: 'email' });
return { success: true, needsVerification: false };
return { success: true, needsVerification };
} catch (error) {
console.error('Error signing up:', error);
trackAuth('signup_failed', { method: 'email' });

View file

@ -19,6 +19,7 @@
"emailInvalid": "Bitte gib eine gültige E-Mail-Adresse ein",
"passwordRequired": "Passwort ist erforderlich",
"signInFailed": "Anmeldung fehlgeschlagen",
"invalidCredentials": "Ungültige E-Mail oder Passwort",
"signInSuccess": "Erfolgreich angemeldet. Weiterleitung...",
"emailVerified": "E-Mail erfolgreich bestätigt! Bitte melde dich an.",
"emailNotVerified": "E-Mail nicht bestätigt.",

View file

@ -19,6 +19,7 @@
"emailInvalid": "Please enter a valid email address",
"passwordRequired": "Password is required",
"signInFailed": "Sign in failed",
"invalidCredentials": "Invalid email or password",
"signInSuccess": "Successfully signed in. Redirecting...",
"emailVerified": "Email successfully verified! Please sign in.",
"emailNotVerified": "Email not verified.",

View file

@ -34,6 +34,7 @@ export interface AuthTranslations {
emailInvalid: string;
passwordRequired: string;
signInFailed: string;
invalidCredentials?: string;
signInSuccess: string;
emailVerified?: string;
emailNotVerified?: string;

View file

@ -131,6 +131,14 @@ export function createAuthRoutes(
return c.json(response);
} catch (error) {
// Check if Better Auth rejected login due to unverified email
const errorMessage = error instanceof Error ? error.message : String(error);
const isEmailNotVerified =
errorMessage.includes('email') && errorMessage.toLowerCase().includes('verif');
if (isEmailNotVerified) {
return c.json({ error: 'Email not verified', code: 'EMAIL_NOT_VERIFIED' }, 403);
}
security.logEvent({
eventType: 'LOGIN_FAILURE',
ipAddress: ip,