Skip to main content

claude_pool_server/
auth.rs

1//! Bearer token authentication for HTTP transport.
2
3use std::collections::HashSet;
4use std::sync::Arc;
5
6/// Validated set of bearer tokens.
7///
8/// Wraps an `Arc<HashSet<String>>` for cheap cloning into middleware closures.
9#[derive(Clone)]
10#[cfg_attr(not(feature = "http"), allow(dead_code))]
11pub struct BearerTokens {
12    tokens: Arc<HashSet<String>>,
13}
14
15#[cfg_attr(not(feature = "http"), allow(dead_code))]
16impl BearerTokens {
17    /// Create a new token set from the given list.
18    pub fn new(tokens: Vec<String>) -> Self {
19        Self {
20            tokens: Arc::new(tokens.into_iter().collect()),
21        }
22    }
23
24    /// Check whether the given token is valid.
25    pub fn validate(&self, token: &str) -> bool {
26        self.tokens.contains(token)
27    }
28
29    /// Returns true if no tokens were configured (auth disabled).
30    pub fn is_empty(&self) -> bool {
31        self.tokens.is_empty()
32    }
33}
34
35#[cfg(test)]
36mod tests {
37    use super::*;
38
39    #[test]
40    fn validate_known_token() {
41        let tokens = BearerTokens::new(vec!["sk-test-123".into(), "sk-test-456".into()]);
42        assert!(tokens.validate("sk-test-123"));
43        assert!(tokens.validate("sk-test-456"));
44    }
45
46    #[test]
47    fn reject_unknown_token() {
48        let tokens = BearerTokens::new(vec!["sk-test-123".into()]);
49        assert!(!tokens.validate("sk-wrong"));
50        assert!(!tokens.validate(""));
51    }
52
53    #[test]
54    fn empty_tokens() {
55        let tokens = BearerTokens::new(vec![]);
56        assert!(tokens.is_empty());
57        assert!(!tokens.validate("anything"));
58    }
59
60    #[test]
61    fn non_empty_tokens() {
62        let tokens = BearerTokens::new(vec!["key".into()]);
63        assert!(!tokens.is_empty());
64    }
65}