Skip to main content

OAuth vs Governance Policies

If you're coming from a traditional OAuth/OIDC background, you might wonder why AxonFlow has its own policy layer. Short answer: OAuth controls who can access the API. AxonFlow policies control what content and behavior is allowed.

These are orthogonal concerns. You need both.

Comparison

ConcernOAuth/OIDCAxonFlow Governance
"Can this service call the API?"Yes (identity verification)N/A (handled by auth)
"Can this response contain SSNs?"No (no content awareness)Yes (response-phase PII redaction)
"Can Tenant A's query return Tenant B's data?"No (scopes are coarse-grained)Yes (tenant-scoped connector policies)
"Can this team exceed $50/day in LLM spend?"NoYes (dynamic budget policies)
"Must PAN card blocking apply to all 12 teams?"No (no org hierarchy)Yes (org-tier policy cascading)
"Can a support agent query by SSN but not see SSN in response?"No (no phase awareness)Yes (phase-aware action_request/action_response)

"But We Already Use OAuth for Our LLM Calls"

OAuth protects the transport layer — it verifies the caller's identity and grants access to endpoints. AxonFlow governance protects the content layer — it evaluates what's inside requests and responses.

Both are needed because:

  • OAuth can't prevent an LLM from generating an SSN in its output. The LLM is a downstream service that produces arbitrary text. OAuth authenticates the caller but has no mechanism to scan or redact response content.
  • OAuth can't enforce different rules for request vs. response. A support agent needs to search by SSN (input) but the response must have SSN redacted (output). OAuth has no concept of phase-aware enforcement.
  • OAuth can't cascade rules across an organization. When you add a new team, they should automatically inherit org-level compliance policies. OAuth scopes are per-client, not hierarchical.

Request Lifecycle

Here's how both layers compose in a single request:

SDK Request


┌────────────────────────────┐
│ Layer 1: Identity (OAuth) │ Authorization: Basic base64(clientId:clientSecret)
│ │ → Reject if credentials are invalid
└──────────┬─────────────────┘


┌────────────────────────────┐
│ Layer 2: Input Policies │ Three-tier policy evaluation (system → org → tenant)
│ (Governance) │ → Block SQLi patterns, warn on PII in queries
└──────────┬─────────────────┘


┌────────────────────────────┐
│ LLM / MCP Execution │ The actual call to the model or connector
└──────────┬─────────────────┘


┌────────────────────────────┐
│ Layer 2: Output Policies │ Response-phase evaluation
│ (Governance) │ → Redact PII, enforce exfiltration limits
└──────────┬─────────────────┘


Response to SDK

Layer 1 (Identity) runs once at entry. Layer 2 (Governance) runs on both input and output.

When You Need What

OAuth Alone Is Sufficient When:

  • Single-tenant deployment with no compliance requirements
  • You trust all LLM outputs (no PII risk, no regulatory obligations)
  • No need for organizational policy hierarchy
  • No cost governance requirements

OAuth + AxonFlow Governance When:

  • Multi-tenant — different teams need different rules
  • Compliance requirements — PCI-DSS, HIPAA, SOX, RBI, or similar
  • Response scanning — PII must be detected and redacted in LLM/connector outputs
  • Organizational policy inheritance — org-level rules must cascade to all tenants automatically
  • Cost governance — per-team budget caps with org-wide limits
  • Phase-aware enforcement — different actions for request vs. response (e.g., query by SSN allowed, SSN in response redacted)

Concrete Example: Support Agent Workflow

A support agent needs to look up a customer by SSN but must never see the raw SSN in the response.

With OAuth only:

Agent authenticates → Queries "find customer SSN 123-45-6789" → Gets back full SSN in response

OAuth has no mechanism to redact the SSN from the response.

With OAuth + AxonFlow governance:

Agent authenticates (OAuth)
→ Input policy: PII detected (sys_pii_ssn), action_request = warn → ALLOWED (logged)

Connector returns: { "name": "John Doe", "ssn": "123-45-6789", "email": "[email protected]" }

→ Output policy: PII detected (sys_pii_ssn), action_response = redact
→ Response: { "name": "John Doe", "ssn": "***-**-6789", "email": "j***@example.com" }

The agent found the customer. The SSN was never exposed. The query was audit-logged.