🏀

CourtEdge ProGear

Architecture & Security Overview

Back to Chat
SUCCESSToken Grant
published: 2025-12-18T17:29:13.031Z
eventType: app.oauth2.as.token.grant.access_token
outcome.result: SUCCESS ← Governance decision
actor.displayName: ProGear Sales Agent ← AI Agent
actor.id: wlp8x5q7mvH86KvFJ0g7
target.displayName: Sarah Sales ← Acting on behalf of
target.alternateId: sarah.sales@progear.demo
authorizationServer: ProGear Inventory MCP ← Resource being accessed
requestedScopes: inventory:read
grantedScopes: inventory:read ← Access granted
FAILUREPolicy Denied
published: 2025-12-18T17:25:30.227Z
eventType: app.oauth2.as.token.grant
outcome.result: FAILURE ← Governance decision
outcome.reason: no_matching_policy ← Policy blocked this request
actor.displayName: ProGear Sales Agent ← Same AI Agent
actor.id: wlp8x5q7mvH86KvFJ0g7
target.subject: 00u8xdeptoh4cK9pG0g7 (Sarah Sales) ← Same user
authorizationServer: ProGear Inventory MCP
requestedScopes: inventory:write ← Write access denied
grantedScopes: (none)
1USER AUTHENTICATED
Sarah Sales
Logged in via Okta OIDC • Has ID Token
sub: 00u8xdeptoh4cK9pG0g7
2USER REQUEST
"Our customer State University wants to order 1500 basketballs. Can we fulfill that and what would the pricing look like?"
3LANGGRAPH ORCHESTRATOR(routing only — no security boundary)
Analyzes Request & Determines Required MCPs
LangGraph decides what's needed → Okta decides what's allowed
Inventory Customer Pricing Sales
4PROGEAR SALES AGENT — ID-JAG TOKEN EXCHANGEOkta Governance
ProGear Sales Agent
Okta AI Agent • wlp8x5q7mvH86KvFJ0g7
For each MCP selected by LangGraph, Okta evaluates access:
User ID TokenID-JAG Inventory Auth Server Token
Example: ProGear Inventory Auth Server Token (Granted)
sub: 00u8xdeptoh4cK9pG0g7 Sarah Sales
actor.sub: wlp8x5q7mvH86KvFJ0g7 ← AI Agent identity
aud: api://progear-inventory ← Target MCP
scope: inventory:read ← Granted by Okta policy
iat: 1771443478 ← Issued at
exp: 1771447078 ← Expires in 1hr
5AGENT CALLS MCPS WITH GRANTED TOKENS
Example: Inventory MCP Call
→ Request to MCP
GET /api/inventory/stock?product=basketball&qty=1500
Authorization: Bearer eyJhbGciOiJSUzI1...
↑ Inventory Auth Server Token from Step 4 (contains sub, actor.sub, scope)
MCP Validates Token
Signature valid (Okta-signed)
aud = api://progear-inventory
scope includes inventory:read
Token not expired
← Response from MCP
200 OK
{ "available": 2340, "canFulfill": true }
✓ All responses aggregated and returned to user
The Problem ID-JAG Solves

The user authenticated to the Main Auth Server and got an ID Token.

But each MCP has its own Authorization Server with its own access policies.

The MCP Auth Server did not issue that ID Token. It cannot just trust it directly.

The Solution: ID-JAG as a Bridge

The ID-JAG (Identity Assertion JWT Authorization Grant) is a cryptographically signed "letter of introduction" from the Main Auth Server to the MCP Auth Server:

"I authenticated this user. I verified this agent. Here is a signed token binding them together, addressed specifically to you. Now YOU apply YOUR policies."

Two Authorization Servers
Main Auth Server
Your Okta org / default
Issues ID Tokens (OIDC login)
Validates agent JWT assertion
Step 1: ID Token → ID-JAG
Target Auth Server
MCP / Resource / 3rd Party SaaS
Validates ID-JAG signature
Applies its own access policies
Step 2: ID-JAG → Access Token
ID-JAG Token
The ID-JAG bridges trust between authorization servers
Same Tenant
Internal MCP Auth Server
e.g., aus...inventory in your Okta org
Partner Tenant
Federated Auth Server
e.g., Partner company's Okta org
3rd Party SaaS
External Service Auth
e.g., Salesforce, ServiceNow, Workday
Key insight: The ID-JAG pattern works across trust boundaries. The target auth server does not need to be in your Okta tenant. It just needs to trust the ID-JAG signature from your Main Auth Server.
id-jag-token-exchange.sequence
👤User🤖AI Agent🔐Main Auth🎯Target Auth🛡️MCP API1OIDC LoginID Token2ID Token + Agent JWTID-JAG Token3ID-JAG + Agent JWT + scopesPolicy Check ✓Access Token (scoped)4API Call + Bearer Token200 OK • Inventory Data
ID Token
sub: 00u8xdeptoh4cK9pG0g7
aud: frontend-app
iss: main-auth-server
User identity only
ID-JAG Token
sub: 00u8xdeptoh4cK9pG0g7
act.sub: wlp...agent
aud: mcp-auth-server
Bridges user + agent to target
Access Token
sub: 00u8xdeptoh4cK9pG0g7
act.sub: wlp...agent
scp: inventory:read
Policy-granted scopes
Why Two Authorization Servers?
Each MCP has its own auth server with its own access policies. This separation allows fine-grained control: the Inventory MCP can have different policies than the Pricing MCP. The ID-JAG securely carries the user+agent identity across this boundary so each MCP auth server can make independent authorization decisions.

Key insight: The same AI Agent (wlp...) receives different scopes based on which user is logged in. Okta policies evaluate the user's group membership to determine what the agent can do on their behalf.

Sarah Sales
Sales Representative
Groups
ProGear-Sales
MCP Access Token Claims
sub: sarah.sales@progear.demo
actor.sub: wlp8x5q7mvH86KvFJ0g7
aud: api://progear-inventory
Granted Scopes
inventory:read
inventory:write
pricing:read
pricing:margin
Read-only access
Can view data but cannot modify inventory or see margins
Mike Manager
Sales Manager
Groups
ProGear-SalesProGear-Managers
MCP Access Token Claims
sub: mike.manager@progear.demo
actor.sub: wlp8x5q7mvH86KvFJ0g7
aud: api://progear-inventory
Granted Scopes
inventory:read
inventory:write
pricing:read
pricing:margin
Full read/write access
Can modify inventory and view profit margins
Same AI Agent • Different Permissions
Notice actor.sub is identical in both tokens — it's the same AI agent. But the granted scopes differ based on the user's group membership. This is Okta's governance in action.
CourtEdge ProGear - Powered by Okta AI Agent Governance