This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
securitycritical PriorityID: webauthn-passkey-tenant-rpid-sandboxing

Passkey WebAuthn RP ID Sandboxing and Tenant-Scoped Conditional Mediation

Enforces strict dynamic Relying Party ID (RP ID) scoping and origin isolation in multi-tenant WebAuthn deployments. Prevents cross-tenant credential autocomplete pollution and account collisions during conditional mediation passkey ceremonies by prohibiting broad apex-domain relaxation.

Prohibited Anti-Pattern: Apex-Domain RP ID Relaxation in Multi-Tenant Passkey Conditional Mediation Allowing Cross-Tenant Credential Leakage

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: Passkey WebAuthn RP ID Sandboxing and Tenant-Scoped Conditional Mediation - Enforces strict dynamic Relying Party ID (RP ID) scoping and origin isolation in multi-tenant WebAuthn deployments. Prevents cross-tenant credential autocomplete pollution and account collisions during conditional mediation passkey ceremonies by prohibiting broad apex-domain relaxation.
globs: src/auth/**/*.{ts,tsx}, src/server/auth/**/*.{ts,tsx}, src/pages/api/auth/**/*.{ts,tsx}, src/lib/webauthn/**/*.{ts,tsx}
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/webauthn-passkey-tenant-rpid-sandboxing"
---

# Passkey WebAuthn RP ID Sandboxing and Tenant-Scoped Conditional Mediation

> **Severity**: CRITICAL | **Category**: security
> **Anti-Pattern Warning**: Apex-Domain RP ID Relaxation in Multi-Tenant Passkey Conditional Mediation Allowing Cross-Tenant Credential Leakage

## System Constraints
You are a Principal Software Architect enforcing WebAuthn / FIDO2 security standards. You must strictly mandate dynamic RP ID sandboxing, verify exact tenant-to-origin mapping, and prevent cross-tenant credential exposure in Passkey conditional UI mediation flows.

## Strict Guidelines
- Engineers MUST ALWAYS isolate the WebAuthn RP ID to the fully qualified tenant subdomain (or validated tenant custom domain) rather than collapsing to the root apex eTLD+1 domain.
- Engineers MUST NOT allow `navigator.credentials.get({ mediation: 'conditional' })` to query using a shared root RP ID across isolated multi-tenant workspaces.
- Services MUST verify that `clientDataJSON.origin` matches the exact tenant origin on the backend during both registration (`navigator.credentials.create`) and authentication (`navigator.credentials.get`).
- Services MUST bind stored Passkey credential records immutably to a `tenantId` in the persistence layer and verify that any requested `allowCredentials` or resolved assertions belong exclusively to that tenant.
- Components NEVER trigger conditional passkey mediation prior to verifying that the tenant context has been resolved and validated on the client runtime.

## Bad vs Good Implementations
### Tenant RP ID Resolution & Assertion Verification

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Relaxing rpId to the apex domain 'saas.com' across all tenants enables the browser to surface credentials created in 'tenant-b.saas.com' inside 'tenant-a.saas.com' conditional mediation autofill prompts. This leaks tenant membership and permits cross-tenant credential collision.
```typescript
// BAD: Apex domain relaxation causes passkeys to leak across tenants in conditional UI
import type { Request, Response } from 'express';
import { verifyAuthenticationResponse } from '@simplewebauthn/server';

export async function getAuthOptions(req: Request, res: Response) {
  // Anti-pattern: Broadening RP ID to apex domain allows any tenant passkey
  // to be proposed in autocomplete on tenant-a.saas.com and tenant-b.saas.com
  return res.json({
    challenge: 'c3VwZXItc2VjcmV0LWNoYWxsZW5nZQ',
    rpId: 'saas.com', // Apex relaxation vulnerability
    timeout: 60000,
    userVerification: 'preferred'
  });
}

export async function verifyAuth(req: Request, res: Response) {
  const { credential, expectedChallenge } = req.body;
  // Anti-pattern: Does not validate tenant context against clientData origin
  const verification = await verifyAuthenticationResponse({
    response: credential,
    expectedChallenge,
    expectedOrigin: 'https://saas.com',
    expectedRPID: 'saas.com'
  });
  res.json({ success: verification.verified });
}
```

