Available on crate feature auth only.
Expand description

Authorize requests using the Authorization header.

Example

use tower_http::auth::RequireAuthorizationLayer;
use hyper::{Request, Response, Body, Error};
use http::{StatusCode, header::AUTHORIZATION};
use tower::{Service, ServiceExt, ServiceBuilder, service_fn};

async fn handle(request: Request<Body>) -> Result<Response<Body>, Error> {
    Ok(Response::new(Body::empty()))
}

let mut service = ServiceBuilder::new()
    // Require the `Authorization` header to be `Bearer passwordlol`
    .layer(RequireAuthorizationLayer::bearer("passwordlol"))
    .service_fn(handle);

// Requests with the correct token are allowed through
let request = Request::builder()
    .header(AUTHORIZATION, "Bearer passwordlol")
    .body(Body::empty())
    .unwrap();

let response = service
    .ready()
    .await?
    .call(request)
    .await?;

assert_eq!(StatusCode::OK, response.status());

// Requests with an invalid token get a `401 Unauthorized` response
let request = Request::builder()
    .body(Body::empty())
    .unwrap();

let response = service
    .ready()
    .await?
    .call(request)
    .await?;

assert_eq!(StatusCode::UNAUTHORIZED, response.status());

Custom authorization schemes can be made by implementing AuthorizeRequest:

use tower_http::auth::{RequireAuthorizationLayer, AuthorizeRequest};
use hyper::{Request, Response, Body, Error};
use http::{StatusCode, header::AUTHORIZATION};
use tower::{Service, ServiceExt, ServiceBuilder, service_fn};

#[derive(Clone, Copy)]
struct MyAuth;

impl<B> AuthorizeRequest<B> for MyAuth {
    type ResponseBody = Body;

    fn authorize(
        &mut self,
        request: &mut Request<B>,
    ) -> Result<(), Response<Self::ResponseBody>> {
        if let Some(user_id) = check_auth(request) {
            // Set `user_id` as a request extension so it can be accessed by other
            // services down the stack.
            request.extensions_mut().insert(user_id);

            Ok(())
        } else {
            let unauthorized_response = Response::builder()
                .status(StatusCode::UNAUTHORIZED)
                .body(Body::empty())
                .unwrap();

            Err(unauthorized_response)
        }
    }
}

fn check_auth<B>(request: &Request<B>) -> Option<UserId> {
    // ...
}

#[derive(Debug)]
struct UserId(String);

async fn handle(request: Request<Body>) -> Result<Response<Body>, Error> {
    // Access the `UserId` that was set in `on_authorized`. If `handle` gets called the
    // request was authorized and `UserId` will be present.
    let user_id = request
        .extensions()
        .get::<UserId>()
        .expect("UserId will be there if request was authorized");

    println!("request from {:?}", user_id);

    Ok(Response::new(Body::empty()))
}

let service = ServiceBuilder::new()
    // Authorize requests using `MyAuth`
    .layer(RequireAuthorizationLayer::custom(MyAuth))
    .service_fn(handle);

Or using a closure:

use tower_http::auth::{RequireAuthorizationLayer, AuthorizeRequest};
use hyper::{Request, Response, Body, Error};
use http::{StatusCode, header::AUTHORIZATION};
use tower::{Service, ServiceExt, ServiceBuilder, service_fn};

async fn handle(request: Request<Body>) -> Result<Response<Body>, Error> {
    // ...
}

let service = ServiceBuilder::new()
    .layer(RequireAuthorizationLayer::custom(|request: &mut Request<Body>| {
        // authorize the request
    }))
    .service_fn(handle);

Structs

Type that performs basic authorization.
Type that performs “bearer token” authorization.
Middleware that authorizes all requests using the Authorization header.
Layer that applies RequireAuthorization which authorizes all requests using the Authorization header.

Traits

Trait for authorizing requests.