This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
securitycritical PriorityID: oauth21-rar-fine-grained-assertion

OAuth 2.1 Rich Authorization Requests (RFC 9396) Fine-Grained Assertion Guardrail

Eliminates privilege escalation and confused deputy vulnerabilities by replacing coarse OAuth 2.0 scopes with RFC 9396 Rich Authorization Requests (RAR). Mandates cryptographically sender-constrained access token verification with explicit, transactional equality and threshold validation between API request parameters and token authorization_details payloads.

Prohibited Anti-Pattern: Authorizing High-Value Mutations with Coarse Scopes Instead of RFC 9396 authorization_details Assertions

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: OAuth 2.1 Rich Authorization Requests (RFC 9396) Fine-Grained Assertion Guardrail - Eliminates privilege escalation and confused deputy vulnerabilities by replacing coarse OAuth 2.0 scopes with RFC 9396 Rich Authorization Requests (RAR). Mandates cryptographically sender-constrained access token verification with explicit, transactional equality and threshold validation between API request parameters and token authorization_details payloads.
globs: src/middleware/**/*.ts, src/controllers/**/*.ts, src/auth/**/*.ts, src/routes/**/*.ts
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/oauth21-rar-fine-grained-assertion"
---

# OAuth 2.1 Rich Authorization Requests (RFC 9396) Fine-Grained Assertion Guardrail

> **Severity**: CRITICAL | **Category**: security
> **Anti-Pattern Warning**: Authorizing High-Value Mutations with Coarse Scopes Instead of RFC 9396 authorization_details Assertions

## System Constraints
You are a Principal Security Architect enforcing OAuth 2.1 Rich Authorization Requests (RFC 9396). Reject any API authorization pattern relying on coarse-grained OAuth scopes (e.g., 'transfers:write', 'admin') for sensitive domain mutations. Require strict runtime schema validation of token `authorization_details` and ensure transactional business payloads are cryptographically locked to the exact authorization bounds specified in the token.

## Strict Guidelines
- Services MUST NEVER rely solely on OAuth 2.0 string-based scopes (e.g., 'scope: payment') for authorizing state-mutating, financial, or data-exfiltration-sensitive operations.
- Services MUST extract, parse, and validate RFC 9396 `authorization_details` from verified access tokens using strict schema validators (e.g., Zod or TypeBox).
- Services MUST cryptographically assert that the token is sender-constrained using DPoP (RFC 9449) `jkt` thumbprint matching or mTLS client certificate binding (`x5t#S256`).
- Authorization logic MUST assert exact parameter matching or bounded sub-setting: request entity IDs, source accounts, destination accounts, currency, and numerical thresholds MUST match or fall strictly within the RAR payload.
- Handlers MUST emit an OAuth 2.1 compliant error response with HTTP 403 Forbidden and error code `insufficient_authorization_details` when the request payload exceeds or mismatches authorization_details.
- Services MUST treat an access token containing multiple `authorization_details` objects by locating the exact matching `type` descriptor and confirming that all required action parameters conform to that specific entry.

## Bad vs Good Implementations
### RFC 9396 Rich Authorization Request (RAR) Validation vs Coarse Scope Check

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: The endpoint relies on the coarse scope 'transfers:write'. Any client granted this scope can execute transfers to arbitrary recipients for arbitrary sums, exposing the application to token-reuse fraud, lateral privilege escalation, and confused deputy exploits.
```typescript
import { Request, Response } from 'express';

interface AuthenticatedRequest extends Request {
  user?: { id: string; scopes: string[] };
}

export async function handleTransfer(req: AuthenticatedRequest, res: Response) {
  const { debtorIban, creditorIban, amount, currency } = req.body;

  // CRITICAL SECURITY FLAW: Coarse-grained scope check permits unbounded financial movement.
  // Any token with 'transfers:write' can drain any account to any destination of any amount.
  if (!req.user?.scopes?.includes('transfers:write')) {
    return res.status(403).json({ error: 'insufficient_scope' });
  }

  const result = await executeBankTransfer({ debtorIban, creditorIban, amount, currency });
  return res.status(200).json(result);
}
```

