I am trying to build an extractor in actix_web where I extract a Bearer token from an Authorization header, decode the JWT token and store it in a struct.
use actix_web::dev::Payload;
use actix_web::{FromRequest, HttpRequest, HttpResponse};
use std::future::{ready, Ready};
use uuid::Uuid;
use crate::domain::UserRoles;
use crate::helpers::unauthorized_error;
use crate::services::{JwtService, JwtTokenType};
#[derive(Debug)]
pub struct AuthedUser {
id: Uuid,
tenant: Uuid,
role: UserRoles,
}
impl FromRequest for AuthedUser {
type Error = HttpResponse;
type Future = Ready<Result<AuthedUser, Self::Error>>;
fn from_request(req: &HttpRequest, _payload: &mut Payload) -> Self::Future {
let authorization_header = req.headers().get("Authorization").ok_or(|_| {
tracing::error!("No 'Authorization' header present");
ready(Err(unauthorized_error()))
})?;
// Extract JWT token from 'Authorization header'
let bearer_token: Vec<&str> = authorization_header
.to_str()
.map_err(|e| {
tracing::error!("Header should only contain ASCII characters: {}", e);
ready(Err(unauthorized_error()))
})?
.split_whitespace()
.collect();
// Make sure that it is a Bearer token
if bearer_token[0] != "Bearer" {
tracing::error!("Authorization header is not a Bearer token");
return ready(Err(unauthorized_error()));
}
let token = bearer_token[1];
// Get secret key to decode JWT token
let token_data = JwtService::decode(token, JwtTokenType::AccessToken).map_err(|e| {
tracing::error!("Header should only contain ASCII characters: {}", e);
ready(Err(unauthorized_error()))
})?;
ready(Ok(Self {
id: token_data.user_id,
tenant: token_data.tenant_id,
role: token_data.user_role,
}))
}
}
I get the following errors:
error: the `?` operator can only be used in a method that returns `Result` or `Option` (or another type that implements `FromResidual`)
note: required because of the requirements on the impl of `std::convert::From<HttpResponse>` for `actix_web::Error`
label: the trait `ResponseError` is not implemented for `HttpResponse`
How can I return the errors in this situation? The function unauthorized_error
simply returns HttpResponse::Unauthorized().finish()