Skip to main content

micromegas/servers/
tonic_auth_interceptor.rs

1use micromegas_auth::client_ip::resolve_client_ip;
2use micromegas_auth::types::{AuthProvider, GrpcRequestParts, ProviderUnavailable, RequestParts};
3use micromegas_tracing::prelude::*;
4use std::sync::Arc;
5use tonic::{Request, Status};
6
7/// Checks the authentication of a Tonic request using an `AuthProvider`.
8///
9/// This function extracts request parts from the gRPC metadata
10/// and validates them using the provided authentication provider.
11pub async fn check_auth(
12    req: Request<()>,
13    auth_provider: &Arc<dyn AuthProvider>,
14) -> Result<Request<()>, Status> {
15    let metadata = req.metadata();
16    // Mirrors `flight_sql_service_impl.rs`'s existing two `get_client_ip` call sites.
17    let client_ip = resolve_client_ip(metadata.as_ref(), req.extensions());
18
19    let parts = GrpcRequestParts {
20        metadata: metadata.clone(),
21        client_ip,
22    };
23
24    let auth_ctx = auth_provider
25        .validate_request(&parts as &dyn RequestParts)
26        .await
27        .map_err(|e| {
28            if e.downcast_ref::<ProviderUnavailable>().is_some() {
29                debug!("authentication failed: {e}");
30                Status::unavailable("auth provider unavailable")
31            } else {
32                warn!("authentication failed: {e}");
33                Status::unauthenticated("invalid token")
34            }
35        })?;
36
37    info!(
38        "authenticated: subject={} email={:?} issuer={} admin={}",
39        auth_ctx.subject,
40        auth_ctx.email,
41        auth_ctx.issuer,
42        auth_ctx.is_admin()
43    );
44
45    let mut req = req;
46    req.extensions_mut().insert(auth_ctx);
47    Ok(req)
48}