use actix_web::{ http::StatusCode, middleware::Logger, web, App, HttpRequest, HttpResponse, HttpServer, ResponseError, }; use futures::future::{err, ok, Ready}; use http_signature_normalization_actix::prelude::*; use log::info; use sha2::{Digest, Sha256}; #[derive(Clone, Debug)] struct MyVerify; impl SignatureVerify for MyVerify { type Error = MyError; type Future = Ready>; fn signature_verify( &mut self, algorithm: Option, key_id: String, signature: String, signing_string: String, ) -> Self::Future { match algorithm { Some(Algorithm::Hs2019) => (), _ => return err(MyError::Algorithm), }; if key_id != "my-key-id" { return err(MyError::Key); } let decoded = match base64::decode(&signature) { Ok(decoded) => decoded, Err(_) => return err(MyError::Decode), }; println!("Signing String\n{}", signing_string); ok(decoded == signing_string.as_bytes()) } } async fn index( (_, sig_verified): (DigestVerified, SignatureVerified), req: HttpRequest, _body: web::Bytes, ) -> &'static str { info!("Verified request for {}", sig_verified.key_id()); info!("{:?}", req); "Eyyyyup" } #[actix_rt::main] async fn main() -> Result<(), Box> { std::env::set_var("RUST_LOG", "info"); pretty_env_logger::init(); let config = Config::default().require_header("accept"); HttpServer::new(move || { App::new() .wrap(VerifyDigest::new(Sha256::new()).optional()) .wrap(VerifySignature::new(MyVerify, config.clone()).optional()) .wrap(Logger::default()) .route("/", web::post().to(index)) }) .bind("127.0.0.1:8010")? .run() .await?; Ok(()) } #[derive(Debug, thiserror::Error)] enum MyError { #[error("Failed to verify, {0}")] Verify(#[from] PrepareVerifyError), #[error("Unsupported algorithm")] Algorithm, #[error("Couldn't decode signature")] Decode, #[error("Invalid key")] Key, } impl ResponseError for MyError { fn status_code(&self) -> StatusCode { StatusCode::BAD_REQUEST } fn error_response(&self) -> HttpResponse { HttpResponse::BadRequest().finish() } }