diff options
author | Martin Fischer <martin@push-f.com> | 2022-07-27 14:29:00 +0200 |
---|---|---|
committer | Martin Fischer <martin@push-f.com> | 2022-07-27 14:29:00 +0200 |
commit | 70a6127d48baa86c724d467943e64074c9e41f18 (patch) | |
tree | 9070183319448c56811bc6cdc1cec1ab3e82eb81 | |
parent | dadd46143e7a0fb9d512d5601a6f8fef553fd82a (diff) |
remove security module
-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()); - } -} |