mirror of
https://git.asonix.dog/asonix/http-signature-normalization.git
synced 2024-11-27 20:01:00 +00:00
123 lines
4.1 KiB
Markdown
123 lines
4.1 KiB
Markdown
# Http Signature Normalization Actix-Web Extractor
|
|
_Experimental Extractor for request signatures_
|
|
|
|
- [crates.io](https://crates.io/crates/http-signature-normalization-actix-extractor)
|
|
- [docs.rs](https://docs.rs/http-signature-normalization-actix-extractor)
|
|
- [Hit me up on Mastodon](https://masto.asonix.dog/@asonix)
|
|
|
|
Http Signature Normalization is a minimal-dependency crate for producing HTTP Signatures with user-provided signing and verification. The API is simple; there's a series of steps for creation and verification with types that ensure reasonable usage. This library takes a different approach from the other implementation, which prefers Middlewares.
|
|
|
|
## Usage
|
|
|
|
This crate provides extensions the ClientRequest type from Actix Web, and provides middlewares for verifying HTTP Signatures, and optionally, Digest headers
|
|
|
|
#### First, add this crate to your dependencies
|
|
```toml
|
|
actix-rt = "2.7.0"
|
|
actix-web = "4.0.0"
|
|
thiserror = "1"
|
|
http-signature-normalization-actix-extractor = "0.1.0"
|
|
sha2 = "0.10"
|
|
```
|
|
|
|
#### Then, use it in your client
|
|
|
|
```rust
|
|
use actix_web::{http::StatusCode, web, App, HttpRequest, HttpResponse, HttpServer, ResponseError};
|
|
use http_signature_normalization_actix_extractor::{
|
|
Algorithm, Config, ConfigGenerator, DeprecatedAlgorithm, Signed, VerifyKey,
|
|
};
|
|
use sha2::Sha256;
|
|
|
|
#[actix_web::main]
|
|
async fn main() -> std::io::Result<()> {
|
|
HttpServer::new(|| App::new().route("/", web::post().to(protected)))
|
|
.bind("127.0.0.1:8010")?
|
|
.run()
|
|
.await
|
|
}
|
|
|
|
async fn protected(signed_request: Signed<String, Cfg, Sha256, Key>) -> &'static str {
|
|
let (value, signature) = signed_request.into_parts();
|
|
|
|
println!("{}", value);
|
|
println!("{:#?}", signature);
|
|
|
|
"hewwo, mr obama"
|
|
}
|
|
|
|
pub struct Cfg;
|
|
|
|
#[derive(Debug)]
|
|
pub struct Key;
|
|
|
|
#[derive(Debug, thiserror::Error)]
|
|
pub enum VerifyError {
|
|
#[error("Unsupported algorithm")]
|
|
Algorithm,
|
|
|
|
#[error("Couldn't decode signature")]
|
|
Decode,
|
|
|
|
#[error("Invalid key")]
|
|
Key,
|
|
}
|
|
|
|
impl ConfigGenerator for Cfg {
|
|
fn config() -> Config {
|
|
Config::new().require_header("accept")
|
|
}
|
|
}
|
|
|
|
#[async_trait::async_trait(?Send)]
|
|
impl VerifyKey for Key {
|
|
type Error = VerifyError;
|
|
|
|
async fn init(
|
|
_: &HttpRequest,
|
|
key_id: &str,
|
|
algorithm: Option<&Algorithm>,
|
|
) -> Result<Self, Self::Error> {
|
|
match algorithm {
|
|
Some(Algorithm::Hs2019 | Algorithm::Deprecated(DeprecatedAlgorithm::RsaSha256)) => (),
|
|
_ => return Err(VerifyError::Algorithm),
|
|
};
|
|
|
|
if key_id != "my-key-id" {
|
|
return Err(VerifyError::Key);
|
|
}
|
|
|
|
Ok(Key)
|
|
}
|
|
|
|
fn verify(&mut self, signature: &str, signing_string: &str) -> Result<bool, Self::Error> {
|
|
use subtle::ConstantTimeEq;
|
|
|
|
let decoded = base64::decode(&signature).map_err(|_| VerifyError::Decode)?;
|
|
|
|
Ok(decoded.ct_eq(signing_string.as_bytes()).into())
|
|
}
|
|
}
|
|
|
|
impl ResponseError for VerifyError {
|
|
fn status_code(&self) -> StatusCode {
|
|
StatusCode::BAD_REQUEST
|
|
}
|
|
|
|
fn error_response(&self) -> HttpResponse {
|
|
HttpResponse::BadRequest().finish()
|
|
}
|
|
}
|
|
```
|
|
|
|
### Contributing
|
|
Feel free to open issues for anything you find an issue with. Please note that any contributed code will be licensed under the AGPLv3.
|
|
|
|
### License
|
|
Copyright © 2022 Riley Trautman
|
|
|
|
HTTP Signature Normalization Actix Extractor is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
|
|
|
HTTP Signature Normalization Actix Extractor is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. This file is part of HTTP Signature Normalization Actix Extractor.
|
|
|
|
You should have received a copy of the GNU General Public License along with HTTP Signature Normalization Actix Extractor. If not, see [http://www.gnu.org/licenses/](http://www.gnu.org/licenses/).
|