diff options
| -rw-r--r-- | Cargo.toml | 6 | ||||
| -rw-r--r-- | README.md | 41 | ||||
| -rw-r--r-- | src/lib.rs | 4 | ||||
| -rw-r--r-- | src/security.rs | 57 | 
4 files changed, 0 insertions, 108 deletions
@@ -14,7 +14,6 @@ keywords = ["web", "cookie", "hyper", "hmac"]  [features]  hyper_body = ["hyper"]  hyper_body_json = ["serde_json", "hyper_body"] -security = ["base64", "hmac", "rand", "sha2"]  [dependencies]  http = "0.2" @@ -27,11 +26,6 @@ thiserror = "1.0"  hyper = { version = "0.14", optional = true }  serde_json = { version = "1.0", optional = true } -base64 = { version = "0.13", optional = true } -hmac = { version = "0.12", optional = true } -rand = { version = "0.8", optional = true } -sha2 = { version = "0.10", optional = true } -  [package.metadata.docs.rs]  all-features = true  rustdoc-args = ["--cfg", "docsrs"] @@ -12,11 +12,6 @@ with [Serde](https://serde.rs/) you can enable the following feature flags:    `into_form` method for parsing data submitted from HTML forms.  - `hyper_body_json` additionaly provides an `into_json` method -With the `security` feature Sputnik furthermore provides what's necessary to -implement [signed & expiring cookies](#signed--expiring-cookies) with the -expiry date encoded into the signed cookie value, providing a more -lightweight alternative to JWT if you don't need interoperability. -  Sputnik does **not** handle routing because even complex routing can be quite  easily implemented with nested `match` blocks. If you want a more high-level  router, you can check out the [router crates](https://crates.io/keywords/router). @@ -123,39 +118,3 @@ async fn main() {      server.await;  }  ``` - -## Signed & expiring cookies - -After a successful authentication you can build a session id cookie for -example as follows: - -```rust -let expiry_date = SystemTime::now() + Duration::from_secs(24 * 60 * 60); -let mut cookie = Cookie::new("userid", -    key.sign( -        &encode_expiring_claim(&userid, expiry_date) -    )); -headers.set_cookie(Cookie{ -    name: "userid".into(), -    value: key.sign( -        &encode_expiring_claim(&userid, expiry_date) -    ), -    secure: Some(true), -    expires: Some(expiry_date), -    same_site: SameSite::Lax, -}); -``` - -This session id cookie can then be retrieved and verified as follows: - -```rust -let userid = req.cookies().find(|(name, _value)| *name == "userid") -    .ok_or_else(|| "expected userid cookie".to_owned()) -    .and_then(|(_name, value)| key.verify(value)) -    .and_then(|value| decode_expiring_claim(value).map_err(|e| format!("failed to decode userid cookie: {}", e))); -``` - -Tip: If you want to store multiple claims in the cookie, you can -(de)serialize a struct with [serde_json](https://docs.serde.rs/serde_json/). -This approach can pose a lightweight alternative to JWT, if you don't care -about the standardization aspect. @@ -11,10 +11,6 @@ pub use mime;  pub mod request;  pub mod response; -#[cfg(feature = "security")] -#[cfg_attr(docsrs, doc(cfg(feature = "security")))] -pub mod security; -  #[cfg(feature = "hyper_body")]  #[cfg_attr(docsrs, doc(cfg(feature = "hyper_body")))]  pub mod hyper_body; diff --git a/src/security.rs b/src/security.rs deleted file mode 100644 index bc3b381..0000000 --- a/src/security.rs +++ /dev/null @@ -1,57 +0,0 @@ -//! Provides [`Key`] and functions to encode & decode expiring claims. - -pub use signed::Key; -pub use std::time::{SystemTime, UNIX_EPOCH}; - -mod signed; - -/// Join a string and an expiry date together into a string. -pub fn encode_expiring_claim(claim: &str, expiry_date: SystemTime) -> String { -    format!( -        "{}:{}", -        claim, -        expiry_date.duration_since(UNIX_EPOCH).unwrap().as_secs() -    ) -} - -/// Extract the string, failing if the expiry date is in the past. -pub fn decode_expiring_claim(value: &str) -> Result<&str, &'static str> { -    let mut parts = value.rsplitn(2, ':'); -    let expiry_date = parts -        .next() -        .expect("first .rsplitn().next() is expected to return Some"); -    let claim = parts.next().ok_or("expected colon")?; -    let expiry_date: u64 = expiry_date -        .parse() -        .map_err(|_| "failed to parse timestamp")?; - -    if expiry_date -        > SystemTime::now() -            .duration_since(UNIX_EPOCH) -            .unwrap() -            .as_secs() -    { -        Ok(claim) -    } else { -        Err("token is expired") -    } -} - -#[cfg(test)] -mod tests { -    use std::time::{Duration, SystemTime}; - -    #[test] -    fn test_expiring_claim() { -        for claim in vec!["test", "", "foo:bar"] { -            let encoded_claim = -                super::encode_expiring_claim(claim, SystemTime::now() + Duration::from_secs(60)); -            assert_eq!(super::decode_expiring_claim(&encoded_claim).unwrap(), claim); - -            let encoded_claim = -                super::encode_expiring_claim(claim, SystemTime::now() - Duration::from_secs(60)); -            assert!(super::decode_expiring_claim(&encoded_claim).is_err()); -        } -        assert!(super::decode_expiring_claim("test".into()).is_err()); -    } -}  | 
