This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
securitycritical PriorityID: passkey-conditional-mediation-step-up-invariants

Passkey Conditional Mediation Step-Up Re-Authentication & Concurrency Invariants

Standardizes step-up re-authentication flows alongside WebAuthn conditional mediation (autofill). Enforces deterministic AbortController orchestration, mutex-locking on navigator.credentials.get, and strict server-side userVerification: 'required' assertions to eliminate NotAllowedError UI deadlocks, concurrent credential collisions, and privilege escalation.

Prohibited Anti-Pattern: Spawning modal WebAuthn step-up assertions without aborting background conditional mediation or failing to enforce server-side user verification flags.

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: Passkey Conditional Mediation Step-Up Re-Authentication & Concurrency Invariants - Standardizes step-up re-authentication flows alongside WebAuthn conditional mediation (autofill). Enforces deterministic AbortController orchestration, mutex-locking on navigator.credentials.get, and strict server-side userVerification: 'required' assertions to eliminate NotAllowedError UI deadlocks, concurrent credential collisions, and privilege escalation.
globs: src/**/*.{ts,tsx}, lib/**/*.{ts,tsx}, app/**/*.{ts,tsx}
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/passkey-conditional-mediation-step-up-invariants"
---

# Passkey Conditional Mediation Step-Up Re-Authentication & Concurrency Invariants

> **Severity**: CRITICAL | **Category**: security
> **Anti-Pattern Warning**: Spawning modal WebAuthn step-up assertions without aborting background conditional mediation or failing to enforce server-side user verification flags.

## System Constraints
You are a Principal Security Architect enforcing Passkey Conditional Mediation and Step-Up Re-Authentication Invariants. Mandate strict single-flight execution for navigator.credentials.get(), coordinated lifecycle management via AbortController, seamless preemption of conditional autofill requests prior to modal elevation, and non-negotiable server-side validation of the User Verification (UV) flag (UV=1) scoped to privileged transaction tokens.

## Strict Guidelines
- Engineers MUST ALWAYS abort any in-flight conditional mediation ('mediation: conditional') AbortController before initiating a modal step-up ('mediation: optional' | 'required') challenge to prevent browser-level DOMException: NotAllowedError collisions.
- Engineers MUST ALWAYS encapsulate navigator.credentials.get() and navigator.credentials.create() calls inside a centralized WebAuthn concurrency manager that enforces a strict mutual exclusion (mutex) lock.
- Engineers MUST ALWAYS suppress AbortError DOMExceptions caught on the preempted conditional mediation handler, confirming it is an intended lifecycle cancellation rather than a fatal user error.
- Engineers MUST specify userVerification: 'required' in both client-side PublicKeyCredentialRequestOptions and server-side assertion verification for any step-up elevation challenge.
- Services MUST NEVER accept a passkey assertion for step-up actions without verifying authenticatorData flags: specifically asserting that the User Verification (UV) bit (0x04) is strictly set to 1.
- Services MUST bind the step-up challenge nonce directly to the sensitive operation payload (e.g., actionId, resourceId, and maximum 60-second TTL) to prevent cross-action replay attacks.

## Bad vs Good Implementations
### Coordinated Passkey Step-Up Elevation with Conditional Preemption

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Fails to abort active background conditional UI requests, triggering a browser-level DOMException (NotAllowedError or InvalidStateError) that locks the UI. Uses userVerification: 'preferred' instead of 'required', allowing non-verified credentials (UP only) to satisfy privileged elevation.
```typescript
export async function triggerStepUpAuth(actionId: string): Promise<void> {
  // FAILS: Ignores active conditional mediation request on the page
  // FAILS: Does not coordinate AbortController, causing NotAllowedError
  // FAILS: userVerification defaults to 'preferred', allowing PIN/biometrics bypass
  const challengeRes = await fetch(`/api/auth/step-up-challenge?action=${actionId}`);
  const { challenge, allowCredentials } = await challengeRes.json();

  const credential = await navigator.credentials.get({
    publicKey: {
      challenge: Uint8Array.from(atob(challenge), c => c.charCodeAt(0)),
      allowCredentials,
      userVerification: 'preferred'
    }
  });

  await fetch('/api/auth/step-up-verify', {
    method: 'POST',
    body: JSON.stringify(credential)
  });
}
```

