Description
A signed-in session survives the administrator account being deleted, recreated, or having its password
changed. There is no way to revoke access short of waiting out the 14-day cookie lifetime.
Observed accidentally: after dropping and recreating the demo database (so AdminAccounts was empty, then
seeded with a different admin), an existing browser session was still authenticated — the nav rendered
signed-in links and /settings was reachable.
This is a gap in the auth design from #48, not an unlucky edge case. The cookie carries the username and
role as claims, and nothing re-checks them against the store on subsequent requests, so the cookie is the
authority for its whole lifetime.
The root cause is a deliberate decision made in #48 that turns out to have been too narrow: we took ASP.NET
Core Identity's PasswordHasher but not the rest of Identity, including the security stamp — the
mechanism whose entire purpose is invalidating existing sessions when credentials change. Skipping the user
store was right; skipping the revocation mechanism was not, and nothing replaced it.
Impact
- Deleting the administrator does not sign anyone out.
- Changing the password does not invalidate other sessions (so a stolen cookie survives the usual response
to a suspected compromise).
- No way to force-sign-out a session at all.
Severity is moderate rather than high for a single-admin self-hosted tool on a trusted network — but
"change the password" is the reflex when someone suspects a leak, and here it does nothing to existing
sessions, which is worse than the user will assume.
Reproduction Steps
- Set up an administrator and sign in.
- Delete the row:
delete from "AdminAccounts";
- Reload any authenticated page — still signed in, still authorised.
- Same holds after recreating a different administrator, or changing the password.
Expected Behavior
Deleting the administrator, or changing its password, invalidates existing sessions promptly.
Actual Behavior
Sessions remain valid for the full 14-day cookie lifetime regardless.
Scope
Alternative
Shorten ExpireTimeSpan so a stale session dies sooner. That reduces the window without fixing anything,
and trades it against forcing the operator to log in constantly.
Notes
Description
A signed-in session survives the administrator account being deleted, recreated, or having its password
changed. There is no way to revoke access short of waiting out the 14-day cookie lifetime.
Observed accidentally: after dropping and recreating the demo database (so
AdminAccountswas empty, thenseeded with a different admin), an existing browser session was still authenticated — the nav rendered
signed-in links and
/settingswas reachable.This is a gap in the auth design from #48, not an unlucky edge case. The cookie carries the username and
role as claims, and nothing re-checks them against the store on subsequent requests, so the cookie is the
authority for its whole lifetime.
The root cause is a deliberate decision made in #48 that turns out to have been too narrow: we took ASP.NET
Core Identity's
PasswordHasherbut not the rest of Identity, including the security stamp — themechanism whose entire purpose is invalidating existing sessions when credentials change. Skipping the user
store was right; skipping the revocation mechanism was not, and nothing replaced it.
Impact
to a suspected compromise).
Severity is moderate rather than high for a single-admin self-hosted tool on a trusted network — but
"change the password" is the reflex when someone suspects a leak, and here it does nothing to existing
sessions, which is worse than the user will assume.
Reproduction Steps
delete from "AdminAccounts";Expected Behavior
Deleting the administrator, or changing its password, invalidates existing sessions promptly.
Actual Behavior
Sessions remain valid for the full 14-day cookie lifetime regardless.
Scope
AdminAccount— a value that changes whenever credentials change.OnValidatePrincipalevent: load the account,compare the stamp against the one in the cookie, and reject the principal on mismatch or if the
account is gone. Use
ValidateIntervalso this is a periodic check rather than a database read onevery single request.
session is unaffected.
Alternative
Shorten
ExpireTimeSpanso a stale session dies sooner. That reduces the window without fixing anything,and trades it against forcing the operator to log in constantly.
Notes
identity provider's concern, but our cookie lifetime still applies locally.