authenticationrustactix-web

How can I make protected routes in actix-web


I need to verify if the user has permission for some routes. I have made 3 "scopes" (guest, auth-user, admin) and now I don't know how to check if the user has access to these routes.

I'm trying to implement auth-middleware and this middleware should check if the user has the correct cookie or token. (I'm able to print out a cookie from request header), but I have no idea how to import, use actix_identity, and have access to id parameter inside this middleware.

I believe that my problem isn't only regarding Actix-identity, but I'm not able to pass parameters inside middleware.

    #[actix_rt::main]
    async fn main() -> std::io::Result<()> {

        let cookie_key = conf.server.key;
    
        // Register http routes
        let mut server = HttpServer::new(move || {
            App::new()
                // Enable logger
                .wrap(Logger::default())
                .wrap(IdentityService::new(
                    CookieIdentityPolicy::new(cookie_key.as_bytes())
                        .name("auth-cookie")
                        .path("/")
                        .secure(false),
                ))
                //limit the maximum amount of data that server will accept
                .data(web::JsonConfig::default().limit(4096))
                //normal routes
                .service(web::resource("/").route(web::get().to(status)))
                // .configure(routes)
                .service(
                    web::scope("/api")
                        // guest endpoints
                        .service(web::resource("/user_login").route(web::post().to(login)))
                        .service(web::resource("/user_logout").route(web::post().to(logout)))
                        // admin endpoints
                        .service(
                            web::scope("/admin")
                                // .wrap(AdminAuthMiddleware)
                                .service(
                                    web::resource("/create_admin").route(web::post().to(create_admin)),
                                )
                                .service(
                                    web::resource("/delete_admin/{username}/{_:/?}")
                                        .route(web::delete().to(delete_admin)),
                                ),
                        )
                        //user auth routes
                        .service(
                            web::scope("/auth")
                                // .wrap(UserAuthMiddleware)
                                .service(web::resource("/get_user").route(web::get().to(get_user))),
                        ),
                )
        });
    
        // Enables us to hot reload the server
        let mut listenfd = ListenFd::from_env();
        server = if let Some(l) = listenfd.take_tcp_listener(0).unwrap() {
            server.listen(l)?
        } else {
            server.bind(ip)?
        };
    
        server.run().await

resources that I have tried:

  1. Creating authentication middleware for Actix API https://www.jamesbaum.co.uk/blether/creating-authentication-middleware-actix-rust-react/

  2. Actix-web token validation in middleware https://users.rust-lang.org/t/actix-web-token-validation-in-middleware/38205

  3. Actix middleware examples https://github.com/actix/examples/tree/master/middleware

Maybe I think completely wrong and auth-middleware isn't the best solution for my problem. I hope that you can help me create "protected routes"


Solution

  • Try extractors instead

    Trying to implement this pattern in Actix 3 I banged my head for awhile trying to use middleware, basically making a guard and then figuring out how to pass data from the middleware into the handler. It was painful and eventually I realized that I was working against Actix rather than with it.

    Finally I learned out that the way to get information to a handler is to create a struct (AuthedUser, perhaps?) and implement the FromRequest trait on that struct.

    Then every handler that asks for an AuthedUser in the function signature will be auth gated and if the user is logged in will have any user information you attach to AuthedUser in the FromRequest::from_request method.

    Actix refers to these structs that implement FromRequest as extractors. It's a bit of magic that could use more attention in the guide.