use actix::System; use actix_web::{web, App, HttpResponse, HttpServer, ResponseError}; use failure::Fail; use http_signature_normalization_actix::{prelude::*, verify::Algorithm}; use sha2::{Digest, Sha256}; #[derive(Clone, Debug)] struct MyVerify; impl SignatureVerify for MyVerify { type Error = MyError; type Future = Result; fn signature_verify( &mut self, algorithm: Option, key_id: &str, signature: &str, signing_string: &str, ) -> Self::Future { match algorithm { Some(Algorithm::Hs2019) => (), _ => return Err(MyError::Algorithm), }; if key_id != "my-key-id" { return Err(MyError::Key); } let decoded = base64::decode(signature).map_err(|_| MyError::Decode)?; Ok(decoded == signing_string.as_bytes()) } } fn index(_: (DigestVerified, SignatureVerified)) -> &'static str { "Eyyyyup" } fn main() -> Result<(), Box> { let sys = System::new("server-example"); let config = Config::default(); HttpServer::new(move || { App::new() .wrap(VerifyDigest::new(Sha256::new()).optional()) .wrap( VerifySignature::new(MyVerify, config.clone()) .authorization() .optional(), ) .route("/", web::post().to(index)) }) .bind("127.0.0.1:8010")? .start(); sys.run()?; Ok(()) } #[derive(Debug, Fail)] enum MyError { #[fail(display = "Failed to verify, {}", _0)] Verify(#[cause] PrepareVerifyError), #[fail(display = "Unsupported algorithm")] Algorithm, #[fail(display = "Couldn't decode signature")] Decode, #[fail(display = "Invalid key")] Key, } impl ResponseError for MyError { fn error_response(&self) -> HttpResponse { HttpResponse::BadRequest().finish() } fn render_response(&self) -> HttpResponse { self.error_response() } } impl From for MyError { fn from(e: PrepareVerifyError) -> Self { MyError::Verify(e) } }