pub fn is_bearer_scheme(auth_header: &str) -> bool {
let trimmed = auth_header.trim();
let scheme = trimmed.split_ascii_whitespace().next().unwrap_or("");
scheme.eq_ignore_ascii_case("bearer")
}
pub fn extract_bearer_token(auth_header: &str) -> Option<String> {
let trimmed = auth_header.trim();
let (scheme, rest) = trimmed.split_once([' ', '\t'])?;
if !scheme.eq_ignore_ascii_case("bearer") {
return None;
}
let token = rest.trim();
if token.is_empty() {
return None;
}
if token.contains(|c: char| c.is_ascii_whitespace()) {
return None;
}
if token.contains(|c: char| c.is_ascii_control()) {
return None;
}
Some(token.to_string())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_bearer_extraction_from_header() {
assert_eq!(
extract_bearer_token("Bearer abc123"),
Some("abc123".to_string())
);
assert_eq!(
extract_bearer_token("Bearer eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiIxIn0.sig"),
Some("eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiIxIn0.sig".to_string())
);
}
#[test]
fn test_bearer_case_insensitive() {
assert_eq!(
extract_bearer_token("bearer abc123"),
Some("abc123".to_string())
);
assert_eq!(
extract_bearer_token("BEARER abc123"),
Some("abc123".to_string())
);
assert_eq!(
extract_bearer_token("BeArEr abc123"),
Some("abc123".to_string())
);
}
#[test]
fn test_bearer_reject_empty_token() {
assert_eq!(extract_bearer_token("Bearer "), None);
assert_eq!(extract_bearer_token("Bearer "), None);
}
#[test]
fn test_bearer_reject_multi_token() {
assert_eq!(extract_bearer_token("Bearer abc 123"), None);
assert_eq!(extract_bearer_token("Bearer abc\t123"), None);
}
#[test]
fn test_bearer_ows_handling() {
assert_eq!(
extract_bearer_token("Bearer abc123"),
Some("abc123".to_string())
);
assert_eq!(
extract_bearer_token("Bearer\tabc123"),
Some("abc123".to_string())
);
assert_eq!(
extract_bearer_token(" Bearer abc123 "),
Some("abc123".to_string())
);
}
#[test]
fn test_bearer_reject_control_chars() {
assert_eq!(extract_bearer_token("Bearer abc\x00123"), None);
assert_eq!(extract_bearer_token("Bearer abc\x01123"), None);
assert_eq!(extract_bearer_token("Bearer abc\x7f123"), None);
}
#[test]
fn test_non_bearer_not_extracted() {
assert_eq!(extract_bearer_token("Basic dXNlcjpwYXNz"), None);
assert_eq!(extract_bearer_token("Digest realm=\"mcp\""), None);
}
#[test]
fn test_is_bearer_scheme() {
assert!(is_bearer_scheme("Bearer abc123"));
assert!(is_bearer_scheme("bearer abc123"));
assert!(is_bearer_scheme("BEARER abc123"));
assert!(is_bearer_scheme("Bearer ")); assert!(!is_bearer_scheme("Basic dXNlcjpwYXNz"));
assert!(!is_bearer_scheme("Digest realm=\"mcp\""));
assert!(!is_bearer_scheme(""));
}
}