limes/lib.rs
1#![warn(
2 missing_debug_implementations,
3 rust_2018_idioms,
4 unreachable_pub,
5 clippy::pedantic
6)]
7#![allow(
8 clippy::module_name_repetitions,
9 clippy::large_enum_variant,
10 clippy::doc_markdown
11)]
12#![forbid(unsafe_code)]
13// #![cfg_attr(docsrs, feature(doc_cfg))]
14
15//! [](https://opensource.org/licenses/Apache-2.0)
16//! [](https://github.com/vakamo-labs/limes-rs/actions/workflows/unittests.yaml)
17//!
18//! # Limes
19//!
20//! Limes is a multi-tenant capable Authentication middleware for OAuth2.0 and Open ID Connect with optional support for `axum`.
21//! It supports the following [`Authenticator`]s natively:
22//!
23//! * [`JWKSWebAuthenticator`](`jwks::JWKSWebAuthenticator`) that fetches JWKs keys from a `.well-known/openid-configuration`, refreshes keys regularly, and validates tokens locally.
24//! * [`KubernetesAuthenticator`](`kubernetes::KubernetesAuthenticator`) which validates tokens using Kubernetes `TokenReview`.
25//! * [`AuthenticatorChain`] holds a collection of [`Authenticator`]s and authenticates the token with the first suitable Authenticator. This is especially useful for multi-tenant setups where tokens from multiple IdPs should be accepted. Each IdP is assigned a unique `idp_id` to provide a globally unique [`Subject`] that identifies a user.
26//!
27//! Custom Authenticators can easily be added by implementing the [`Authenticator`] trait.
28//!
29//! # Why the Name?
30//! "Limes" is the ancient Roman wall that fortified the ROman Empire. Just like those mighty walls, our Limes library
31//! stands guard, protecting your applications from unauthorized access. So, while you won't find any tangy flavors here,
32//! you will find robust authentication to keep your digital empire safe. When life gives you Limes, add auth to your
33//! crate! Wait a minute ...
34//!
35//! # Single-Tenant Example
36//!
37//! ```no_run
38//! use axum::{middleware::from_fn_with_state, response::IntoResponse, routing::get, Extension};
39//! use limes::{
40//! axum::authentication_middleware, format_subject, jwks::JWKSWebAuthenticator, Authentication,
41//! };
42//!
43//! // Use none for single tenant setups
44//! const IDP_SEPARATOR: Option<char> = None;
45//!
46//! #[tokio::main]
47//! async fn main() {
48//! let authenticator = JWKSWebAuthenticator::new(
49//! "https://accounts.google.com", // Must provide ./well-known/openid-configuration
50//! Some(std::time::Duration::from_secs(10 * 60)), // Refresh JWKS keys every 10 minutes
51//! )
52//! .await
53//! .unwrap()
54//! .set_accepted_audiences(vec!["my-app".to_string()]); // Acceptable audiences (optional)
55//!
56//! let app = axum::Router::new()
57//! .route("/whoami", get(whoami))
58//! .layer(from_fn_with_state(
59//! authenticator,
60//! authentication_middleware::<JWKSWebAuthenticator>,
61//! ));
62//!
63//! let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
64//! .await
65//! .unwrap();
66//! println!("listening on {}", listener.local_addr().unwrap());
67//! axum::serve(listener, app).await.unwrap();
68//! }
69//!
70//! async fn whoami(Extension(auth): Extension<Authentication>) -> impl IntoResponse {
71//! format!("Hello, {}!", format_subject(auth.subject(), IDP_SEPARATOR))
72//! }
73//! ```
74//!
75//! # Multi-Tenant Setup
76//! Limes supports the chained Authenticators. As each Authenticator can point to a different IdP, and subject IDs are not guaranteed to be unique across IdPs, it is important to specify the `idp_id` for each [`Authenticator`] that is used in a [`AuthenticatorChain`].
77//!
78//! ```no_run
79//! use axum::{middleware::from_fn_with_state, response::IntoResponse, routing::get, Extension};
80//! use limes::{
81//! axum::authentication_middleware, format_subject, jwks::JWKSWebAuthenticator,
82//! kubernetes::KubernetesAuthenticator, Authentication, AuthenticatorChain, AuthenticatorEnum,
83//! };
84//!
85//! // We recommend using a character that is never used in subject ids
86//! const IDP_SEPARATOR: Option<char> = Some('~');
87//!
88//! #[tokio::main]
89//! async fn main() {
90//! let oidc_authenticator = JWKSWebAuthenticator::new(
91//! "https://accounts.google.com", // Must provide ./well-known/openid-configuration
92//! Some(std::time::Duration::from_secs(10 * 60)), // Refresh JWKS keys every 10 minutes
93//! )
94//! .await
95//! .unwrap()
96//! .set_idp_id("oidc") // Unique identifier for this IdP. Must never contain the `IDP_SEPARATOR`
97//! .set_accepted_audiences(vec!["my-app".to_string()]); // Acceptable audiences (optional)
98//!
99//! // Uses the default Kubernetes client. Other constructors are available that accept a custom client.
100//! let kubernetes_authenticator = KubernetesAuthenticator::try_new_with_default_client(
101//! Some("kubernetes"), // Unique identifier for this IdP. Must never contain the `IDP_SEPARATOR`
102//! vec![], // Don't validate the audience
103//! )
104//! .await
105//! .unwrap();
106//!
107//! // Chain the authenticators together. Order matters.
108//! // The first authenticator that returns true for `can_handle_token` will be used.
109//! let chain = AuthenticatorChain::<AuthenticatorEnum>::builder()
110//! .add_authenticator(oidc_authenticator)
111//! .add_authenticator(kubernetes_authenticator)
112//! .build();
113//!
114//! let app = axum::Router::new()
115//! .route("/whoami", get(whoami))
116//! .layer(from_fn_with_state(
117//! chain,
118//! authentication_middleware::<AuthenticatorChain<AuthenticatorEnum>>,
119//! ));
120//!
121//! let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
122//! .await
123//! .unwrap();
124//! println!("listening on {}", listener.local_addr().unwrap());
125//! axum::serve(listener, app).await.unwrap();
126//! }
127//!
128//! async fn whoami(Extension(auth): Extension<Authentication>) -> impl IntoResponse {
129//! format!("Hello, {}!", format_subject(auth.subject(), IDP_SEPARATOR))
130//! // Would print "oidc~<subject_id>" for google tokens, where oidc is the `idp_id` we set above.
131//! }
132//! ```
133//!
134//! # Feature flags
135//! Limes uses a set of feature flags to reduce the amount of compiled code.
136//! The following feature flags are available:
137//!
138//! * `all`: Activate all features
139//! * `default`: Includes `rustls-tls` and `jwks`.
140//! * `kubernetes`: Provides the `KubernetesAuthenticator` implementation which validates tokens using Kubernetes `TokenReview`.
141//! * `rustls-tls`: Enable `rustls` for all dependant crates.
142//! * `jwks`: Provides the `JWKSWebAuthenticator`
143//! * `axum`: Provides axum middleware that performs the Authentication and provides the tokens Payload as extension.
144
145mod authenticator;
146mod chain;
147pub mod error;
148pub mod introspect;
149#[cfg(feature = "jwks")]
150pub mod jwks;
151mod subject;
152
153#[cfg(feature = "kubernetes")]
154pub mod kubernetes;
155
156pub use authenticator::{Authentication, Authenticator, PrincipalType};
157pub use chain::{AuthenticatorChain, AuthenticatorChainBuilder, AuthenticatorEnum};
158pub use subject::Subject;
159
160pub use subject::{format_subject, parse_subject};
161
162#[cfg(feature = "axum")]
163pub mod axum;