From f2f23f986492ff2b2d54644b3c2f03114fc0846b Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Sat, 4 Jul 2026 14:48:30 +0100 Subject: [PATCH] Fix login endpoint leaking account existence via EmailNotConfirmed flag Returning EmailNotConfirmed=true after a correct password was submitted disclosed both that the email address is registered and that the password is valid, without completing authentication. The endpoint now returns a uniform 401 Bad credentials in all failure cases. Clients should offer a resend-confirmation link unconditionally via POST /auth/email/resend. --- Marechai.Server/Controllers/AuthController.cs | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/Marechai.Server/Controllers/AuthController.cs b/Marechai.Server/Controllers/AuthController.cs index d7858fcf..a1501925 100644 --- a/Marechai.Server/Controllers/AuthController.cs +++ b/Marechai.Server/Controllers/AuthController.cs @@ -101,20 +101,11 @@ public class AuthController if(userInDb is null) return Unauthorized(); - // Identity is configured with RequireConfirmedAccount=true. Surface the unconfirmed-email state as an - // explicit flag in the response so the client can offer a "Resend confirmation email" affordance - // instead of a generic "bad credentials" message (which would be confusing since the password was - // accepted just above). - if(!userInDb.EmailConfirmed) - { - return Ok(new AuthResponse - { - Message = "Email not confirmed", - Succeeded = false, - Token = "", - EmailNotConfirmed = true - }); - } + // Identity is configured with RequireConfirmedAccount=true. Return a generic 401 rather than surfacing + // the unconfirmed-email flag explicitly — doing so would let an attacker enumerate valid accounts + // (and confirm correct passwords) without completing login. Clients should offer a "resend confirmation" + // link unconditionally via the POST /auth/email/resend endpoint, which is already anti-enumeration. + if(!userInDb.EmailConfirmed) return Unauthorized("Bad credentials"); // Two-factor required: short-circuit and return a pending token. The client must collect a code via one of // the /auth/login/two-factor* endpoints to complete the login.