mirror of
https://github.com/block/buzz.git
synced 2026-10-27 12:40:30 +00:00
fix(nip11): advertise auth_required: true to match actual enforcement (#556)
Signed-off-by: Tyler Longwell <109685178+tlongwell-block@users.noreply.github.com>
This commit is contained in:
@@ -39,7 +39,8 @@ pub struct Config {
|
||||
pub send_buffer_size: usize,
|
||||
/// Authentication provider configuration.
|
||||
pub auth: sprout_auth::AuthConfig,
|
||||
/// Whether clients must authenticate via NIP-42 before sending events.
|
||||
/// Whether REST API requests must present a valid token. Independent of
|
||||
/// WebSocket protocol auth, which is *always* required by REQ/EVENT/COUNT.
|
||||
pub require_auth_token: bool,
|
||||
/// Comma-separated list of allowed CORS origins.
|
||||
/// If empty, permissive CORS is used (dev mode).
|
||||
@@ -197,8 +198,8 @@ impl Config {
|
||||
|
||||
if !require_auth_token {
|
||||
warn!(
|
||||
"SPROUT_REQUIRE_AUTH_TOKEN is false — relay accepts unauthenticated connections. \
|
||||
Set to true for production."
|
||||
"SPROUT_REQUIRE_AUTH_TOKEN is false — REST API requests bypass token auth. \
|
||||
WebSocket protocol auth is unaffected. Set to true for production."
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,8 @@ pub struct RelayLimitation {
|
||||
pub max_subid_length: Option<u32>,
|
||||
/// Minimum proof-of-work difficulty required for events.
|
||||
pub min_pow_difficulty: Option<u32>,
|
||||
/// Whether NIP-42 authentication is required before sending events.
|
||||
/// Whether NIP-42 authentication is required before subscribing or
|
||||
/// publishing events.
|
||||
pub auth_required: bool,
|
||||
/// Whether payment is required to use the relay.
|
||||
pub payment_required: bool,
|
||||
@@ -56,12 +57,32 @@ pub struct RelayLimitation {
|
||||
pub restricted_writes: bool,
|
||||
}
|
||||
|
||||
/// Canonical `RelayLimitation` advertised by this relay.
|
||||
///
|
||||
/// `auth_required` is always `true`: the REQ, EVENT, and COUNT handlers
|
||||
/// unconditionally reject connections that are not in
|
||||
/// `AuthState::Authenticated`. This is independent of the REST API token
|
||||
/// toggle (`config.require_auth_token`).
|
||||
fn relay_limitation() -> RelayLimitation {
|
||||
RelayLimitation {
|
||||
max_message_length: Some(MAX_FRAME_BYTES as u64),
|
||||
max_subscriptions: Some(1024),
|
||||
max_filters: Some(10),
|
||||
max_limit: Some(10_000),
|
||||
max_subid_length: Some(256),
|
||||
min_pow_difficulty: None,
|
||||
auth_required: true,
|
||||
payment_required: false,
|
||||
restricted_writes: true,
|
||||
}
|
||||
}
|
||||
|
||||
impl RelayInfo {
|
||||
/// Builds a `RelayInfo` document from the relay's runtime config.
|
||||
/// Builds the relay's NIP-11 information document.
|
||||
///
|
||||
/// `relay_pubkey` is the relay's own signing pubkey (hex), advertised as the
|
||||
/// NIP-11 `self` field for NIP-43 membership verification.
|
||||
pub fn from_config(config: &crate::config::Config, relay_pubkey: Option<&str>) -> Self {
|
||||
pub fn build(relay_pubkey: Option<&str>) -> Self {
|
||||
Self {
|
||||
name: "Sprout Relay".to_string(),
|
||||
description: "Sprout — private team communication relay".to_string(),
|
||||
@@ -70,17 +91,7 @@ impl RelayInfo {
|
||||
supported_nips: SUPPORTED_NIPS.to_vec(),
|
||||
software: "https://github.com/sprout-rs/sprout".to_string(),
|
||||
version: env!("CARGO_PKG_VERSION").to_string(),
|
||||
limitation: Some(RelayLimitation {
|
||||
max_message_length: Some(MAX_FRAME_BYTES as u64),
|
||||
max_subscriptions: Some(1024),
|
||||
max_filters: Some(10),
|
||||
max_limit: Some(10_000),
|
||||
max_subid_length: Some(256),
|
||||
min_pow_difficulty: None,
|
||||
auth_required: config.require_auth_token,
|
||||
payment_required: false,
|
||||
restricted_writes: true,
|
||||
}),
|
||||
limitation: Some(relay_limitation()),
|
||||
relay_self: relay_pubkey.map(|s| s.to_string()),
|
||||
}
|
||||
}
|
||||
@@ -97,10 +108,7 @@ pub async fn relay_info_handler(
|
||||
} else {
|
||||
None
|
||||
};
|
||||
axum::response::Json(RelayInfo::from_config(
|
||||
&state.config,
|
||||
relay_pubkey.as_deref(),
|
||||
))
|
||||
axum::response::Json(RelayInfo::build(relay_pubkey.as_deref()))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -129,6 +137,15 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn auth_required_is_advertised_true() {
|
||||
// REQ, EVENT, and COUNT all unconditionally require
|
||||
// `AuthState::Authenticated` (see `crates/sprout-relay/src/handlers/`).
|
||||
// The NIP-11 doc must reflect that or clients (e.g. the desktop pair
|
||||
// flow) misroute unauthenticated peers.
|
||||
assert!(relay_limitation().auth_required);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn supported_nips_are_sorted() {
|
||||
let mut sorted = SUPPORTED_NIPS.to_vec();
|
||||
|
||||
@@ -160,7 +160,7 @@ async fn nip11_or_ws_handler(
|
||||
};
|
||||
|
||||
if accept.contains("application/nostr+json") {
|
||||
let info = RelayInfo::from_config(&state.config, relay_pubkey.as_deref());
|
||||
let info = RelayInfo::build(relay_pubkey.as_deref());
|
||||
return Json(info).into_response();
|
||||
}
|
||||
|
||||
@@ -179,7 +179,7 @@ async fn nip11_or_ws_handler(
|
||||
}
|
||||
}
|
||||
// Not a WS request and not asking for nostr+json — serve NIP-11 as fallback.
|
||||
let info = RelayInfo::from_config(&state.config, relay_pubkey.as_deref());
|
||||
let info = RelayInfo::build(relay_pubkey.as_deref());
|
||||
Json(info).into_response()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -605,12 +605,12 @@ async fn test_nip11_relay_info() {
|
||||
Some(1024),
|
||||
"limitation.max_subscriptions must be 1024"
|
||||
);
|
||||
assert!(
|
||||
limitation
|
||||
.get("auth_required")
|
||||
.and_then(|v| v.as_bool())
|
||||
.is_some(),
|
||||
"limitation.auth_required must be a boolean"
|
||||
// The REQ, EVENT, and COUNT handlers unconditionally require an
|
||||
// authenticated connection, so the NIP-11 doc must advertise that.
|
||||
assert_eq!(
|
||||
limitation.get("auth_required").and_then(|v| v.as_bool()),
|
||||
Some(true),
|
||||
"limitation.auth_required must be true — REQ/EVENT/COUNT require NIP-42 auth"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user