rmcp_openapi/security/
observer.rs1use crate::config::Authorization;
2use tracing::{debug, trace, warn};
3
4pub struct SecurityObserver<'a> {
6 authorization: &'a Authorization,
7}
8
9impl<'a> SecurityObserver<'a> {
10 pub fn new(authorization: &'a Authorization) -> Self {
12 Self { authorization }
13 }
14
15 pub fn observe_request(&self, operation_id: &str, has_auth: bool, requires_auth: bool) {
17 match self.authorization {
18 Authorization::None if has_auth => {
19 debug!(
20 operation_id,
21 "Authorization header stripped (MCP-compliant mode)"
22 );
23 }
24 #[cfg(feature = "authorization-token-passthrough")]
25 Authorization::PassthroughWarn(_) if has_auth => {
26 debug!(
27 operation_id,
28 "Forwarding Authorization header (passthrough mode)"
29 );
30 }
31 #[cfg(feature = "authorization-token-passthrough")]
32 Authorization::PassthroughSilent(_) => {
33 trace!(operation_id, has_auth, "Processing request");
34 }
35 _ => {
36 trace!(operation_id, has_auth, requires_auth, "Processing request");
37 }
38 }
39
40 if requires_auth && !has_auth {
42 warn!(
43 operation_id,
44 "OpenAPI spec requires auth but no Authorization header present"
45 );
46 }
47 }
48
49 pub fn log_startup(&self) {
51 match self.authorization {
52 Authorization::None => {
53 tracing::info!("Authorization mode: compliant (headers will not be forwarded)");
54 }
55 #[cfg(feature = "authorization-token-passthrough")]
56 Authorization::PassthroughWarn(_) => {
57 tracing::warn!(
58 "Authorization mode: passthrough (non-MCP-compliant) - \
59 Authorization headers WILL be forwarded to backend APIs. See SECURITY.md"
60 );
61 }
62 #[cfg(feature = "authorization-token-passthrough")]
63 Authorization::PassthroughSilent(_) => {
64 tracing::info!("Authorization mode: passthrough-silent");
65 }
66 }
67 }
68}