Two approaches compared: full flow state on the server with permitted next steps, against only the current step held on the client with history reconstructed from a token.
Two ways to hold a journey. Only one can refuse a bad order.

A user journey can look correct at every individual step and still allow an unsafe transition when steps are combined. That is the design problem behind identity-flow state: what has already been verified, what action is currently allowed, and what may happen next?

The idea at a glance
  1. Start request
  2. Validate server state
  3. Run permitted checks
  4. Commit result + audit

Do not reduce the journey to one current step

Keeping only the name of the current step loses important context. A robust flow needs a record of the steps that have completed, the current step, the allowed next steps and the conditions for moving between them. The client can ask to advance, but the server should decide whether the transition is permitted.

Design question: Can a user reach a sensitive step by changing client-held state or by combining two individually valid flows in an unexpected order?

Separate ceremonies by intent

Enrollment, signup, verification, authentication and recovery solve different problems. Enrollment should start from a session that is already authenticated. Signup creates a new identity. Verification builds a claim before a session is issued. Recovery should rely on the credentials and policy intended for recovery, rather than silently reusing a weaker path.

Model sensitive journeys as transactions

Think about the complete request, not just the handler that starts it. A request may need to coordinate authentication, step-up verification, risk checks, profile updates, recovery enrollment and network evaluation. Each part should run in a valid order, and the resulting event trail should preserve how the transaction steps related to one another.

Make the design testable

  1. Write down allowed and forbidden state transitions.
  2. Test out-of-order calls and repeated submissions.
  3. Verify that adding a credential does not let a session retroactively satisfy a stronger check.
  4. Review the audit trail for the whole request, not only the final outcome.

WebFrolic's security white paper describes server-side extended state and transaction-based identity flows as core design principles. Use the paper as a starting point, then validate the behavior in the actual environment.

How an unsafe transition is assembled

The attacker in these cases is not breaking cryptography. They are presenting a legitimate token to a legitimate endpoint in an order nobody tested. Each request is individually reasonable, which is why code review and single-flow penetration tests both miss it.

A concrete shape: a step-up is demanded for a privileged action and refused, then a separate enrollment flow adds a new factor without knowing what just happened, and the new factor satisfies the requirement. Two correct flows, one unsafe sequence.

What the server needs to hold

The server needs more than the current step. It needs the steps that have run, the order they ran in, which remain outstanding, and which transitions are legal from here. With that, a ceremony opened inside a transaction can inherit the transaction’s preconditions rather than starting from a blank slate.

The audit benefit arrives later and is easy to undervalue: because transactions nest, the record shows how actions related to one another rather than leaving an investigator to infer it from timestamps.

Put it into practice

The checks that matter

  • Record valid and invalid transitions.
  • Test repeated, stale and out-of-order requests.
  • Keep recovery, signup and credential enrolment distinct.
  • Review the whole transaction trail.
← Back to all articlesSee the security white paper →