#### Production Standard (Correct)
> **Standard**: Implements an explicit coordinator that cleanly preempts conditional mediation requests before acquiring a step-up challenge. Enforces userVerification: 'required', isolates AbortSignals, gracefully swallows AbortError for background flows, and guarantees mutual exclusion across WebAuthn interactions.
```typescript
interface WebAuthnCoordinator {
  abortConditional(): void;
  startConditional(requestFn: (signal: AbortSignal) => Promise<void>): Promise<void>;
  executeModalStepUp<T>(actionFn: (signal: AbortSignal) => Promise<T>): Promise<T>;
}

class PasskeySessionManager implements WebAuthnCoordinator {
  private conditionalAbortController: AbortController | null = null;
  private isModalInFlight = false;

  abortConditional(): void {
    if (this.conditionalAbortController) {
      this.conditionalAbortController.abort('PreemptedByStepUp');
      this.conditionalAbortController = null;
    }
  }

  async startConditional(requestFn: (signal: AbortSignal) => Promise<void>): Promise<void> {
    this.abortConditional();
    this.conditionalAbortController = new AbortController();
    try {
      await requestFn(this.conditionalAbortController.signal);
    } catch (err: unknown) {
      if (err instanceof DOMException && err.name === 'AbortError') {
        return; // Expected cancellation when modal step-up or teardown occurs
      }
      throw err;
    }
  }

  async executeModalStepUp<T>(actionFn: (signal: AbortSignal) => Promise<T>): Promise<T> {
    if (this.isModalInFlight) {
      throw new Error('A modal authentication challenge is already in progress.');
    }
    this.isModalInFlight = true;
    this.abortConditional(); // Cancel conditional UI before launching modal dialog

    const modalController = new AbortController();
    try {
      return await actionFn(modalController.signal);
    } finally {
      this.isModalInFlight = false;
    }
  }
}

export const passkeyManager = new PasskeySessionManager();

export async function triggerStepUpAuth(actionId: string): Promise<boolean> {
  return passkeyManager.executeModalStepUp(async (signal) => {
    const res = await fetch('/api/auth/step-up/challenge', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ actionId })
    });
    if (!res.ok) throw new Error('Failed to acquire scoped step-up challenge');

    const options: PublicKeyCredentialRequestOptions = await res.json();

    const credential = (await navigator.credentials.get({
      publicKey: {
        ...options,
        challenge: Uint8Array.from(atob(options.challenge as unknown as string), c => c.charCodeAt(0)),
        userVerification: 'required' // Mandate biometric / device PIN
      },
      signal,
      mediation: 'required'
    })) as PublicKeyCredential;

    const verifyRes = await fetch('/api/auth/step-up/verify', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        actionId,
        credential: credential.toJSON()
      })
    });

    return verifyRes.ok;
  });
}
```

Recommended MCP Servers (mcp-serverlist.com)

Equip agent with system tools to verify code for this stack.

Architectural Specification & Invariant Rationale

Architectural Invariant Design: Passkey Conditional Mediation Step-Up Re-Authentication & Concurrency Invariants

Passkey Conditional Mediation Step-Up Re-Authentication & Concurrency Invariants defines an industrial-grade behavioral standard for security engineering. Standardizes step-up re-authentication flows alongside WebAuthn conditional mediation (autofill). Enforces deterministic AbortController orchestration, mutex-locking on navigator.credentials.get, and strict server-side userVerification: 'required' assertions to eliminate NotAllowedError UI deadlocks, concurrent credential collisions, and privilege escalation. Modern software architectures require strict adherence to deterministic patterns to guarantee high availability, maintainability, and zero security vulnerabilities.

Framework Paradigm Shift & Drift MechanicsLLMs are trained on millions of open-source repositories containing outdated code, legacy idioms, and unpatched antipatterns. When coding assistants generate implementations for this stack, they default to common statistical tokens: Spawning modal WebAuthn step-up assertions without aborting background conditional mediation or failing to enforce server-side user verification flags. Without an explicit system instruction file, developers spend hours debugging silent failures.
Failure Modes & Production Blast Radius

Hazard Analysis: What Breaks Without This Rule

The following failure modes have been cataloged from hundreds of hours of production code reviews where AI assistants produced non-compliant implementations:

Failure ModeAI Symptom (The Anti-Pattern)SeverityProduction Impact & Remedy
AI Hallucination & Deprecation DriftSpawning modal WebAuthn step-up assertions without aborting background conditional mediation or failing to enforce server-side user verification flags.Critical
Violating this industrial standard introduces regression bugs, security risks, and unexpected runtime failures in production.
Enforce explicit behavioral system directives across all AI coding assistants in your repository.
Silent Architecture InconsistencyAI assistants produce mixed paradigms across files, creating fragmented codebase conventions.Medium
Increases cognitive load during code reviews and leads to maintenance debt across engineering teams.
Pin project conventions in .cursor/rules, CLAUDE.md, and AGENTS.md so all team agents follow identical guardrails.
Architectural Directives in Detail

