rust_grpc_lib/auth.rs
1//! Re-exports from `rust-auth-lib` plus the two gRPC-specific sub-modules.
2//!
3//! Everything a consumer needs for JWT auth lives here; a direct dependency on
4//! `rust-auth-lib` is not required.
5//!
6//! # Sub-modules
7//!
8//! - [`interceptor`] — [`ClientJwtInterceptor`], the outbound client interceptor
9//! that attaches `Bearer` tokens to every outgoing request.
10//! - [`layer`] — [`JwtValidationLayer`] / [`JwtValidationService`] and the
11//! [`validator_into_layer`] constructor for server-side JWT validation.
12//!
13//! # Re-exported items
14//!
15//! **Traits:** [`TokenProvider`], [`TokenValidator`], [`Claims`], [`Ephemeral`]
16//!
17//! **Token sources:** [`FileTokenProvider`], [`ForwardedToken`]
18//!
19//! **Validators:** [`KeyValidator`], [`KeyValidatorConfig`]
20//!
21//! **Errors:** [`AuthError`], [`ConfigError`], [`TokenError`]
22//!
23//! **Claims:** [`KeycloakClaims`]
24//!
25//! **Free function:** [`extract_token`] — strips the `Bearer ` prefix from an
26//! incoming tonic request's `Authorization` header and returns a
27//! [`ForwardedToken`].
28//!
29//! # Intentionally omitted
30//!
31//! - `KeycloakClientCredentialsProvider` — requires a live Keycloak token
32//! endpoint; use `rust-auth-lib` directly if needed.
33
34pub mod interceptor;
35pub mod layer;
36
37// Traits
38pub use rust_auth_lib::Claims;
39pub use rust_auth_lib::Ephemeral;
40pub use rust_auth_lib::TokenProvider;
41pub use rust_auth_lib::TokenValidator;
42
43// Token sources
44pub use rust_auth_lib::FileTokenProvider;
45pub use rust_auth_lib::ForwardedToken;
46
47// Validators
48pub use rust_auth_lib::KeyValidator;
49pub use rust_auth_lib::KeyValidatorConfig;
50
51// Error types
52pub use rust_auth_lib::AuthError;
53pub use rust_auth_lib::ConfigError;
54pub use rust_auth_lib::TokenError;
55
56// Keycloak-specific claims
57pub use rust_auth_lib::keycloak::KeycloakClaims;
58
59// gRPC-specific types from submodules
60pub use interceptor::ClientJwtInterceptor;
61pub use layer::{JwtValidationLayer, validator_into_layer};
62use tonic::Request;
63
64#[cfg(test)]
65mod tests;
66
67/// Construct from the metadata of an incoming tonic request.
68pub fn extract_token<T>(request: &Request<T>) -> Result<ForwardedToken, TokenError> {
69 request
70 .metadata()
71 .get("authorization")
72 .and_then(|v| v.to_str().ok())
73 .and_then(|s| s.strip_prefix("Bearer "))
74 .map(ForwardedToken::new)
75 .ok_or(TokenError::EmptyAccessToken)
76}