forked from coracle/caravel
62 lines
1.9 KiB
Rust
62 lines
1.9 KiB
Rust
use anyhow::{Result, anyhow};
|
|
use base64::Engine;
|
|
use base64::engine::general_purpose;
|
|
use std::str::FromStr;
|
|
|
|
use nostr_sdk::JsonUtil;
|
|
use nostr_sdk::nostr::key::PublicKey;
|
|
use nostr_sdk::nostr::nips::nip98::HttpMethod;
|
|
use nostr_sdk::nostr::types::url::Url;
|
|
use nostr_sdk::nostr::{Alphabet, Event, Kind, SingleLetterTag, TagKind, TagStandard};
|
|
|
|
pub fn verify_nip98(auth_header: &str, url: &str, method: &str) -> Result<PublicKey> {
|
|
let url = Url::parse(url)?;
|
|
let method = HttpMethod::from_str(&method.to_uppercase())?;
|
|
|
|
let event = decode_auth_event(auth_header)?;
|
|
|
|
if event.kind != Kind::HttpAuth {
|
|
return Err(anyhow!("authorization event kind mismatch"));
|
|
}
|
|
|
|
let authorized_url =
|
|
match event
|
|
.tags
|
|
.find_standardized(TagKind::SingleLetter(SingleLetterTag::lowercase(
|
|
Alphabet::U,
|
|
))) {
|
|
Some(TagStandard::AbsoluteURL(url)) => url,
|
|
_ => return Err(anyhow!("authorization header missing url tag")),
|
|
};
|
|
|
|
let authorized_method = match event.tags.find_standardized(TagKind::Method) {
|
|
Some(TagStandard::Method(method)) => method,
|
|
_ => return Err(anyhow!("authorization header missing method tag")),
|
|
};
|
|
|
|
if authorized_url != &url || authorized_method != &method {
|
|
return Err(anyhow!("authorization does not match request"));
|
|
}
|
|
|
|
event.verify()?;
|
|
Ok(event.pubkey)
|
|
}
|
|
|
|
fn decode_auth_event(auth_header: &str) -> Result<Event> {
|
|
if auth_header.trim().is_empty() {
|
|
return Err(anyhow!("missing authorization header"));
|
|
}
|
|
|
|
let (prefix, encoded) = auth_header
|
|
.split_once(' ')
|
|
.ok_or_else(|| anyhow!("malformed authorization header"))?;
|
|
|
|
if prefix != "Nostr" || encoded.is_empty() {
|
|
return Err(anyhow!("malformed authorization header"));
|
|
}
|
|
|
|
let decoded = general_purpose::STANDARD.decode(encoded)?;
|
|
let json = String::from_utf8(decoded)?;
|
|
Ok(Event::from_json(json)?)
|
|
}
|