fix(m7.1): correct middleware layer order so JwksState is visible
CI / Check (pull_request) Successful in 11m31s
CI / Detect Changes (pull_request) Has been skipped
CI / Deploy Agent (pull_request) Has been skipped
CI / Deploy Dashboard (pull_request) Has been skipped
CI / Deploy Docs (pull_request) Has been skipped
CI / Deploy MCP (pull_request) Has been skipped

Axum applies layers outermost-first. With the previous ordering
(`Extension(jwks_state)` first, `require_jwt_auth` last), the JWT
middleware ran before the Extension layer attached `JwksState` to
the request, so `request.extensions().get::<JwksState>()` always
returned None and the middleware silently passed through every
request as if Keycloak weren't configured.

Verified end-to-end against the local CERTifAI Keycloak realm:
- no token / bad token -> 401
- active / trial -> 200 read, write reaches handler
- frozen -> 200 read, 402 on writes
- archived -> 410 on every method

The bug was invisible to the unit + integration tests because they
construct the layer stack manually; only the live wiring exhibited it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Sharang Parnerkar
2026-05-20 17:20:37 +02:00
parent 05c01ea547
commit cb7b1b86f5
+8 -3
View File
@@ -8,7 +8,7 @@ use tower_http::set_header::SetResponseHeaderLayer;
use tower_http::trace::TraceLayer;
use crate::agent::ComplianceAgent;
use crate::api::auth_middleware::{require_jwt_auth, JwksState};
use crate::api::auth_middleware::{require_jwt_auth, require_tenant_status, JwksState};
use crate::api::routes;
use crate::error::AgentError;
@@ -44,9 +44,14 @@ pub async fn start_api_server(agent: ComplianceAgent, port: u16) -> Result<(), A
jwks_url,
};
tracing::info!("Keycloak JWT auth enabled for realm '{kc_realm}'");
// Layers execute outermost-first. The Extension must run before
// require_jwt_auth so that middleware can read JwksState from
// request extensions, and the status gate must run after the
// JWT auth so TenantContext is in extensions.
app = app
.layer(Extension(jwks_state))
.layer(middleware::from_fn(require_jwt_auth));
.layer(middleware::from_fn(require_tenant_status))
.layer(middleware::from_fn(require_jwt_auth))
.layer(Extension(jwks_state));
} else {
tracing::warn!("Keycloak not configured - API endpoints are unprotected");
}