#### Production Standard (Correct)
> **Standard**: Validates RFC 9396 authorization_details via Zod, enforces DPoP sender-constraining, and asserts that transfer parameters (parties, currency, maximum amount) strictly match the cryptographically authorized payload.
```typescript
import { Request, Response } from 'express';
import { z } from 'zod';

const PaymentAuthorizationDetailSchema = z.object({
  type: z.literal('payment_initiation'),
  actions: z.array(z.string()).refine((a) => a.includes('initiate')),
  instructed_amount: z.object({
    currency: z.string().length(3),
    value: z.number().positive(),
  }),
  debtor_account: z.object({
    iban: z.string().min(15).max(34),
  }),
  creditor_account: z.object({
    iban: z.string().min(15).max(34),
  }),
});

type PaymentAuthorizationDetail = z.infer<typeof PaymentAuthorizationDetailSchema>;

interface RARTokenPayload {
  sub: string;
  cnf?: { jkt: string }; // RFC 9449 DPoP sender-constraint thumbprint
  authorization_details?: unknown[];
}

interface AuthenticatedRARRequest extends Request {
  tokenClaims?: RARTokenPayload;
  dpopJkt?: string;
}

export async function handleTransfer(req: AuthenticatedRARRequest, res: Response) {
  const { debtorIban, creditorIban, amount, currency } = req.body;
  const claims = req.tokenClaims;

  // 1. Enforce DPoP Sender-Constrained Binding
  if (!claims?.cnf?.jkt || claims.cnf.jkt !== req.dpopJkt) {
    return res.status(401).json({ error: 'invalid_dpop_proof', error_description: 'Key binding mismatch' });
  }

  // 2. Validate existence and schema of RFC 9396 authorization_details
  if (!Array.isArray(claims.authorization_details)) {
    return res.status(403).json({
      error: 'insufficient_authorization_details',
      error_description: 'Missing RFC 9396 authorization_details claim',
    });
  }

  const paymentAuth = claims.authorization_details
    .map((detail) => PaymentAuthorizationDetailSchema.safeParse(detail))
    .find((result): result is z.SafeParseSuccess<PaymentAuthorizationDetail> => result.success)?.data;

  if (!paymentAuth) {
    return res.status(403).json({
      error: 'insufficient_authorization_details',
      error_description: 'No valid payment_initiation authorization detail found',
    });
  }

  // 3. Cryptographically enforce transactional boundary invariants
  const isDebtorValid = paymentAuth.debtor_account.iban === debtorIban;
  const isCreditorValid = paymentAuth.creditor_account.iban === creditorIban;
  const isCurrencyValid = paymentAuth.instructed_amount.currency === currency;
  const isAmountValid = amount > 0 && amount <= paymentAuth.instructed_amount.value;

  if (!isDebtorValid || !isCreditorValid || !isCurrencyValid || !isAmountValid) {
    return res.status(403).json({
      error: 'insufficient_authorization_details',
      error_description: 'Requested execution exceeds granted authorization bounds',
    });
  }

  const result = await executeBankTransfer({ debtorIban, creditorIban, amount, currency });
  return res.status(200).json(result);
}
```

Recommended MCP Servers (mcp-serverlist.com)

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

Recommended Agent Skills (askills.dev)

Ready-to-use executable skill functions tailored to this stack.

Architectural Specification & Invariant Rationale

Architectural Invariant Design: OAuth 2.1 Rich Authorization Requests (RFC 9396) Fine-Grained Assertion Guardrail

OAuth 2.1 Rich Authorization Requests (RFC 9396) Fine-Grained Assertion Guardrail defines an industrial-grade behavioral standard for security engineering. Eliminates privilege escalation and confused deputy vulnerabilities by replacing coarse OAuth 2.0 scopes with RFC 9396 Rich Authorization Requests (RAR). Mandates cryptographically sender-constrained access token verification with explicit, transactional equality and threshold validation between API request parameters and token authorization_details payloads. 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: Authorizing High-Value Mutations with Coarse Scopes Instead of RFC 9396 authorization_details Assertions 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 DriftAuthorizing High-Value Mutations with Coarse Scopes Instead of RFC 9396 authorization_details AssertionsCritical
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

Services MUST NEVER rely solely on OAuth 2.0 string-based scopes (e.g., 'scope

Services MUST NEVER rely solely on OAuth 2.0 string-based scopes (e.g., 'scope: payment') for authorizing state-mutating, financial, or data-exfiltration-sensitive operations.

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

Services MUST extract, parse, and validate RFC 9396 `authorization_details` from verified access tokens using strict schema validators (e.g., Zod or TypeBox).

Services MUST extract, parse, and validate RFC 9396 `authorization_details` from verified access tokens using strict schema validators (e.g., Zod or TypeBox).

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 cryptographically assert that the token is sender-constrained using DPoP (RFC 9449) `jkt` thumbprint matching or mTLS client certificate binding (`x5t#S256`).

Services MUST cryptographically assert that the token is sender-constrained using DPoP (RFC 9449) `jkt` thumbprint matching or mTLS client certificate binding (`x5t#S256`).

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

Authorization logic MUST assert exact parameter matching or bounded sub-setting

Authorization logic MUST assert exact parameter matching or bounded sub-setting: request entity IDs, source accounts, destination accounts, currency, and numerical thresholds MUST match or fall strictly within the RAR payload.

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

Handlers MUST emit an OAuth 2.1 compliant error response with HTTP 403 Forbidden and error code `insufficient_authorization_details` when the request payload exceeds or mismatches authorization_details.

Handlers MUST emit an OAuth 2.1 compliant error response with HTTP 403 Forbidden and error code `insufficient_authorization_details` when the request payload exceeds or mismatches authorization_details.

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 treat an access token containing multiple `authorization_details` objects by locating the exact matching `type` descriptor and confirming that all required action parameters conform to that specific entry.

Services MUST treat an access token containing multiple `authorization_details` objects by locating the exact matching `type` descriptor and confirming that all required action parameters conform to that specific entry.

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 OAuth 2.1 Rich Authorization Requests (RFC 9396) Fine-Grained Assertion Guardrail critical for AI coding assistants?

Eliminates privilege escalation and confused deputy vulnerabilities by replacing coarse OAuth 2.0 scopes with RFC 9396 Rich Authorization Requests (RAR). Mandates cryptographically sender-constrained access token verification with explicit, transactional equality and threshold validation between API request parameters and token authorization_details payloads. 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 (Authorizing High-Value Mutations with Coarse Scopes Instead of RFC 9396 authorization_details Assertions) 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

OAuth