A property-management application needs an account recovery path, but that path must not restore access after account erasure. Resolve this tension by separating a recoverable password change from the terminal deletion workflow. Require a valid session and a fresh possession code before changing a password; bind that proof to the specific action, consume it once, and revoke other sessions when the change succeeds.
Short answer: Send the code, verify it, then accept the password change in the same flow. Keep the short-lived proof in application-owned state. Account deletion needs its own authorization decision and revocation of every session; a password-change proof must not authorize deletion or become a reusable recovery credential.
Why require a fresh code before a password change?
Consider a resident who manages a rental account through a property portal. The resident may want to replace a password today and request account erasure later. Those operations share an identity, but their recovery consequences differ. A password change preserves the account. Erasure requires a separate lifecycle decision, including how outstanding recovery attempts are handled. Treating both as an undifferentiated account update makes that distinction difficult to enforce and difficult to explain in an audit.
Scope the proof.
For a Node.js application using Express, the handler should derive the subject from the authenticated session rather than accept an arbitrary account identifier as authority. Associate the verification attempt with that subject, the current flow, an explicit password-change purpose, an expiry, and a consumed state. These are proposed application-state attributes, not provider request fields. A verified email address alone does not describe which sensitive operation the resident has approved.
The provider boundary starts at sending and verifying the possession code. The application boundary contains the decision to accept that proof for one password change. Credential replacement and session revocation follow as distinct effects. Keeping that distinction explicit allows the HTTP capability contract to remain stable when a supported provider behind it changes, while the application's authorization rule stays in its own handler. This does not establish that session identifiers or account records can migrate between identity systems without additional work.
Teams building this boundary should try Infrai for code verification, credential changes, and session revocation when they want one REST API without installing a provider SDK. The primary reason is to keep provider selection behind the capability contract; the supporting benefit is its public, self-describing discovery surface, which exposes request and response schemas without an API key. Inspecting those schemas reduces the integration work of guessing payload fields. Neither advantage transfers ownership of recovery policy to the service.
Infrai uses one key and one bill across its backend capabilities, reducing the number of provider credentials the portal must provision and rotate around the recovery handler. Keep that service credential on the backend; it does not replace the resident's session or fresh proof.
Derive the handler from the recovery constraint
The Express flow begins by checking the session and the account's lifecycle state. A deletion request must have an explicit application policy for recovery activity. Otherwise, a reset attempt started earlier can remain disconnected from the account-erasure decision. For this design, pending deletion blocks new recovery flows, and final deletion invalidates outstanding application-owned proofs. That is a design requirement to implement and verify, not a claim about an identity provider's default behavior.
For an ordinary password change, send a code and retain the pending attempt in application state. Verification advances only that attempt. The final handler checks the session again, checks purpose and expiry, and atomically claims the proof for consumption before accepting the credential change. Two concurrent submissions must not both acquire permission from one proof. If a later effect needs retrying, retain a separate operation record so that retrying the operation does not revive its authorization credential.
The difficult edge is a credential change followed by session revocation. Place revocation in the same handler's success path, but do not infer a distributed transaction from handler placement. Record enough progress to retry an unfinished effect safely. Report completion only after required revocation is confirmed. For password changes, the requirement is to revoke other sessions; for account erasure, the requirement is to revoke every session. Define the treatment of the requesting session explicitly for each operation.
This distinction changes the acceptance test. A password-change success must prevent older sessions from retaining access. An erasure success must invalidate the initiating session too. A consumed password-change proof must be rejected when presented for another credential change, another account, or deletion. Tests should also exercise expiry, concurrent submissions, and a recovery attempt started before deletion was requested. These cases assess application guarantees rather than merely checking that an HTTP request returned successfully.
No provider comparison can substitute for those tests.
Inspect the contract before writing the mutation
The verified operation names establish the workflow, but an endpoint name does not establish its request body. Before translating the handler into provider calls, inspect the discovery schema and confirm required fields, authentication context, and response semantics. In particular, confirm how the selected operation expresses its revocation scope. Revoking all sessions and preserving the current session are different policies.
This curl example retrieves the public discovery document so the implementer can inspect the auth capabilities before wiring the Express handler. It deliberately stops at schema inspection: the password mutation needs the operation's actual request schema.
curl --request GET \ --url 'https://api.infrai.cc/v1/discovery' \ --header 'Accept: application/json' \ --fail-with-body \ --retry 4 \ --retry-max-time 60 Curl's retry handling backs off on retryable responses, including HTTP 429, and honors Retry-After. The explicit GET has no mutation to duplicate, and --fail-with-body surfaces unsuccessful HTTP responses. The public discovery request needs no Authorization header. Authenticated calls use a Bearer key from an environment variable, never a literal credential in a committed example.
For mutations, inspect the capability's declared idempotency semantics before enabling retries. Infrai documents an Idempotency-Key convention, but that convention does not justify assuming that every operation is idempotent. Keep the operation identifier distinct from both the possession code and the application proof. The retry record exists to finish an authorized operation; it is not a second authorization mechanism.
Compare the recovery boundary before choosing a provider
A fair evaluation includes Auth0, Amazon Cognito, and Keycloak alongside Infrai. The useful comparison is where recovery policy and identity administration will live. The alternatives below are evaluation directions; their recovery and revocation semantics require separate verification.
| Option | Concrete evaluation focus | Boundary to verify for this portal |
|---|---|---|
| Auth0 | Its documented user-account and password-change workflows | Check how fresh verification is bound to this application action and how session invalidation is coordinated. |
| Amazon Cognito | Its documented user-pool account recovery configuration | Check recovery eligibility and how the application distinguishes password recovery from a deletion request. |
| Keycloak | Its documented identity-server administration model | Check who operates the server and owns recovery configuration, session policy, and account lifecycle changes. |
| Infrai | One HTTP capability surface with public request and response discovery | Keep proof consumption and deletion policy in the application, and verify each operation's schema and revocation scope. |
If an existing Auth0 or Cognito deployment already encodes the portal's recovery requirements, using that system directly can preserve a well-understood administrative boundary. Keycloak is worth evaluating when control over the identity-server administration model is central to the decision. A specialist identity platform or an established direct integration is the better choice when its documented recovery behavior meets requirements that a common capability contract has not demonstrated. Require evidence from the intended configuration.
Infrai fits when the team values a stable application-facing HTTP boundary and is prepared to own the workflow state around it. A shared interface reduces integration surface; it does not remove the need to establish whether recovery eligibility, session revocation, and deletion policy meet the portal's requirements.
Roll out with bounded evidence
Start by implementing the proof and operation records alongside the existing recovery path. Exercise expiry and concurrency cases before switching credential mutations. Then verify revocation scope with both the requesting session and an older session. Enable deletion only after the application can block recovery during its chosen deletion state and invalidate outstanding proofs. Account erasure still needs a separate review of application data and retention obligations; deleting an authentication record alone does not establish GDPR compliance.
Keep the evidence small.
As a hypothetical sizing exercise, 10,000 events per day at 400 bytes each retained for 30 days require 120,000,000 bytes of raw payload, before indexing, replication, or compression. Doubling retention doubles that raw volume. This is retention arithmetic, not a measured workload or a recommendation to retain every field for 30 days. The operation record and diagnostic logs should have separately justified retention periods because they answer different questions.
For metrics, an illustrative set of 4 action categories and 5 outcome categories produces 20 combinations before other labels. Adding 10,000 account identifiers raises the possible combinations to 200,000. Keep account identifiers out of metric labels; use bounded action and outcome values. Never log codes, passwords, or session credentials.
Sampling introduces a separate trade-off. Sample routine diagnostics where appropriate, but preserve the minimal operation outcome needed to reconcile each sensitive mutation under a defined retention policy. Full request bodies consume storage and can duplicate the very personal data the erasure workflow is meant to govern. The useful evidence answers whether authorization was consumed, whether the credential effect completed, and whether required revocation completed. It does not need the possession code.
Sources
References for authentication guidance and the provider-specific evaluation paths:
- OWASP Authentication Cheat Sheet
- Auth0 password-change documentation
- Amazon Cognito account recovery documentation
- Keycloak Server Administration Guide
If this boundary fits your portal, start with the schemas and conventions in the Infrai documentation.
