#axum #security #permissions #grant #proc-macro

protect-axum

Authorization extension for axum to protect your endpoints

3 releases

0.1.2 May 30, 2024
0.1.1 May 29, 2024
0.1.0 Apr 10, 2024
0.0.1-beta.1 Apr 10, 2024

#737 in Authentication

25 downloads per month

MIT/Apache

47KB
281 lines

protect-axum

protect-axum

Authorization extension for axum to protect your endpoints.

Crates.io Downloads Badge crates.io Documentation Apache 2.0 or MIT licensed

To check user access to specific services, you can use built-in proc-macro or manual.

The library can also be integrated with third-party solutions (e.g. jwt-middlewares).

How to use

  1. Declare your own authority extractor

The easiest way is to declare a function with the following signature (trait is already implemented for such Fn):

use axum::extract::Request;
use axum::response::Response;

// You can use custom type instead of String
pub async fn extract(req: &mut Request) -> Result<HashSet<String>, Response>
  1. Add middleware to your application using the extractor defined in step 1
Router::new()
    .route("/endpoint", get(your_handler))
    .layer(GrantsLayer::with_extractor(extract));

Steps 1 and 2 can be replaced by custom middleware or integration with another libraries.

  1. Protect your endpoints in any convenient way from the examples below:

Example of proc-macro way protection

#[get("/secure")]
#[protect_axum::protect("OP_READ_SECURED_INFO")]
async fn macro_secured() -> &'static str {
    return "Hello, World!";
}
Example of ABAC-like protection and custom authority type

Here is an example using the ty and expr attributes. But these are independent features.

expr allows you to include some checks in the macro based on function params, it can be combined with authorities by using all/any.

ty allows you to use a custom type for th authorities (then the middleware needs to be configured). Take a look at an enum-role example

use enums::Role::{self, ADMIN};
use dto::User;

#[get("/info/{user_id}")]
#[protect_axum::protect("ADMIN", expr = "user_id.into_inner() == user.id", ty = "Role")]
async fn macro_secured(Path(user_id): Path<i32>, Json(user): Json<User>) -> &'static str {
    "some secured response"
}

#[post("/info/{user_id}")]
#[protect_axum::protect(any("ADMIN", expr = "user.is_super_user()"), ty = "Role")]
async fn admin_or_super_user(Path(user_id): Path<i32>, Json(user): Json<User>) -> &'static str {
    "some secured response"
}

Example of manual way protection

use protect_axum::authorities::{AuthDetails, AuthoritiesCheck};

async fn manual_secure(details: AuthDetails) -> &'static str {
    if details.has_authority(ROLE_ADMIN) {
        return "ADMIN_RESPONSE";
    }
    "OTHER_RESPONSE"
}

You can find more examples in the git repository folder and documentation.

Dependencies

~2.8–4MB
~75K SLoC