#### Production Standard (Correct)
> **Standard**: Production invariant compliant implementation ensuring memory safety, deterministic execution, and zero runtime hallucination.
```typescript
// GOOD: Dynamic RP ID sandboxed to the specific tenant subdomain and verified on backend
import type { Request, Response } from 'express';
import { verifyAuthenticationResponse } from '@simplewebauthn/server';

interface TenantConfig {
  id: string;
  hostname: string;
}

function resolveTenantContext(req: Request): TenantConfig {
  const tenantHostname = req.hostname.toLowerCase();
  const tenantId = req.headers['x-tenant-id'];
  if (typeof tenantId !== 'string' || !tenantHostname.endsWith('.saas.com')) {
    throw new Error('Invalid or unverified tenant boundary');
  }
  return { id: tenantId, hostname: tenantHostname };
}

export async function getAuthOptions(req: Request, res: Response) {
  const tenant = resolveTenantContext(req);

  return res.json({
    challenge: 'c3VwZXItc2VjcmV0LWNoYWxsZW5nZQ',
    // Invariant: RP ID is sandboxed strictly to the tenant subdomain
    rpId: tenant.hostname,
    timeout: 60000,
    userVerification: 'preferred'
  });
}

export async function verifyAuth(req: Request, res: Response) {
  const tenant = resolveTenantContext(req);
  const { credential, expectedChallenge } = req.body;

  const verification = await verifyAuthenticationResponse({
    response: credential,
    expectedChallenge,
    // Invariant: Origin and RP ID strictly bound to the isolated tenant
    expectedOrigin: `https://${tenant.hostname}`,
    expectedRPID: tenant.hostname
  });

  if (verification.verified && verification.authenticationInfo) {
    // Invariant: Confirm credential belongs to the resolved tenant
    const credentialRecord = await getCredentialById(verification.authenticationInfo.credentialID);
    if (!credentialRecord || credentialRecord.tenantId !== tenant.id) {
      return res.status(403).json({ error: 'Credential does not belong to this tenant' });
    }
  }

  return res.json({ success: verification.verified });
}

declare function getCredentialById(id: string): Promise<{ tenantId: string } | null>;
```

Architectural Specification & Invariant Rationale

Architectural Invariant Design: Passkey WebAuthn RP ID Sandboxing and Tenant-Scoped Conditional Mediation

Passkey WebAuthn RP ID Sandboxing and Tenant-Scoped Conditional Mediation defines an industrial-grade behavioral standard for security engineering. Enforces strict dynamic Relying Party ID (RP ID) scoping and origin isolation in multi-tenant WebAuthn deployments. Prevents cross-tenant credential autocomplete pollution and account collisions during conditional mediation passkey ceremonies by prohibiting broad apex-domain relaxation. 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: Apex-Domain RP ID Relaxation in Multi-Tenant Passkey Conditional Mediation Allowing Cross-Tenant Credential Leakage 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 DriftApex-Domain RP ID Relaxation in Multi-Tenant Passkey Conditional Mediation Allowing Cross-Tenant Credential LeakageCritical
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 isolate the WebAuthn RP ID to the fully qualified tenant subdomain (or validated tenant custom domain) rather than collapsing to the root apex eTLD+1 domain.

Engineers MUST ALWAYS isolate the WebAuthn RP ID to the fully qualified tenant subdomain (or validated tenant custom domain) rather than collapsing to the root apex eTLD+1 domain.

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 NOT allow `navigator.credentials.get({ mediation

Engineers MUST NOT allow `navigator.credentials.get({ mediation: 'conditional' })` to query using a shared root RP ID across isolated multi-tenant workspaces.

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

Services MUST verify that `clientDataJSON.origin` matches the exact tenant origin on the backend during both registration (`navigator.credentials.create`) and authentication (`navigator.credentials.get`).

Services MUST verify that `clientDataJSON.origin` matches the exact tenant origin on the backend during both registration (`navigator.credentials.create`) and authentication (`navigator.credentials.get`).

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

Services MUST bind stored Passkey credential records immutably to a `tenantId` in the persistence layer and verify that any requested `allowCredentials` or resolved assertions belong exclusively to that tenant.

Services MUST bind stored Passkey credential records immutably to a `tenantId` in the persistence layer and verify that any requested `allowCredentials` or resolved assertions belong exclusively to that tenant.

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

Components NEVER trigger conditional passkey mediation prior to verifying that the tenant context has been resolved and validated on the client runtime.

Components NEVER trigger conditional passkey mediation prior to verifying that the tenant context has been resolved and validated on the client runtime.

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 WebAuthn RP ID Sandboxing and Tenant-Scoped Conditional Mediation critical for AI coding assistants?

Enforces strict dynamic Relying Party ID (RP ID) scoping and origin isolation in multi-tenant WebAuthn deployments. Prevents cross-tenant credential autocomplete pollution and account collisions during conditional mediation passkey ceremonies by prohibiting broad apex-domain relaxation. 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 (Apex-Domain RP ID Relaxation in Multi-Tenant Passkey Conditional Mediation Allowing Cross-Tenant Credential Leakage) 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