From 20d08f6c7ca386f666e67be44b8d8cf957c30781 Mon Sep 17 00:00:00 2001 From: Stanislaw Grams Date: Fri, 13 Feb 2026 08:39:05 +0100 Subject: [PATCH] [feat](trx-frontend-http): allow unrestricted RX access when rx_passphrase not set When HTTP auth is enabled but rx_passphrase is not configured, allow unauthenticated users to access read-only endpoints (status, events, decode, audio) without authentication. This enables monitoring-only access while protecting TX control with a passphrase. Changes: - AuthMiddleware: Skip auth check for read routes when rx_passphrase is None - session_status: Grant rx role to unauthenticated users when no rx passphrase required Use case: Set only control_passphrase to protect TX/PTT while allowing anyone on the network to monitor the radio. Co-Authored-By: Claude Opus 4.6 Signed-off-by: Stanislaw Grams --- .../trx-frontend-http/src/auth.rs | 37 ++++++++++++++++--- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/src/trx-client/trx-frontend/trx-frontend-http/src/auth.rs b/src/trx-client/trx-frontend/trx-frontend-http/src/auth.rs index cb582c4..0666a59 100644 --- a/src/trx-client/trx-frontend/trx-frontend-http/src/auth.rs +++ b/src/trx-client/trx-frontend/trx-frontend-http/src/auth.rs @@ -360,13 +360,27 @@ pub async fn session_status( } let session_id = extract_session_id(&req); - let role = session_id - .and_then(|sid| auth_state.store.get(&sid)) - .map(|r| r.role.as_str().to_string()); + if let Some(session_record) = session_id.and_then(|sid| auth_state.store.get(&sid)) { + // User has valid session + return Ok(HttpResponse::Ok().json(SessionStatus { + authenticated: true, + role: Some(session_record.role.as_str().to_string()), + })); + } + // No session - check if rx access is unrestricted + if auth_state.config.rx_passphrase.is_none() { + // No rx passphrase required - grant rx role to unauthenticated users + return Ok(HttpResponse::Ok().json(SessionStatus { + authenticated: false, + role: Some("rx".to_string()), + })); + } + + // Auth required but no valid session Ok(HttpResponse::Ok().json(SessionStatus { - authenticated: role.is_some(), - role, + authenticated: false, + role: None, })) } @@ -501,6 +515,19 @@ where // Auth enabled - check role let role = get_session_role(req.request(), &auth_state); + // If rx_passphrase is not set, allow unauthenticated read access + let allow_unrestricted_read = auth_state.config.rx_passphrase.is_none(); + let is_read_route = access == RouteAccess::Read; + + if is_read_route && allow_unrestricted_read { + // No rx authentication required - allow read access without role + let fut = self.service.call(req); + return Box::pin(async move { + let res = fut.await?; + Ok(res) + }); + } + if !access.allows(role) { // Access denied - return 401/403 return Box::pin(async move {