Fix login accepting wrong credentials (empty user signed in anyway)

fis_admin_getUserAccount always inserted a result row, even when no
matching user was found, so fis_admin_authenticate never truly
returned "no result" on wrong credentials — the login handler then
signed the caller in with an empty useraccount_id. The authenticated
shell rendered (IsAuthenticated only checks the claim exists), while
every data endpoint 401'd (FuchsUserIdentity.IsAuthenticated also
checks the id is non-empty), producing an empty portal.

Also treat an empty useraccount_id in HandleLogin as a failed login
(defense in depth) and fix a column-name mismatch (auth vs
authorization) that was silently zeroing the authorization level.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Stefan
2026-09-14 14:51:44 +02:00
co-authored by Claude Sonnet 5
parent c18e34a3f1
commit 38145a917e
2 changed files with 19 additions and 16 deletions
+3 -3
View File
@@ -249,16 +249,16 @@ public partial class IntranetController : Microsoft.AspNetCore.Mvc.Controller
_logger.LogDebug("HandleLogin attempt for email={Email} ip={IP}", _logger.LogDebug("HandleLogin attempt for email={Email} ip={IP}",
email, HttpContext.Connection.RemoteIpAddress); email, HttpContext.Connection.RemoteIpAddress);
var row = await _intranet.AuthenticateAsync(email, password); var row = await _intranet.AuthenticateAsync(email, password);
if (row == null) string userId = row?.nz("useraccount_id") ?? "";
if (row == null || string.IsNullOrEmpty(userId))
{ {
_logger.LogWarning("Login failed for email={Email} ip={IP}", _logger.LogWarning("Login failed for email={Email} ip={IP}",
email, HttpContext.Connection.RemoteIpAddress); email, HttpContext.Connection.RemoteIpAddress);
return Unauthorized401(); return Unauthorized401();
} }
string userId = row.nz("useraccount_id");
string userEmail = row.nz("email"); string userEmail = row.nz("email");
int auth = int.TryParse(row.nz("authorization"), out var a) ? a : 0; int auth = int.TryParse(row.nz("auth"), out var a) ? a : 0;
var identity = FuchsUserIdentity.BuildIdentity(userId, userEmail, auth, Fuchs_intranet.AuthScheme); var identity = FuchsUserIdentity.BuildIdentity(userId, userEmail, auth, Fuchs_intranet.AuthScheme);
var principal = new System.Security.Claims.ClaimsPrincipal(identity); var principal = new System.Security.Claims.ClaimsPrincipal(identity);
@@ -36,19 +36,22 @@ BEGIN
(SELECT ',' + [value] as [text()] FROM [fis_useraccounts_settings] WHERE [useraccount_id] = @useraccount_id and [key] = 'intranet_function' FOR XML PATH(''), TYPE).value('.','nvarchar(max)') (SELECT ',' + [value] as [text()] FROM [fis_useraccounts_settings] WHERE [useraccount_id] = @useraccount_id and [key] = 'intranet_function' FOR XML PATH(''), TYPE).value('.','nvarchar(max)')
, 1,1,''); , 1,1,'');
INSERT INTO @RET IF @useraccount_id IS NOT NULL
VALUES( BEGIN
@useraccount_id INSERT INTO @RET
,IIF(@useraccount_id is null, -1, @auth) VALUES(
,IIF(@useraccount_id is null, null, @name) @useraccount_id
,IIF(@useraccount_id is null, null, @firstname) ,@auth
,IIF(@useraccount_id is null, null, @email) ,@name
,IIF(@useraccount_id is null, null, @mobile) ,@firstname
,IIF(@useraccount_id is null, null, @functions) ,@email
,IIF(@useraccount_id is null, null, @language) ,@mobile
,IIF(@useraccount_id is null, null, @fullname) ,@functions
,IIF(@useraccount_id is null, null, @fullname_rev) ,@language
); ,@fullname
,@fullname_rev
);
END
RETURN; RETURN;