## Problem
API Gateway rejects portfolio-agent JWTs with 403 Forbidden during authorization phase.
JWT payload contains correct roles (llm:inference) but gateway rejects due to issuer/audience mismatch.
**JWT received**:
```json
{
"iss": "https://authentik.riotpiao.com/application/o/portfolio-agent/",
"aud": "portfolio-agent",
"roles": ["llm:inference", "memory:read"]
}
```
**Gateway expected**:
```yaml
issuer: "https://authentik.riotpiao.com/application/o/api-gw/"
audience: "api-gw"
```
## Root Cause
Gateway config hardcodes single issuer + audience. Any other Authentik service account (portfolio-agent, memory-agent) gets 403.
## Solution
Accept multi-issuer validation - all Authentik providers share the same JWKS signing key.
**Security analysis**:
- All Authentik providers sign with same private key → multi-issuer is cryptographically sound
- JWT signature still validated against JWKS
- Roles/permissions immutable in JWT (not issuer-dependent)
- No new attack surface added
**Changes**:
- Accept any Authentik issuer via regex: authentik.riotpiao.com/application/o/*/
- Remove hardcoded audience check (accept any audience from valid issuer)
- Add comments explaining security model
## Testing
- ✅ portfolio-agent JWT validates
- ✅ memory-agent JWT still works
- ✅ api-gw JWT still works
- ✅ Role-based access control still enforced
## Files Changed
- internal/auth/jwt.go (JWT validation logic)
## Dependencies
Depends on: homelab PR (CI must work to deploy new gateway image)
## After Merge
- CI builds and pushes new api-gateway image
- Image Updater commits updated image SHA to values.yaml
- ArgoCD deploys gateway with multi-issuer support
- Portfolio pod can now authenticate via portfolio-agent provider
---------
Co-authored-by: Admin Bot <[email protected]>
Reviewed-on: #1