Permission and Authorization Bugs

Deleted Account Still Passes Auth Checks

After an administrator deletes or disables a user account, that user's existing bearer token continues to authenticate successfully and passes authorisation checks on protected endpoints. The authentication middleware verifies only the token's signature and expiry — it never queries the database to confirm the account still exists and is active.

HighBeginnerSecurity testingAPI testingManual testing

// UNDERSTAND

// Symptoms

  • A bearer token captured before account deletion returns 200 OK on GET /api/users/me after the account is deleted
  • The deleted user can still read, write, or delete records using their pre-deletion token
  • Admin-initiated account suspension has no immediate effect on the user's active session
  • The token continues to function until its natural expiry (e.g. 24 hours) even though the account no longer exists

// Root Cause

  • The authentication middleware validates the JWT signature and expiry time but does not perform a database lookup to confirm the referenced user_id still exists and has an active status. A valid token for a deleted account therefore passes every auth check until the token naturally expires.
  • Account deletion does not trigger token revocation — no entry is written to a token blocklist, and the deleted user's tokens continue to function for their full remaining TTL without any mechanism to cut them short.

// Where It Appears

  • SaaS applications where admins can delete or suspend user accounts
  • HR or enterprise tools where off-boarding requires immediate access revocation
  • Applications that use stateless JWT authentication with no token blocklist
  • Multi-tenant platforms where a tenant admin removes a team member's account

// REPRODUCE & TEST

// How to Reproduce

  1. 01Log in as a standard user and capture the bearer token from any authenticated request in DevTools
  2. 02Confirm the token works by sending GET /api/users/me with the bearer token and noting the 200 response
  3. 03In the admin panel, delete or disable the user account
  4. 04Send GET /api/users/me again using the same bearer token captured in step 1
  5. 05If the response is 200 with user data, the deleted account is still passing auth checks

// Test Data Needed

  • A standard user account that can be deleted or disabled via the admin panel
  • The bearer token captured from an authenticated request before the account is deleted
  • Admin access to delete or disable accounts

// Manual Testing Ideas

  • Delete a test account in the admin panel and immediately attempt API calls using the pre-deletion token — confirm whether they succeed or return 401
  • Disable (rather than delete) the account and test the same token to check whether disabled accounts are treated differently from deleted ones
  • Test the browser session as well as the API token — after an admin deletes the account, can the user still navigate the app in an open browser tab?
  • Test off-boarding scenarios: remove a user from a team workspace and confirm their token no longer has access to that workspace's resources
  • Check whether the application has a 'force logout all sessions' feature and whether it correctly invalidates tokens

// API Testing Ideas

  • Authenticate as the test user and capture the bearer token
  • Send GET /api/users/me with the token; assert the response is 200 — confirming the token is valid before deletion
  • Via the admin API or panel, delete or disable the test user account
  • Send GET /api/users/me again with the same bearer token
  • Assert the response is 401 Unauthorized or 403 Forbidden — if it is 200, the deleted account is still authenticated

// Automation Idea

Capture a valid bearer token for a test user. Call the admin API to delete or disable the account (DELETE /api/admin/users/{id}). Immediately send GET /api/users/me with the captured token and assert the response is 401 or 403. A 200 confirms the token was not invalidated on account deletion.

// Expected Result

Immediately after an account is deleted or disabled, all bearer tokens associated with that account are rejected with 401 Unauthorized or 403 Forbidden.

// Actual Result (Example)

After an admin deletes the test user account, GET /api/users/me with the pre-deletion bearer token returns 200 OK and the full user profile. The deleted account's token remains valid for its remaining TTL.

// REPORT IT

Example Bug Report

Title
Bearer token from deleted account still returns 200 on GET /api/users/me
Severity
High
Environment
Staging environment Postman Admin account + standard test user account Bearer token captured before account deletion
Steps to Reproduce
  1. 01Log in as the test user and copy the bearer token from any authenticated request
  2. 02Send GET /api/users/me with the bearer token; confirm the response is 200
  3. 03Log in as admin and delete the test user account from the admin panel
  4. 04Send GET /api/users/me with the same pre-deletion bearer token
Expected Result
The response is 401 Unauthorized — the token is no longer valid.
Actual Result
The response is 200 OK with the deleted user's full profile data. The bearer token from a deleted account continues to authenticate successfully.
Impact
Off-boarded employees or suspended users retain full API access until their token naturally expires. In applications with long token TTLs (e.g. 24 hours), this creates a significant window during which a terminated user can exfiltrate data or take harmful actions.

// RELATED