1 unstable release

0.1.0 Mar 18, 2022

#1042 in HTTP server

MIT/Apache

21KB
145 lines

Actix Middleware for Oso Authorization

actix-web middleware for the Oso authorization framework.

ci crates.io Documentation Apache 2.0 or MIT licensed Dependency Status

Installation

Add actix-web-middleware-oso as a dependency:

[dependencies]
actix-web-middleware-oso = "0.1.0"
actix-web = "4"
oso = "0.26.0"

Usage

Create a function to run your Oso authorization logic.

async fn authorize(req: ServiceRequest, oso: Oso) -> Result<ServiceRequest, Error> {
    let action = req.method().to_string().to_uppercase();
    let resource = req.path();

    match oso.is_allowed("_actor", action, resource) {
        Ok(true) => Ok(req),
        _ => Err(ErrorUnauthorized("not allowed")),
    }
}

Initialize Oso and the middleware, and add it to your actix App with wrap.

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| {
        let mut oso = Oso::new();
        oso.load_str(r#"allow(_actor, action, resource) if action = "GET" and resource.starts_with("/ok/");"#)
            .unwrap();
        let authz = OsoMiddleware::new(oso, authorize);
        App::new()
            .wrap(middleware::Logger::default())
            .wrap(authz)
            .default_service(web::to(|| HttpResponse::Ok()))
    })
        .bind("127.0.0.1:8080")?
        .run()
        .await
}

In addition, your initialized Oso is available to handlers via the extractor:

#[get("/hello")]
async fn hello(oso: ExtractedOso) -> impl Responder {
    let user = User {
        name: "alice".to_string(),
    };

    if oso.is_allowed(user, "action", "resource").unwrap() {
        HttpResponse::Ok().body("cool cool")
    } else {
        HttpResponse::Unauthorized().body("nope, sorry")
    }
}

License

This project is licensed under either of

at your option.

Dependencies

~18–33MB
~572K SLoC