Step 3 of #8072 — design: docs/superpowers/specs/2026-09-17-resigned-account-login-refusal-design.md (PR #8073).
Steps 1 and 2 shipped: EformUser.IsActive in Microting.eFormApi.BasePn 10.0.35, and the Users.IsActive column in Microting.EformAngularFrontendBase 10.0.39. Nothing reads the flag yet.
This issue
-
Refuse login when IsActive == false on every surface in this repo:
AuthService.AuthenticateUser (REST POST /api/auth/token; the core gRPC service delegates here, so it inherits the check)
AuthService.RefreshToken — today it mints a fresh 24h token on nothing more than "the row still exists", so a disabled account could otherwise roll its session forward indefinitely
AuthService.GetGoogleAuthenticator — anonymous, and a second credential-verification oracle
-
One identical failure message for unknown account, wrong password and disabled account:
You have entered an invalid username or password
Today they are three distinguishable hard-coded English literals, and the unknown-account one echoes the submitted username back:
| Case |
Today |
| unknown account |
User with username <what you typed> not found |
| wrong password |
Incorrect password. |
| disabled |
did not exist |
The client toasts body.message verbatim (apiBase.service.ts:257-261), so the login box currently tells any visitor which emails have accounts. The UserNameOrPasswordIncorrect resource key already exists in all 25 .resx files and is already used by GetGoogleAuthenticator — reuse it rather than adding a near-duplicate.
Brute-force lockout keeps its own distinct message: it is temporary and self-resolving, users need to understand it, and it reveals nothing the generic message hides.
-
Bump Microting.eFormApi.BasePn to 10.0.35 and Microting.EformAngularFrontendBase to 10.0.39.
Deploy note
Program.cs:214 runs Database.Migrate() per tenant at startup, so deploying this applies the IsActive column automatically. Deploy the host before any plugin bumps BasePn: the property maps by convention, so a plugin dragging BasePn ≥ 10.0.35 onto a host without the column makes every query against Users fail.
Not in this issue
Step 3 of #8072 — design:
docs/superpowers/specs/2026-09-17-resigned-account-login-refusal-design.md(PR #8073).Steps 1 and 2 shipped:
EformUser.IsActiveinMicroting.eFormApi.BasePn10.0.35, and theUsers.IsActivecolumn inMicroting.EformAngularFrontendBase10.0.39. Nothing reads the flag yet.This issue
Refuse login when
IsActive == falseon every surface in this repo:AuthService.AuthenticateUser(RESTPOST /api/auth/token; the core gRPC service delegates here, so it inherits the check)AuthService.RefreshToken— today it mints a fresh 24h token on nothing more than "the row still exists", so a disabled account could otherwise roll its session forward indefinitelyAuthService.GetGoogleAuthenticator— anonymous, and a second credential-verification oracleOne identical failure message for unknown account, wrong password and disabled account:
Today they are three distinguishable hard-coded English literals, and the unknown-account one echoes the submitted username back:
User with username <what you typed> not foundIncorrect password.The client toasts
body.messageverbatim (apiBase.service.ts:257-261), so the login box currently tells any visitor which emails have accounts. TheUserNameOrPasswordIncorrectresource key already exists in all 25.resxfiles and is already used byGetGoogleAuthenticator— reuse it rather than adding a near-duplicate.Brute-force lockout keeps its own distinct message: it is temporary and self-resolving, users need to understand it, and it reveals nothing the generic message hides.
Bump
Microting.eFormApi.BasePnto 10.0.35 andMicroting.EformAngularFrontendBaseto 10.0.39.Deploy note
Program.cs:214runsDatabase.Migrate()per tenant at startup, so deploying this applies theIsActivecolumn automatically. Deploy the host before any plugin bumps BasePn: the property maps by convention, so a plugin dragging BasePn ≥ 10.0.35 onto a host without the column makes every query againstUsersfail.Not in this issue
eform-backendconfiguration-pluginand the time-planning plugin (which also owns a second, parallel login implementation).