From 817ccfea312c5f67889c940b7d865188aa34e67d Mon Sep 17 00:00:00 2001 From: Till JS Date: Thu, 19 Mar 2026 15:05:04 +0100 Subject: [PATCH] fix(auth): improve email verification error detection in signIn Better Auth may return error objects instead of throwing for unverified emails. Now checks result.error before hasUser(), uses case-insensitive matching, and re-throws NestJS HTTP exceptions to avoid masking them. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../src/auth/services/better-auth.service.ts | 32 ++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/services/mana-core-auth/src/auth/services/better-auth.service.ts b/services/mana-core-auth/src/auth/services/better-auth.service.ts index 6b6b3cf1c..6dfc4cc07 100644 --- a/services/mana-core-auth/src/auth/services/better-auth.service.ts +++ b/services/mana-core-auth/src/auth/services/better-auth.service.ts @@ -455,6 +455,28 @@ export class BetterAuthService { }, }); + // Better Auth returns error objects instead of throwing for some cases + if (result && typeof result === 'object' && 'error' in result) { + const errorResult = result as { + error: { message?: string; code?: string; status?: number }; + }; + const errorMsg = errorResult.error?.message || ''; + const errorCode = errorResult.error?.code || ''; + this.logger.debug(`SignIn error result: ${JSON.stringify(errorResult.error)}`); + + if ( + errorMsg.includes('not verified') || + errorMsg.includes('not confirmed') || + errorCode === 'EMAIL_NOT_VERIFIED' || + errorCode === 'EMAIL_NOT_CONFIRMED' + ) { + throw new ForbiddenException({ + message: 'Email not verified', + code: 'EMAIL_NOT_VERIFIED', + }); + } + } + if (!hasUser(result)) { throw new UnauthorizedException('Invalid credentials'); } @@ -550,9 +572,17 @@ export class BetterAuthService { expiresIn: 15 * 60, // 15 minutes in seconds }; } catch (error: unknown) { + // Re-throw NestJS HTTP exceptions directly + if (error instanceof ForbiddenException || error instanceof UnauthorizedException) { + throw error; + } + if (error instanceof Error) { + this.logger.debug(`SignIn caught error: ${error.message}`); + if ( - error.message?.includes('Email not verified') || + error.message?.toLowerCase().includes('not verified') || + error.message?.toLowerCase().includes('not confirmed') || error.message?.includes('EMAIL_NOT_VERIFIED') ) { throw new ForbiddenException({