1use std::{future::Future, pin::Pin, sync::Arc};
2
3use crate::{
4 auth::{
5 credentials::Credentials,
6 identity::AuthenticatedIdentity,
7 provider::{AuthFuture, AuthProvider},
8 },
9 error::{McpError, McpResult},
10};
11
12pub type BasicValidatorFn = Arc<
14 dyn Fn(String, String) -> Pin<Box<dyn Future<Output = McpResult<AuthenticatedIdentity>> + Send>>
15 + Send
16 + Sync,
17>;
18
19pub struct BasicAuthProvider {
39 validator: BasicValidatorFn,
40}
41
42impl BasicAuthProvider {
43 pub fn with_validator<F, Fut>(f: F) -> Self
45 where
46 F: Fn(String, String) -> Fut + Send + Sync + 'static,
47 Fut: Future<Output = McpResult<AuthenticatedIdentity>> + Send + 'static,
48 {
49 Self {
50 validator: Arc::new(move |u, p| Box::pin(f(u, p))),
51 }
52 }
53}
54
55impl AuthProvider for BasicAuthProvider {
56 fn authenticate<'a>(&'a self, credentials: &'a Credentials) -> AuthFuture<'a> {
57 Box::pin(async move {
58 match credentials {
59 Credentials::Basic { username, password } => {
60 (self.validator)(username.clone(), password.clone()).await
61 }
62 _ => Err(McpError::Unauthorized(
63 "expected basic auth credentials".into(),
64 )),
65 }
66 })
67 }
68
69 fn accepts(&self, credentials: &Credentials) -> bool {
70 matches!(credentials, Credentials::Basic { .. })
71 }
72}