ADR-045: Authentication and Authorization Remain in CoreΒΆ
- Status: Proposed
- Date: 2026-03-15
- Deciders: Platform Team
- Related: Modular Runtime Architecture, ADR-004
ContextΒΆ
The modular gateway architecture introduces protocol modules that can be implemented in different languages and run as separate processes. A key question is whether authentication and authorization logic should be duplicated in each module or centralized in the core platform.
ContextForge implements a two-layer security model:
- Token Scoping (Layer 1):
normalize_token_teams()inmcpgateway/auth.pycontrols what resources a caller can see. - RBAC (Layer 2):
PermissionServicecontrols what actions a caller can perform.
Both layers are security-critical and have non-trivial edge cases (admin bypass, public-only tokens, team hierarchy resolution).
DecisionΒΆ
Authentication and authorization never move into modules. The core platform remains the single source of truth for:
- JWT verification and token scoping (
normalize_token_teams()). - RBAC permission checks (
PermissionService). - SSO provider integration (GitHub, Google, Okta, Keycloak, Entra ID, generic OIDC).
- Token revocation checks.
- Rate limiting.
Modules consume auth through a core-owned auth and policy SPI. The exact RPC or method names are intentionally left open, but the contract must support:
- resolving a caller into a typed authenticated context
- checking permissions against that context
- preserving token-scoped visibility and deny-path behavior
Modules receive authenticated context or permission outcomes from the core and pass that context through subsequent core SPI calls as needed.
ConsequencesΒΆ
PositiveΒΆ
- Security-critical code has a single implementation β no drift between module auth implementations.
- Simplifies security auditing β one codebase to review, not N per module.
- Modules in any language get the full auth stack without reimplementing it.
- Consistent behavior across all protocols (MCP, A2A, LLM, REST).
NegativeΒΆ
- Every module request that needs auth must make at least one call or cacheable check against the core-owned auth boundary.
- Auth logic cannot be freely reimplemented per protocol without risking policy drift.
NeutralΒΆ
- Auth caching at the core level (ADR-028) can amortize the cost of repeated checks.
- The current Rust MCP runtime already demonstrates this pattern in practice.
ReferencesΒΆ
- Modular Runtime Architecture
mcpgateway/auth.pyβnormalize_token_teams(), single source of truth- ADR-043