Expand description
§axum-server-mtls
mTLS client certificate extraction for axum-server.
axum-server does not expose peer certificates after the TLS handshake
(issue #162).
This crate fills that gap by wrapping RustlsAcceptor with a custom
Accept implementation that extracts the client certificate chain and
injects it into every HTTP request as an extension.
§Usage
use axum::{extract::Extension, routing::get, Router};
use axum_server_mtls::{MtlsAcceptor, PeerCertificates};
use axum_server::tls_rustls::{RustlsAcceptor, RustlsConfig};
#[tokio::main]
async fn main() {
let rustls_config = RustlsConfig::from_pem_file("cert.pem", "key.pem")
.await
.unwrap();
let app = Router::new().route("/", get(handler));
let acceptor = MtlsAcceptor::new(RustlsAcceptor::new(rustls_config));
let addr: std::net::SocketAddr = "0.0.0.0:3000".parse().unwrap();
axum_server::bind(addr)
.acceptor(acceptor)
.serve(app.into_make_service())
.await
.unwrap();
}
async fn handler(
Extension(certs): Extension<PeerCertificates>,
) -> String {
match certs.leaf_cn() {
Some(cn) => format!("Hello, {cn}!"),
None => "No client certificate presented.".into(),
}
}§How It Works
MtlsAcceptordelegates the TLS handshake to the innerRustlsAcceptor.- After the handshake, it reads
ServerConnection::peer_certificates(). - It wraps the inner service with a
towerExtensionlayer so that every request on that connection carries aPeerCertificatesvalue. - Handlers extract it via
Extension<PeerCertificates>.
The Rustls ServerConfig must be built with
with_client_cert_verifier
(optional or required) for clients to present certificates. If built with
with_no_client_auth(), PeerCertificates will always be empty.
Structs§
- Mtls
Acceptor - An
Acceptwrapper aroundRustlsAcceptorthat extracts client certificates from the TLS connection and injects them into every HTTP request as anaxum::Extension<PeerCertificates>. - Peer
Certificates - Client certificate chain extracted from the TLS connection.