Scope Password Resets to the Current Panel

A staff sign-in page and a customer sign-in page can share a user table without offering the same access. Password recovery has to respect that difference too. Restricting the login form while leaving recovery unscoped creates a second path with different rules.
My account-lifecycle update in AdzByte App applies the panel rule to both reset requests and reset completion. One regression case is particularly useful: asking for a reset from the wrong panel must leave an existing valid token alone. That goes beyond checking whether the page sent an email.
Put eligibility in the broker lookup
The implementation uses one trait shared by the request-password-reset page and the reset-password page. It adds a query constraint to the credentials used for recovery. The current panel determines which web-guard roles qualify.
For the admin panel, the query allows the application’s administrator and super-administrator roles. For the account panel, it allows the customer role. An unknown panel produces an empty allowed set. This is a rule about which account can sign in through that panel, not a new identity system.
The trait also trims and lowercases the supplied email. That keeps this recovery path consistent when someone enters an address in uppercase. The test exercises that input instead of assuming the browser will normalize it.
Keeping the eligibility query shared helps because request and completion need the same decision. Two similar conditionals in separate pages are easy to update differently during the next role change.
Check both ends of password recovery
The request page determines whether to create recovery work. The reset page determines whether a presented token may change this user’s password through this panel. Both need the rule.
Checking only the request form leaves an awkward question: what happens if someone brings a token to a different panel’s reset action? Checking only completion can still allow the wrong request path to send mail or replace a token unnecessarily.
The regression test first creates a valid recovery token, waits beyond the relevant request interval, then requests recovery through the wrong panel. It asserts that the existing token still works and that no queued email job was created.
That’s a useful way to test a denial. Don’t stop at the response code or generic message. Check that the rejected operation didn’t change the valid state the user already had. Recovery should remain possible through the right route.
Keep the response useful without confirming membership
The request page uses the same notification for success and failure: if an account can sign in here, a reset email will be sent. It also clears the form after the request. The message gives the user a next step without announcing whether the address belongs to a qualifying account.
This wording is narrower than saying every request sent an email. It covers an unknown address and an address that exists but cannot use the current panel. It also avoids suggesting that a customer account automatically has staff access.
Generic copy is only one part of limiting account disclosure. These tests don’t measure response timing or prove every observable difference has disappeared. Rate limits, logs, and the rest of the recovery path still need review in an application with those requirements.
The practical point is to avoid undoing the query restriction in the message. A carefully scoped backend loses some value if the UI then explains exactly which role an address has.
Follow the generated link through the worker
The tests request recovery from the allowed panel, process the queued notification with a separate worker, and capture the resulting email through a local SMTP sink. They extract the actual reset URL instead of constructing a convenient URL inside the assertion.
That checks several connected pieces: the notification survives queue serialization, the worker produces mail, and the link points at the intended panel. A test that only asserts “notification sent” would leave those parts unexamined.
The test then checks a tampered URL and attempts completion through the wrong panel. The wrong-panel attempt must preserve the token and leave the old password unchanged. Completion through the correct panel changes the password and consumes the token.
This is still controlled test evidence. It doesn’t establish delivery to an external mailbox or describe a production incident. The useful result is a repeatable recovery journey that includes the route, broker, worker, and token state.
Apply later account restrictions to recovery too
A subsequent recoverable record-management change added deleted-account visibility rules. Recovery had to follow that new account state as well. Keeping a row for restoration doesn’t mean the identity should continue requesting access.
The deleted-account test checks that the recovery request sends no notification and creates no password-reset token. Other tests cover existing sessions and bearer tokens after deletion. These are related access paths, and changing one should prompt a review of the others.
For another application, I’d write a small table of account states and allowed recovery routes before adding a new restriction. Include unverified, disabled, deleted, and role-changed states where they exist. Then check both token creation and token consumption for the cases that matter.
Be precise about what panel scoping guarantees
This implementation scopes eligibility by current roles. It doesn’t create an independent password or token store for each panel. A user who legitimately qualifies for more than one panel needs to be understood in terms of that shared identity.
The change is useful because the recovery actions now ask the same access question as the panel they belong to. The tests also protect the user’s remaining recovery options when a request is rejected. That’s the behavior I’d want to preserve during future authentication work: the right route works, the wrong route changes nothing, and the interface doesn’t pretend to know more than it should reveal.
Written by
Adrian Saycon
A developer with a passion for emerging technologies, Adrian Saycon focuses on transforming the latest tech trends into great, functional products.

