Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Authorization middleware #6

Open
divarvel opened this issue May 22, 2023 · 1 comment
Open

Authorization middleware #6

divarvel opened this issue May 22, 2023 · 1 comment

Comments

@divarvel
Copy link
Collaborator

divarvel commented May 22, 2023

The exposed middleware only handles token parsing (and verification), not authorization.

This is done on purpose: authorization is usually specific to each endpoint, while a middleware is called before routing and does not have access to endpoint-specific data.

In some cases, however, authorization can be expressed in a common way across all endpoints.
In that case, being able to do it in a middleware is a good thing:

  • once the middleware is set up, it's impossible to forget to protect an endpoint
  • it strongly separates authorization logic from actual endpoint logic
  • it helps remove boilerplate

This use case is quite different from the one already covered, so i think it should be a different middleware, not a knob on the existing one (even though the actual implementation could be shared between the two middlewares).

Same as for #5, it will be important to strike a good balance between configurability and purpose. For reference, here is what I came up with for the same use case in Haskell https://hackage.haskell.org/package/biscuit-wai-0.1.0.0/candidate/docs/Network-Wai-Middleware-Biscuit.html#t:AuthorizationConfig

@Tipnos
Copy link
Collaborator

Tipnos commented May 30, 2023

Study demonstrates that to execute Route specific Authorization Handlers in the middleware and post process their result requires either:

  • redesign a major part of actix-web architecture
  • or store a dedicated route tree in the middleware to retrieve the Authorization Handlers associated to the Request URI

About actix-web architecture redesign

The Service trait used in actix middleware are defined in a seperate crate actix-service which is a dependency of actix-web and located in a different repo actix-net. Moreover actix-service has 0 knowledge of actix-web Route or Handler implementation.

To make Service that can execute actix-web Handler a closure is used

Route binding to handler in actix-web/src/route.rs

pub fn to<F, Args>(mut self, handler: F) -> Self
    where
        F: Handler<Args>,
        Args: FromRequest + 'static,
        F::Output: Responder + 'static,
    {
        self.service = handler_service(handler);
        self
    }

Closure for actix-service actix-web/src/handler.rs

pub(crate) fn handler_service<F, Args>(handler: F) -> BoxedHttpServiceFactory
where
    F: Handler<Args>,
    Args: FromRequest,
    F::Output: Responder,
{
    boxed::factory(fn_service(move |req: ServiceRequest| {
        let handler = handler.clone();

        async move {
            let (req, mut payload) = req.into_parts();

            let res = match Args::from_request(&req, &mut payload).await {
                Err(err) => HttpResponse::from_error(err),

                Ok(data) => handler
                    .call(data)
                    .await
                    .respond_to(&req)
                    .map_into_boxed_body(),
            };

            Ok(ServiceResponse::new(req, res))
        }
    }))
}

actix-service function used above actix-service/src/fn_service.rs

pub fn fn_service<F, Fut, Req, Res, Err, Cfg>(
    f: F,
) -> FnServiceFactory<F, Fut, Req, Res, Err, Cfg>
where
    F: Fn(Req) -> Fut + Clone,
    Fut: Future<Output = Result<Res, Err>>,
{
    FnServiceFactory::new(f)
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants