A session that was authenticated this morning is used all day for everything, from reading a dashboard to deleting a production database. Asking for a second factor on every click trains people to approve prompts without reading them. Asking only at sign-in means a stolen session can do anything. Step-up authentication is the middle path: ask again, with a stronger factor, at the moment an action deserves it.
What step-up authentication is
Step-up authentication means that a signed-in user is asked to authenticate again, or with a stronger method, before a specific action is allowed. The session stays the same. What changes is the evidence attached to it.
Two properties of a session matter here:
- Strength. How was the user authenticated? A password alone, a password plus a one-time code, or a phishing-resistant method such as a passkey.
- Freshness. How long ago did that happen?
A step-up policy states a minimum for one or both, per action. "Changing the payout account needs a phishing-resistant factor used within the last five minutes" is a step-up policy.
This is different from requiring multi-factor authentication at sign-in, which sets one bar for the whole session.
Which actions, and how fresh
Actions that deserve it
A useful test: if a stolen session performed this action, would the damage be hard to reverse? Typical candidates:
- Changing how the account is protected. Adding or removing a passkey, changing the recovery email, resetting a second factor. These are the actions an attacker performs first to keep access.
- Moving money or changing where it goes. Payments above a threshold, payout details, billing ownership.
- Granting access. Assigning an admin role, creating an API key, approving another person's or an agent's request.
- Destroying or exporting data. Deleting a project, exporting a customer list, downloading audit records.
- Privileged operations on infrastructure. Running a command as root, assuming a production cloud role, rotating a signing key.
Keep the list short. Each addition is a prompt somebody sees, and the value of a prompt falls with how often it appears.
How fresh a session must be
Freshness is a number you choose per action, so it helps to think in bands.
- Routine actions: the sign-in itself is enough, however long ago it was, within the session lifetime.
- Sensitive actions: a strong factor within a short window, measured in minutes.
- Critical actions: a strong factor for this specific action, with no reuse at all.
A short reuse window for the middle band matters more than it seems. Without one, an administrator performing six sensitive actions in a row is challenged six times, and the challenge becomes noise. With one, they are challenged once and work for a few minutes.
How it works in OpenID Connect and OAuth
The standards already carry what a step-up needs.
An ID token can include auth_time, the time the user last actively authenticated, along with acr (the authentication context class that was satisfied) and amr (the methods used). An application reads these to decide whether the session meets the bar for an action.
When it does not, the application sends the user back to the identity provider with a request for more:
GET /authorize?
response_type=code
&client_id=billing-web
&scope=openid
&acr_values=phishing-resistant
&max_age=300
&redirect_uri=https://billing.example.com/callbackmax_age=300 tells the provider to reauthenticate the user if their last authentication is older than five minutes. acr_values asks for a particular strength. The value used here is illustrative: the names are agreed between you and your provider. The application must then check auth_time and acr in the token that comes back, and not assume the request was honoured.
For APIs, RFC 9470 (OAuth 2.0 Step Up Authentication Challenge Protocol) defines how a resource server says "this token is valid but not strong enough". It returns a 401 with an error of insufficient_user_authentication and the acr_values or max_age it requires, and the client starts a new authorisation request with those parameters.
The important design point is that the decision is made where the action happens, by the API or service that owns it, not only in the user interface. A step-up that exists only as a modal in the front end can be skipped by calling the API directly.
Avoiding MFA fatigue
Step-up fails when people stop reading the prompt. A few rules keep it meaningful.
- Prefer phishing-resistant factors. A passkey is bound to the site's origin and needs a local gesture. There is no notification to approve by reflex, which removes the attack where a victim is flooded with push requests until they accept one. See passkeys explained.
- Say what is being approved. "Confirm it is you to remove the passkey on your phone" is a decision. "Verify your identity" is a reflex.
- Use a reuse window. One challenge should cover a short burst of related work.
- Do not step up for reading. Reserve it for changes, with rare exceptions such as bulk export.
- Treat silence as refusal. A challenge that times out denies the action. It never falls back to allowing it.
Also plan for the person who cannot step up because they have only one factor enrolled. Requiring a second method at enrolment, before anyone needs it, is far easier than handling this at the moment of a sensitive action.
Step-up for agents and automation
Software cannot touch a fingerprint reader. When an AI agent or a script reaches a sensitive action, the equivalent of a step-up is to ask a person: the action waits, a named human is prompted out of band and the agent proceeds only on approval. OpenID CIBA (Client-Initiated Backchannel Authentication) is the standard for that pattern. We cover it in human approval for agent actions.
How AuthFI does it
A second step is part of every AuthFI plan, with passkeys recommended as the default and authenticator codes as an alternative. An application can require the stronger sign-in. People manage their own passkeys, sessions and second step from their workspace.
The same idea appears at three other layers of the platform:
- On a route. With Zero-Code protection, a rule on a service route states which roles and groups may call it and whether it needs a second step. It is enforced in front of the service, with no change to its code.
- On a server. Rules for privileged commands can allow, refuse, or allow after a fresh second step, decided on the host itself. This is in pilot, and the console says per host whether the rule is actually enforced there.
- For agents. For one sensitive action, an agent swaps its access token for a 60-second token that names the action. When policy asks for it, a named person approves out of band, and no answer is a refusal.
Sign-ins, approvals and refusals all land on the same audit record, for people and agents alike.
Key takeaways
- Step-up authentication raises the strength or freshness of a session for one action, not for the whole sign-in.
- Cover actions that are hard to reverse: security settings, money, access grants, destruction and export.
- Use
max_age,acr_valuesandauth_time, and enforce the requirement at the API, not only in the interface. - Keep prompts rare, specific and phishing-resistant, with a short reuse window, so people still read them.
- For agents, the step-up is a human approval, and a missing answer means no.



