After JWT validation, gateway injects identity headers into proxied requests so downstream services get audit trail without parsing JWTs themselves.
Headers
X-Forwarded-User: rock # from sub claim
X-Forwarded-Roles: llm:inference # from roles or permissions claim
X-Acting-Service: portfolio-agent # from azp claim (only for service accounts)
X-Auth-Verified: true # gateway validated the JWT
Why
Downstream services (memory, SQS) need to know WHO is calling for audit and authorization
Downstream should NOT need JWKS/JWT validation logic — gateway already did it
Network policy guarantees only gateway can reach downstream, so headers are trustworthy
Enables per-user audit logging at downstream without coupling to Authentik
Acceptance Criteria
Headers injected after successful JWT validation
X-Forwarded-User set from sub claim
X-Forwarded-Roles set from roles or permissions claim (comma-separated)
X-Acting-Service set from azp claim (omitted if same as sub)
X-Auth-Verified: true always set when JWT passed validation
Incoming X-Forwarded-User / X-Auth-Verified stripped from client request (anti-spoofing)
Unauthenticated requests (no JWT) do NOT get these headers
Unit tests: header injection, header stripping, claim extraction edge cases
Implementation
In proxy.go ServeHTTP, after JWT validation block
Strip incoming spoofed headers before routing
Security contract
Downstream MUST verify X-Auth-Verified: true before trusting other X-Forwarded- headers.* If header is absent, request was not authenticated at gateway (e.g. health checks, pre-auth endpoints).
Review checklist
Incoming X-Forwarded-User stripped before injection (no client spoofing)
X-Auth-Verified only set after real JWT validation (never unconditionally)
Wildcard permissions ("") not expanded in header — passed as literal ""
Empty claims handled gracefully (no empty header values)
## Summary
After JWT validation, gateway injects identity headers into proxied requests so downstream services get audit trail without parsing JWTs themselves.
## Headers
```
X-Forwarded-User: rock # from sub claim
X-Forwarded-Roles: llm:inference # from roles or permissions claim
X-Acting-Service: portfolio-agent # from azp claim (only for service accounts)
X-Auth-Verified: true # gateway validated the JWT
```
## Why
- Downstream services (memory, SQS) need to know WHO is calling for audit and authorization
- Downstream should NOT need JWKS/JWT validation logic — gateway already did it
- Network policy guarantees only gateway can reach downstream, so headers are trustworthy
- Enables per-user audit logging at downstream without coupling to Authentik
## Acceptance Criteria
- [ ] Headers injected after successful JWT validation
- [ ] `X-Forwarded-User` set from `sub` claim
- [ ] `X-Forwarded-Roles` set from `roles` or `permissions` claim (comma-separated)
- [ ] `X-Acting-Service` set from `azp` claim (omitted if same as sub)
- [ ] `X-Auth-Verified: true` always set when JWT passed validation
- [ ] Incoming `X-Forwarded-User` / `X-Auth-Verified` stripped from client request (anti-spoofing)
- [ ] Unauthenticated requests (no JWT) do NOT get these headers
- [ ] Unit tests: header injection, header stripping, claim extraction edge cases
## Implementation
- In `proxy.go` ServeHTTP, after JWT validation block
- Strip incoming spoofed headers before routing
## Security contract
**Downstream MUST verify `X-Auth-Verified: true` before trusting other X-Forwarded-* headers.** If header is absent, request was not authenticated at gateway (e.g. health checks, pre-auth endpoints).
## Review checklist
- [ ] Incoming X-Forwarded-User stripped before injection (no client spoofing)
- [ ] X-Auth-Verified only set after real JWT validation (never unconditionally)
- [ ] Wildcard permissions ("*") not expanded in header — passed as literal "*"
- [ ] Empty claims handled gracefully (no empty header values)
rock
added this to the Phase 3: OAuth2 Token Exchange & Identity Propagation milestone 2026-09-08 03:55:45 +00:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
After JWT validation, gateway injects identity headers into proxied requests so downstream services get audit trail without parsing JWTs themselves.
Headers
Why
Acceptance Criteria
X-Forwarded-Userset fromsubclaimX-Forwarded-Rolesset fromrolesorpermissionsclaim (comma-separated)X-Acting-Serviceset fromazpclaim (omitted if same as sub)X-Auth-Verified: truealways set when JWT passed validationX-Forwarded-User/X-Auth-Verifiedstripped from client request (anti-spoofing)Implementation
proxy.goServeHTTP, after JWT validation blockSecurity contract
Downstream MUST verify
X-Auth-Verified: truebefore trusting other X-Forwarded- headers.* If header is absent, request was not authenticated at gateway (e.g. health checks, pre-auth endpoints).Review checklist