JWT & Security Context
How JWT tokens from your identity provider are converted into MACAW security contexts. This conversion is the foundation of user-specific policy enforcement.
JWT to Security Context Conversion
When your application passes a JWT token, the Identity Bridge extracts claims and maps them to MACAW's hierarchical security context:
{
"sub": "alice@fintech.com",
"email": "alice@fintech.com",
"organization": "FinTech Corp",
"business_unit": "Analytics",
"team": "Reporting",
"roles": ["analyst"],
"exp": 1700000000
}{
"company": "FinTech Corp",
"business_unit": "Analytics",
"team": "Reporting",
"user": "alice@fintech.com",
"roles": ["analyst"]
}Policy Resolution Chain
The security context flows through the policy resolver for hierarchical lookup:
security_context = {
"company": "FinTech Corp",
"business_unit": "Analytics",
"team": "Reporting",
"user": "alice@fintech.com",
"roles": ["analyst"]
}
Lookup Chain:
1. base:role:analyst → GPT-3.5, 500 tokens (starting point)
2. restrict:org:fintech-corp → No secrets, audit required
3. restrict:bu:analytics → Low temperature, consistency mode
4. restrict:team:reporting → 9-6 EST only, specific data sources
5. filter:clearance:standard → No executive data access
Final Policy (Most Restrictive):
- Model: GPT-3.5 ONLY
- Tokens: 500 MAX
- Hours: 9-6 EST
- Data: Standard clearance only
- Audit: Full logging requiredImplementation
The conversion happens automatically in the MACAW Client layer. Applications just pass the JWT token:
from macaw_adapters.openai import SecureOpenAI
# Initialize adapter with your app
client = SecureOpenAI(app_name="financial-analyzer")
# Pass JWT token from your identity provider
# (MACAW handles the conversion internally)
response = client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": "Analyze Q4 report"}],
jwt_token=alice_jwt # JWT from Keycloak/Okta/Azure AD
)
# Behind the scenes:
# 1. JWT validated and claims extracted
# 2. Claims mapped via .claims-config.yaml
# 3. security_context created
# 4. Hierarchical policy lookup
# 5. Constraints applied (may downgrade model)
# 6. Request executed with Alice's permissionsMulti-User Safety
The key security property: no identity bleed possible. Each request creates a fresh security context from its JWT:
Concurrent Multi-User Safety:
────────────────────────────
Time T1: Alice's Request
┌─────────────┐ alice_jwt ┌─────────────────┐ security_context ┌─────────────────┐
│ Alice │────────────▶│ Shared │───────────────────▶│ Alice's policies│
│ Financial │ │ Orchestrator │ │ applied │
│ Request │ │ │ │ │
└─────────────┘ │ Each request │ └─────────────────┘
│ creates fresh │
Time T2: Bob's Request │ security_context│
┌─────────────┐ bob_jwt │ │ security_context ┌─────────────────┐
│ Bob │────────────▶│ Same Instance! │───────────────────▶│ Bob's policies │
│ Analysis │ │ │ │ applied │
│ Request │ │ NO STORED STATE │ │ │
└─────────────┘ └─────────────────┘ └─────────────────┘
Key: NO identity bleed possible - each request is isolatedStateless Design
- • No shared state between requests
- • Per-request context creation
- • Isolated processing per thread
- • Clean separation of concerns
Concurrent Safety Proof
Even if 1000 users hit the same orchestrator simultaneously, each request gets its own security_context derived from its own JWT, preventing any possibility of identity bleed.
Claim Mapping
Different identity providers use different claim names. The Claims Mapper handles this translation via .claims-config.yaml:
| Provider | Org Claim → company | User Claim → user |
|---|---|---|
| Keycloak | organization | |
| Okta | companyName | |
| Azure AD | companyName | userPrincipalName |
| Google Workspace | hd (hosted domain) |
See Claims Mapping for complete configuration details.