Crates.io | actix-web-grants |
lib.rs | actix-web-grants |
version | 4.1.1 |
source | src |
created_at | 2021-01-14 13:49:58.547885 |
updated_at | 2024-05-29 23:32:37.73794 |
description | Authorization extension `actix-web` to protect your endpoints |
homepage | https://github.com/DDtKey/protect-endpoints |
repository | https://github.com/DDtKey/protect-endpoints |
max_upload_size | |
id | 341915 |
size | 104,130 |
Authorization extension for
actix-web
to protect your endpoints.
To check user access to specific services, you can use built-in proc-macro
, AuthorityGuard
or manual.
The library can also be integrated with third-party solutions (like actix-web-httpauth
).
The easiest way is to declare a function with the following signature (trait is already implemented for such Fn):
use actix_web::{dev::ServiceRequest, Error};
// You can use custom type instead of String
async fn extract(req: &ServiceRequest) -> Result<HashSet<String>, Error>
App::new()
.wrap(GrantsMiddleware::with_extractor(extract))
Steps 1 and 2 can be replaced by custom middleware or integration with another libraries. Take a look at an jwt-httpauth example
proc-macro
way protection#[get("/secure")]
#[actix_web_grants::protect("OP_READ_SECURED_INFO")]
async fn macro_secured() -> HttpResponse {
HttpResponse::Ok().body("ADMIN_RESPONSE")
}
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}")]
#[actix_web_grants::protect("ADMIN", expr = "user_id.into_inner() == user.id", ty = "Role")]
async fn macro_secured(user_id: web::Path<i32>, user: web::Data<User>) -> HttpResponse {
HttpResponse::Ok().body("some secured response")
}
#[post("/info/{user_id}")]
#[actix_web_grants::protect(any("ADMIN", expr = "user.is_super_user()"), ty = "Role")]
async fn admin_or_super_user(user_id: web::Path<i32>, user: web::Data<User>) -> HttpResponse {
HttpResponse::Ok().body("some secured response")
}
Guard
way protectionuse actix_web_grants::{AuthorityGuard, GrantsMiddleware};
App::new()
.wrap(GrantsMiddleware::with_extractor(extract))
.service(web::resource("/admin")
.to(|| async { HttpResponse::Ok().finish() })
.guard(AuthorityGuard::new("ROLE_ADMIN".to_string())))
.service(web::resource("/admin") // fallback endpoint if you want to return a 403 HTTP code
.to(|| async { HttpResponse::Forbidden().finish() }))
Since Guard
is intended only for routing, if the user doesn't have authorities, it returns a 404
HTTP code. But you can override the behavior like this:
use actix_web_grants::{AuthorityGuard, GrantsMiddleware};
use actix_web::http::header;
App::new()
.wrap(GrantsMiddleware::with_extractor(extract))
.service(web::scope("/admin")
.guard(AuthorityGuard::new("ROLE_ADMIN_ACCESS".to_string()))
.service(web::resource("/users")
.to(|| async { HttpResponse::Ok().finish() }))
).service(
web::resource("/admin{regex:$|/.*?}").to(|| async {
HttpResponse::TemporaryRedirect().append_header((header::LOCATION, "/login")).finish()
}))
When Guard
lets you in the Scope
(meaning you have "ROLE_ADMIN_ACCESS"
), the redirect will be unreachable for you. Even if you will request /admin/some_undefined_page
.
Note: regex
is a Path
variable containing passed link.
use actix_web_grants::authorities::{AuthDetails, AuthoritiesCheck};
async fn manual_secure(details: AuthDetails) -> HttpResponse {
if details.has_authority(ROLE_ADMIN) {
return HttpResponse::Ok().body("ADMIN_RESPONSE");
}
HttpResponse::Ok().body("OTHER_RESPONSE")
}
You can find more examples
in the git repository folder and documentation
.
actix-web
versionsactix-web-grants: 2.*
supported version of actix-web
is 3.*
actix-web-grants: 3.*
& 4.*
supported version of actix-web
is 4.*