http-signature-normalization/http-signature-normalization-actix/src/lib.rs
2019-09-13 17:56:06 -05:00

141 lines
3.6 KiB
Rust

use actix_web::http::{
header::{HeaderMap, InvalidHeaderValue, ToStrError},
uri::PathAndQuery,
Method,
};
use failure::Fail;
use futures::future::IntoFuture;
use std::{collections::BTreeMap, fmt::Display};
mod sign;
#[cfg(feature = "digest")]
pub mod digest;
pub mod create;
pub mod middleware;
pub mod prelude {
pub use crate::{
middleware::VerifySignature, verify::Unverified, Config, Sign, SignatureVerify, Verify,
VerifyError,
};
#[cfg(feature = "digest")]
pub use crate::digest::{
middleware::VerifyDigest, DigestClient, DigestCreate, DigestPart, DigestVerify, SignExt,
};
pub use actix_web::http::header::{InvalidHeaderValue, ToStrError};
}
pub mod verify;
use self::{
create::Unsigned,
verify::{Algorithm, Unverified},
};
pub trait Verify {
fn begin_verify(&self, config: &Config) -> Result<Unverified, VerifyError>;
}
pub trait SignatureVerify {
type Error: actix_web::ResponseError;
type Future: IntoFuture<Item = bool, Error = Self::Error>;
fn signature_verify(
&mut self,
algorithm: Option<Algorithm>,
key_id: &str,
signature: &str,
signing_string: &str,
) -> Self::Future;
}
pub trait Sign {
fn authorization_signature<F, E, K>(self, config: &Config, key_id: K, f: F) -> Result<Self, E>
where
F: FnOnce(&str) -> Result<String, E>,
E: From<ToStrError> + From<InvalidHeaderValue>,
K: Display,
Self: Sized;
fn signature<F, E, K>(self, config: &Config, key_id: K, f: F) -> Result<Self, E>
where
F: FnOnce(&str) -> Result<String, E>,
E: From<ToStrError> + From<InvalidHeaderValue>,
K: Display,
Self: Sized;
}
#[derive(Clone, Debug, Default)]
pub struct Config {
pub config: http_signature_normalization::Config,
}
#[derive(Debug, Fail)]
pub enum VerifyError {
#[fail(display = "Signature error, {}", _0)]
Sig(#[cause] http_signature_normalization::VerifyError),
#[fail(display = "Failed to read header, {}", _0)]
Header(#[cause] ToStrError),
}
impl Config {
pub fn begin_sign(
&self,
method: &Method,
path_and_query: Option<&PathAndQuery>,
headers: HeaderMap,
) -> Result<Unsigned, ToStrError> {
let headers = headers
.iter()
.map(|(k, v)| v.to_str().map(|v| (k.to_string(), v.to_string())))
.collect::<Result<BTreeMap<_, _>, ToStrError>>()?;
let path_and_query = path_and_query
.map(|p| p.to_string())
.unwrap_or(String::from("/"));
let unsigned = self
.config
.begin_sign(&method.to_string(), &path_and_query, headers);
Ok(Unsigned { unsigned })
}
pub fn begin_verify(
&self,
method: &Method,
path_and_query: Option<&PathAndQuery>,
headers: HeaderMap,
) -> Result<Unverified, VerifyError> {
let headers = headers
.iter()
.map(|(k, v)| v.to_str().map(|v| (k.to_string(), v.to_string())))
.collect::<Result<BTreeMap<_, _>, ToStrError>>()?;
let path_and_query = path_and_query
.map(|p| p.to_string())
.unwrap_or(String::from("/"));
let unverified = self
.config
.begin_verify(&method.to_string(), &path_and_query, headers)?;
Ok(unverified)
}
}
impl From<http_signature_normalization::VerifyError> for VerifyError {
fn from(e: http_signature_normalization::VerifyError) -> Self {
VerifyError::Sig(e)
}
}
impl From<ToStrError> for VerifyError {
fn from(e: ToStrError) -> Self {
VerifyError::Header(e)
}
}