actix-extras: [actix-web-httpauth] Custom response body when Bearer token is missing?

Hello!

I was wondering if there is any support for body/JSON content when the Authorization: Bearer <token> header is missing. I have the following HttpAutentication when creating the server app:

HttpServer::new(move || {
        let auth_validator = HttpAuthentication::bearer(jwt_validate);
        App::new()
            .wrap(Logger::default())
            .wrap(auth_validator)
            .service(responders::hello)
}).bind("127.0.0.1:80")?.run().await?;

The jwt_validate function is:

async fn jwt_validate(req: ServiceRequest, credentials: BearerAuth) -> Result<ServiceRequest, Error> {
    if req.path().starts_with("/api/v1/auth") {
        return Ok(req)
    }
    let parsed = match auth::decode_token(credentials.token().into()) {
        Ok(val) => val,
        Err(err) => return Err(Error::from(err))
    };
    match auth::validate_jwt(parsed) {
        Ok(_val) => Ok(req),
        Err(err) => return Err(Error::from(err))
    }
}

This works fine (access is granted when the token is correct and access is denied when it’s not), but when I don’t use the header Authorization: Bearer <token> I just get a 401 Unauthorized code with an empty body. Is there a way of adding a custom JSON body to the 401 Unauthorized error response using actix-web-httpauth?

Thanks in advance!

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 5
  • Comments: 20 (4 by maintainers)

Most upvoted comments

Hey. After some hours I managed to achieve what I was looking for. I just pushed the changes in my fork so if you want you and specially @robjtede can review them before I open a PR. Probably my approach is not the best or contains some rookie errors as I’m quite new to rust.

Check them out here: https://github.com/PauMAVA/actix-extras/tree/extraction-error-handler

I’m using the error callback as:

fn on_missing_header(req: ServiceRequest, _err: actix_web::error::Error) -> Result<ServiceResponse, actix_web::error::Error> {
    Ok(req.into_response(
        HttpResponse::Unauthorized().json(serde_json::json!(build_error_response(
                ApiErrorCode::MissingToken as u64,
                ApiErrorMessage::MissingToken.value(),
                None
        )))
    ))
}

HttpServer::new(move || {
        let auth_validator = HttpAuthentication::bearer(jwt_validate)
            .on_extraction_error(Box::new(on_missing_header))
            .exclude_path("/api/v?/auth/*")
            .exclude_path("/hello");
            ...
})

Also, note I added a function exclude_path which excludes some paths from being authenticated using glob patterns.

@PauMAVA That sounds awesome. Thank you for your work, I hope it gets merged. I’ve recently got the usual ErrorHandlers middleware, with actix-cors and bearer, working too. After looking at your version it seems, at least to me, like the better solution to rely on your implementation though since it involves fewer calls and also doesn’t require wrapping around another middleware.

Edit: Thank you for adding exclude_path. This really helps with routing

I’ve taken a look at #127 but I am not using actix-cors.

$ cargo tree | grep actix-cors
$ 

This is the postman response: imagen imagen The red logo at the top is only a self-signed cert warning.

If you need more info I will gladly provide it.