Do not include WWW-Authenticate headers on API responses (fixes #1795)

This commit is contained in:
mdecimus
2025-07-14 15:30:09 +02:00
parent 6568d61927
commit fccc25fb71
2 changed files with 38 additions and 26 deletions

View File

@@ -273,20 +273,32 @@ impl ToManageHttpResponse for &trc::Error {
}
}
.into_http_response(),
trc::EventType::Auth(trc::AuthEvent::Failed) => {
HttpResponse::new(StatusCode::UNAUTHORIZED)
.with_header(header::WWW_AUTHENTICATE, "Bearer realm=\"Stalwart Server\"")
.with_header(header::WWW_AUTHENTICATE, "Basic realm=\"Stalwart Server\"")
.with_content_type("application/problem+json")
.with_text_body(
serde_json::to_string(&RequestError::unauthorized()).unwrap_or_default(),
)
}
trc::EventType::Auth(
trc::AuthEvent::Failed | trc::AuthEvent::Error | trc::AuthEvent::TokenExpired,
) => HttpResponse::unauthorized(true),
_ => self.to_request_error().into_http_response(),
}
}
}
pub trait UnauthorizedResponse {
fn unauthorized(include_realms: bool) -> Self;
}
impl UnauthorizedResponse for HttpResponse {
fn unauthorized(include_realms: bool) -> Self {
(if include_realms {
HttpResponse::new(StatusCode::UNAUTHORIZED)
.with_header(header::WWW_AUTHENTICATE, "Bearer realm=\"Stalwart Server\"")
.with_header(header::WWW_AUTHENTICATE, "Basic realm=\"Stalwart Server\"")
} else {
HttpResponse::new(StatusCode::UNAUTHORIZED)
})
.with_content_type("application/problem+json")
.with_text_body(serde_json::to_string(&RequestError::unauthorized()).unwrap_or_default())
}
}
impl ManagementApiError<'_> {
fn into_http_response(self) -> HttpResponse {
JsonResponse::new(self).into_http_response()

View File

@@ -4,8 +4,21 @@
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
*/
use std::{net::IpAddr, sync::Arc};
use crate::{
HttpSessionManager,
auth::{
authenticate::{Authenticator, HttpHeaders},
oauth::{
FormData, auth::OAuthApiHandler, openid::OpenIdHandler,
registration::ClientRegistrationHandler, token::TokenHandler,
},
},
autoconfig::Autoconfig,
form::FormHandler,
management::{
ManagementApi, ToManageHttpResponse, UnauthorizedResponse, troubleshoot::TroubleshootApi,
},
};
use common::{
Inner, KV_ACME, Server,
auth::{AccessToken, oauth::GrantType},
@@ -40,24 +53,11 @@ use jmap_proto::{
request::{Request, capability::Session},
types::{blob::BlobId, id::Id},
};
use std::{net::IpAddr, sync::Arc};
use store::dispatch::lookup::KeyValue;
use trc::SecurityEvent;
use utils::url_params::UrlParams;
use crate::{
HttpSessionManager,
auth::{
authenticate::{Authenticator, HttpHeaders},
oauth::{
FormData, auth::OAuthApiHandler, openid::OpenIdHandler,
registration::ClientRegistrationHandler, token::TokenHandler,
},
},
autoconfig::Autoconfig,
form::FormHandler,
management::{ManagementApi, ToManageHttpResponse, troubleshoot::TroubleshootApi},
};
pub trait ParseHttp: Sync + Send {
fn parse_http_request(
&self,
@@ -427,7 +427,7 @@ impl ParseHttp for Server {
(Some("troubleshoot"), _, Some(token)) => {
(GrantType::Troubleshoot, token)
}
_ => return Err(err),
_ => return Ok(HttpResponse::unauthorized(false)),
};
let token_info =
self.validate_access_token(grant_type.into(), token).await?;