torrust / torrust-index

This repository serves as the backend for the Torrust Index project.
https://torrust.com
GNU Affero General Public License v3.0
50 stars 19 forks source link

Use Casbin for the authorization layer #615

Closed mario-nt closed 2 months ago

mario-nt commented 4 months ago

Casbin is a powerful library for implementing authorization.

Using Casbin as an authorization layer would make the code cleaner and easier to work with, also, it will allow us to implement several authorization patterns like role based authorization and attribute based authorization with ease.

The idea is to refactor the authorization service and implement Casbin for the authorization logic.

Subtasks

josecelano commented 3 months ago

Hi @mario-nt, I think after implementing this issue, we should make sure all handlers call the authorization service directly or inside the application services. It would be better if we create an application service for all handlers.

Examples

Handlers without authorization:

#[allow(clippy::unused_async)]
pub async fn about_page_handler(State(_app_data): State<Arc<AppData>>) -> Response {
    (
        StatusCode::OK,
        [(header::CONTENT_TYPE, "text/html; charset=utf-8")],
        about::page(),
    )
        .into_response()
}
pub async fn license_page_handler(State(_app_data): State<Arc<AppData>>) -> Response {
    (
        StatusCode::OK,
        [(header::CONTENT_TYPE, "text/html; charset=utf-8")],
        about::license_page(),
    )
        .into_response()
}
pub async fn get_all_handler(State(app_data): State<Arc<AppData>>) -> Response {
    match app_data.category_repository.get_all().await {
        Ok(categories) => {
            let categories: Vec<Category> = categories.into_iter().map(Category::from).collect();
            Json(responses::OkResponseData { data: categories }).into_response()
        }
        Err(error) => error.into_response(),
    }
}

In fact, there are a lot of them, including all the public endpoints and those that only require a user to be logged in. Even if they don't not require a specific role or conditions we should include them in the authorization service to make the permission explicit in the list.

mario-nt commented 3 months ago

@josecelano I agree, I have already thought about it.

The handlers that require authorization all use the authorize function in the service, and the API layer call those services.

It is a good idea to have the same for endpoints that don't require a logged-in user, like the one you wrote or the download torrent handler, so that way every single actions has to go throught an authorize method (I have to think a way or forcing this, so the compiler complains if an action if performed without the authorize function.

I think there are some actions like editing an owned torrent, that only checks if the user is the owner of the torrent in the frontend, I will check this and make any necessary changes when I start working on those endpoints.

da2ce7 commented 3 months ago

Supports https://csrc.nist.gov/projects/attribute-based-access-control

mario-nt commented 3 months ago

Supports https://csrc.nist.gov/projects/attribute-based-access-control

Hi @da2ce7 , yup I was planning on using the ABAC for the update torrent handler