[−][src]Crate http_signature_normalization_actix
Integration of Http Signature Normalization with Actix Web
This library provides middlewares for verifying HTTP Signature headers and, optionally, Digest
headers with the digest
feature enabled. It also extends actix_web's ClientRequest type to
add signatures and digests to the request
Use it in a server
use actix_web::{http::StatusCode, web, App, HttpResponse, HttpServer, ResponseError}; use futures::future::{err, ok, Ready}; use http_signature_normalization_actix::prelude::*; use sha2::{Digest, Sha256}; #[derive(Clone, Debug)] struct MyVerify; impl SignatureVerify for MyVerify { type Error = MyError; type Future = Ready<Result<bool, Self::Error>>; fn signature_verify( &mut self, algorithm: Option<Algorithm>, 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), }; ok(decoded == signing_string.as_bytes()) } } async fn index((_, sig_verified): (DigestVerified, SignatureVerified)) -> &'static str { println!("Signature verified for {}", sig_verified.key_id()); "Eyyyyup" } #[actix_rt::main] async fn main() -> Result<(), Box<dyn std::error::Error>> { 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")? .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() } }
Use it in a client
use actix_web::{client::Client, error::BlockingError}; use http_signature_normalization_actix::prelude::*; use sha2::{Digest, Sha256}; #[actix_rt::main] async fn main() -> Result<(), Box<dyn std::error::Error>> { let config = Config::default(); let digest = Sha256::new(); let mut response = Client::default() .post("http://127.0.0.1:8010/") .header("User-Agent", "Actix Web") .set(actix_web::http::header::Date(SystemTime::now().into())) .signature_with_digest(config, "my-key-id", digest, "Hewwo-owo", |s| { println!("Signing String\n{}", s); Ok(base64::encode(s)) as Result<_, MyError> }) .await? .send() .await .map_err(|e| { eprintln!("Error, {}", e); MyError::SendRequest })?; let body = response.body().await.map_err(|e| { eprintln!("Error, {}", e); MyError::Body })?; println!("{:?}", body); Ok(()) } #[derive(Debug, thiserror::Error)] pub enum MyError { #[error("Failed to create signing string, {0}")] Convert(#[from] PrepareSignError), #[error("Failed to create header, {0}")] Header(#[from] InvalidHeaderValue), #[error("Failed to send request")] SendRequest, #[error("Failed to retrieve request body")] Body, #[error("Blocking operation was canceled")] Canceled, } impl From<BlockingError<MyError>> for MyError { fn from(b: BlockingError<MyError>) -> Self { match b { BlockingError::Error(e) => e, _ => MyError::Canceled, } } }
Modules
create | Types for signing requests with Actix Web |
digest | Types and Traits for creating and verifying Digest headers |
middleware | Types for verifying requests with Actix Web |
prelude | Useful types and traits for using this library in Actix Web |
verify | Types for Verifying an HTTP Signature |
Structs
Config | Configuration for signing and verifying signatures |
RequiredError | Failed to build a signing string due to missing required headers |
Enums
PrepareSignError | An error when preparing to sign a request |
PrepareVerifyError | An error when preparing to verify a request |
Traits
Sign | A trait implemented by the Actix Web ClientRequest type to add an HTTP signature to the request |
SignatureVerify | A trait for verifying signatures |