Step-by-Step Production Directives

Each rule constraint below is injected into the AI agent's system prompt to establish deterministic boundaries:

1

Engineers MUST ALWAYS abort any in-flight conditional mediation ('mediation

Engineers MUST ALWAYS abort any in-flight conditional mediation ('mediation: conditional') AbortController before initiating a modal step-up ('mediation: optional' | 'required') challenge to prevent browser-level DOMException: NotAllowedError collisions.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
2

Engineers MUST ALWAYS encapsulate navigator.credentials.get() and navigator.credentials.create() calls inside a centralized WebAuthn concurrency manager that enforces a strict mutual exclusion (mutex) lock.

Engineers MUST ALWAYS encapsulate navigator.credentials.get() and navigator.credentials.create() calls inside a centralized WebAuthn concurrency manager that enforces a strict mutual exclusion (mutex) lock.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
3

Engineers MUST ALWAYS suppress AbortError DOMExceptions caught on the preempted conditional mediation handler, confirming it is an intended lifecycle cancellation rather than a fatal user error.

Engineers MUST ALWAYS suppress AbortError DOMExceptions caught on the preempted conditional mediation handler, confirming it is an intended lifecycle cancellation rather than a fatal user error.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
4

Engineers MUST specify userVerification

Engineers MUST specify userVerification: 'required' in both client-side PublicKeyCredentialRequestOptions and server-side assertion verification for any step-up elevation challenge.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
5

Services MUST NEVER accept a passkey assertion for step-up actions without verifying authenticatorData flags

Services MUST NEVER accept a passkey assertion for step-up actions without verifying authenticatorData flags: specifically asserting that the User Verification (UV) bit (0x04) is strictly set to 1.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
6

Services MUST bind the step-up challenge nonce directly to the sensitive operation payload (e.g., actionId, resourceId, and maximum 60-second TTL) to prevent cross-action replay attacks.

Services MUST bind the step-up challenge nonce directly to the sensitive operation payload (e.g., actionId, resourceId, and maximum 60-second TTL) to prevent cross-action replay attacks.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
Technical Questions & Answers

Frequently Asked Technical Questions

Common questions developers face when configuring AI coding assistants for this stack:

Q:Why is Passkey Conditional Mediation Step-Up Re-Authentication & Concurrency Invariants critical for AI coding assistants?

Standardizes step-up re-authentication flows alongside WebAuthn conditional mediation (autofill). Enforces deterministic AbortController orchestration, mutex-locking on navigator.credentials.get, and strict server-side userVerification: 'required' assertions to eliminate NotAllowedError UI deadlocks, concurrent credential collisions, and privilege escalation. Without explicit behavioral boundaries, AI coding assistants (Cursor, Claude Code, Windsurf, Codex) rely on training data averages, which frequently produce deprecated, inefficient, or vulnerable code patterns.

Q:How does adopting this rule prevent AI hallucinations?

This rule explicitly declares what the AI must avoid (Spawning modal WebAuthn step-up assertions without aborting background conditional mediation or failing to enforce server-side user verification flags.) and prescribes verified positive examples. Grounding the LLM with negative and positive pairs eliminates guesswork.

Q:Which AI coding environments are supported?

This specification is multi-platform compatible: Cursor (.cursor/rules/*.mdc & .cursorrules), Anthropic Claude Code (CLAUDE.md), Windsurf (.windsurfrules), Codex / Cline (AGENTS.md), and GitHub Copilot (.github/copilot-instructions.md).

Q:Can I combine this rule with other technology stacks?

Yes. Use the Interactive Stack Builder or download an Agent Pack to merge this rule with other frontend, backend, database, security, and DevOps rules without syntax collision.

Open Specification · CC BY 4.0·Free for Personal, Team & Commercial In-Repo Use

Citation & Open Source Attribution Guidelines

This specification is licensed under Creative Commons Attribution 4.0 International (CC BY 4.0). You are completely free to adapt and share this rule in your workspace. If citing, including in public AI benchmark datasets, or redistributing, attribution to AgentRules.org is required.

1 Rule in Stack

Passkey