Skip to main content

Crate axum_negotiate_layer

Crate axum_negotiate_layer 

Source
Expand description

axum-negotiate-layer provides middleware for authenticating connections over the Microsoft “HTTP Negotiate” extension.

§Features

  • NegotiateMiddleware: A tower::Service object that uses the NegotiateInfo attached to the connection to authenticate that connection
  • NegotiateLayer: A tower::Layer for the above mentioned service
  • A Authenticated request extension object to get information about authenticated clients (so far only the user identity)
  • An extension to the standard axum::serve::Listener (with feature http1) to add negotiation info to every connection. As SPNEGO is a non-http standard authentication method authenticating by connection, the negotiation info has to be included in every connection given to axum, either via this struct or by manually providing it as a ConnectInfo extension when driving the routing loop yourself.

§Usage

The middleware and layer require the Kerberos SPN for the Router in question.

use axum::{routing::get, Extension, Router};
use axum_negotiate_layer::{Authenticated, NegotiateInfo, NegotiateLayer, AddNegotiateInfo};
use tokio::net::TcpListener;

#[tokio::main]
async fn main() {
    let router = Router::new()
        .route("/", get(hello))
        .layer(NegotiateLayer::new(Some("HTTP/example.com")))
        .into_make_service_with_connect_info::<NegotiateInfo>();
    let listener = TcpListener::bind("127.0.0.1:80").await.unwrap();
}

The most convenient use case shown above will use the layer object to verify all routes above it are authenticated. The Router::into_make_service_with_connect_info call is mandatory for this layer to work on the used Router, otherwise the layer will panic.

§Axum handler usage example

async fn hello(a: Authenticated) -> String {
    format!("Hello, {}!", a.client().unwrap_or("whoever".to_owned()))
}

Alternatively, this works:

async fn hello(Extension(a): Extension<Authenticated>) -> String {
    format!("Hello, {}!", a.client().unwrap_or("whoever".to_owned()))
}

When getting the Authenticated object from the request extension or extracting it directly, the authentication can be guaranteed for this route, as this object can only be set by a middleware of this crate.

Structs§

Authenticated
Extension or Extractor type that gets set after successful Authentication
ChannelBindings
HasNegotiateInfo
axum::serve::Listener wrapper that provides connection-bound negotiation info.
NegotiateInfo
Type that must be set via Router::into_make_service_with_connect_info.
NegotiateLayer
Layer which will enforce authentication
NegotiateMiddleware
Middleware to enforce authentication
Negotiator
Io Wrapper that carries a specific connection’s negotiation information

Traits§

WithNegotiateInfo
axum::serve::Listener extension for a convenient way to create a HasNegotiateInfo