actix_web_detached_jws_middleware/lib.rs
1//! Actix-web middleware to sign and verify detached jws ([Detached JWS](https://medium.com/gin-and-tonic/implementing-detached-json-web-signature-9ca5665ddcfc))
2//!
3//! # Example:
4//! ```ignore
5//! use std::{io::Read, sync::Arc};
6//!
7//! use actix_web::{
8//! dev::ServiceRequest,
9//! error::{ErrorForbidden, ErrorInternalServerError},
10//! web::{self},
11//! App, Error, HttpServer, Responder,
12//! };
13//! use actix_web_detached_jws_middleware::{
14//! DetachedJwsSign, DetachedJwsSignConfig, DetachedJwsVerify, DetachedJwsVerifyConfig,
15//! VerifyErrorType,
16//! };
17//! use detached_jws::JwsHeader;
18//! use futures::future::{ready, Ready};
19//! use openssl::{
20//! hash::MessageDigest,
21//! pkcs12::{ParsedPkcs12, Pkcs12},
22//! rsa::Padding,
23//! sign::{Signer, Verifier},
24//! };
25//!
26//! async fn index() -> impl Responder {
27//! "this_is_response_body"
28//! }
29//!
30//! #[actix_web::main]
31//! async fn main() -> std::io::Result<()> {
32//! let config = Arc::new(Config::new());
33//!
34//! HttpServer::new(move || {
35//! App::new()
36//! .service(
37//! web::resource("/protected")
38//! .wrap(DetachedJwsVerify::new(config.clone()))
39//! .wrap(DetachedJwsSign::new(config.clone()))
40//! .route(web::post().to(index)),
41//! )
42//! .service(web::resource("/simple").route(web::post().to(index)))
43//! })
44//! .bind("127.0.0.1:8080")?
45//! .run()
46//! .await
47//! }
48//!
49//! struct Config {
50//! cert_rs256: ParsedPkcs12,
51//! cert_ps256: ParsedPkcs12,
52//! }
53//!
54//! impl Config {
55//! fn new() -> Self {
56//! let load_pkcs12 = |path, pass| {
57//! let mut file = std::fs::File::open(path).unwrap();
58//! let mut pkcs12 = vec![];
59//! file.read_to_end(&mut pkcs12).unwrap();
60//!
61//! let pkcs12 = Pkcs12::from_der(&pkcs12).unwrap();
62//! pkcs12.parse(pass).unwrap()
63//! };
64//!
65//! Self {
66//! cert_rs256: load_pkcs12("examples/cert_for_rs256.pfx", "123456"),
67//! cert_ps256: load_pkcs12("examples/cert_for_ps256.pfx", "123456"),
68//! }
69//! }
70//! }
71//!
72//! impl<'a> DetachedJwsVerifyConfig<'a> for Config {
73//! type Verifier = Verifier<'a>;
74//! type ErrorHandler = Ready<Error>;
75//!
76//! fn get_verifier(&'a self, h: &JwsHeader) -> Option<Self::Verifier> {
77//! match h.get("alg")?.as_str()? {
78//! "RS256" => {
79//! let mut verifier =
80//! Verifier::new(MessageDigest::sha256(), &self.cert_rs256.pkey).unwrap();
81//! verifier.set_rsa_padding(Padding::PKCS1).unwrap();
82//! Some(verifier)
83//! }
84//! "PS256" => {
85//! let mut verifier =
86//! Verifier::new(MessageDigest::sha256(), &self.cert_ps256.pkey).unwrap();
87//! verifier.set_rsa_padding(Padding::PKCS1_PSS).unwrap();
88//! Some(verifier)
89//! }
90//! _ => None,
91//! }
92//! }
93//!
94//! fn error_handler(
95//! &'a self,
96//! _: &'a mut ServiceRequest,
97//! error: VerifyErrorType,
98//! ) -> Self::ErrorHandler {
99//! ready(match error {
100//! VerifyErrorType::HeaderNotFound => ErrorForbidden("Header Not Found"),
101//! VerifyErrorType::IncorrectSignature => ErrorForbidden("Incorrect Signature"),
102//! VerifyErrorType::Other(e) => ErrorInternalServerError(e),
103//! })
104//! }
105//! }
106//!
107//! impl<'a> DetachedJwsSignConfig<'a> for Config {
108//! type Signer = Signer<'a>;
109//!
110//! fn get_signer(&'a self) -> (Self::Signer, String, JwsHeader) {
111//! let mut signer = Signer::new(MessageDigest::sha256(), &self.cert_ps256.pkey).unwrap();
112//! signer.set_rsa_padding(Padding::PKCS1_PSS).unwrap();
113//!
114//! (signer, "PS256".into(), JwsHeader::new())
115//! }
116//! }
117//!
118//! ```
119pub mod sign;
120pub mod verify;
121
122pub use crate::sign::{DetachedJwsSign, DetachedJwsSignConfig};
123pub use crate::verify::{DetachedJwsVerify, DetachedJwsVerifyConfig, VerifyErrorType};