diff --git a/Cargo.lock b/Cargo.lock index f0e5b3d..652ab3d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,41 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" +[[package]] +name = "aead" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +dependencies = [ + "crypto-common", + "generic-array", +] + +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "aes-gcm" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1" +dependencies = [ + "aead", + "aes", + "cipher", + "ctr", + "ghash", + "subtle", +] + [[package]] name = "ahash" version = "0.8.11" @@ -426,6 +461,16 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", +] + [[package]] name = "clang-sys" version = "1.8.1" @@ -515,7 +560,14 @@ version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747" dependencies = [ + "aes-gcm", + "base64 0.22.1", + "hkdf", + "hmac", "percent-encoding", + "rand", + "sha2", + "subtle", "time", "version_check", ] @@ -576,9 +628,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ "generic-array", + "rand_core", "typenum", ] +[[package]] +name = "ctr" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" +dependencies = [ + "cipher", +] + [[package]] name = "data-encoding" version = "2.6.0" @@ -829,6 +891,16 @@ dependencies = [ "wasi", ] +[[package]] +name = "ghash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1" +dependencies = [ + "opaque-debug", + "polyval", +] + [[package]] name = "gimli" version = "0.31.1" @@ -905,6 +977,24 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hkdf" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" +dependencies = [ + "hmac", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + [[package]] name = "home" version = "0.5.11" @@ -1167,6 +1257,15 @@ dependencies = [ "hashbrown 0.15.2", ] +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "generic-array", +] + [[package]] name = "ipnet" version = "2.10.1" @@ -1543,6 +1642,12 @@ version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + [[package]] name = "openssl" version = "0.10.68" @@ -1702,6 +1807,18 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" +[[package]] +name = "polyval" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" +dependencies = [ + "cfg-if", + "cpufeatures", + "opaque-debug", + "universal-hash", +] + [[package]] name = "portable-atomic" version = "1.10.0" @@ -1725,9 +1842,9 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.25" +version = "0.2.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" +checksum = "ca6adb3e4b07458f4d39b34c0c26c2a42ba3c89deb541b8cb8977231b689de5c" dependencies = [ "proc-macro2", "syn 2.0.95", @@ -2605,6 +2722,16 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" +[[package]] +name = "universal-hash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" +dependencies = [ + "crypto-common", + "subtle", +] + [[package]] name = "untrusted" version = "0.9.0" diff --git a/Cargo.toml b/Cargo.toml index 8756e43..bb89102 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,7 @@ serde_json = "1" tokio = { version = "1", features = ["macros", "rt-multi-thread"] } tokio-rusqlite = "0.6" tower-http = { version = "0.6", features = ["trace"] } -tower-sessions = "0.14.0" +tower-sessions = { version = "0.14.0", features = ["private"] } tracing = "0.1" tracing-subscriber = { version = "0.3", features = ["env-filter"] } uuid = "1" diff --git a/flake.lock b/flake.lock index e2924f7..b23a089 100644 --- a/flake.lock +++ b/flake.lock @@ -22,15 +22,14 @@ "gitignore": "gitignore", "nixpkgs": [ "nixpkgs" - ], - "nixpkgs-stable": "nixpkgs-stable" + ] }, "locked": { - "lastModified": 1734797603, - "narHash": "sha256-ulZN7ps8nBV31SE+dwkDvKIzvN6hroRY8sYOT0w+E28=", + "lastModified": 1735882644, + "narHash": "sha256-3FZAG+pGt3OElQjesCAWeMkQ7C/nB1oTHLRQ8ceP110=", "owner": "cachix", "repo": "git-hooks.nix", - "rev": "f0f0dc4920a903c3e08f5bdb9246bb572fcae498", + "rev": "a5a961387e75ae44cc20f0a57ae463da5e959656", "type": "github" }, "original": { @@ -62,11 +61,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1735471104, - "narHash": "sha256-0q9NGQySwDQc7RhAV2ukfnu7Gxa5/ybJ2ANT8DQrQrs=", + "lastModified": 1735834308, + "narHash": "sha256-dklw3AXr3OGO4/XT1Tu3Xz9n/we8GctZZ75ZWVqAVhk=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "88195a94f390381c6afcdaa933c2f6ff93959cb4", + "rev": "6df24922a1400241dae323af55f30e4318a6ca65", "type": "github" }, "original": { @@ -75,22 +74,6 @@ "type": "indirect" } }, - "nixpkgs-stable": { - "locked": { - "lastModified": 1730741070, - "narHash": "sha256-edm8WG19kWozJ/GqyYx2VjW99EdhjKwbY3ZwdlPAAlo=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "d063c1dd113c91ab27959ba540c0d9753409edf3", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixos-24.05", - "repo": "nixpkgs", - "type": "github" - } - }, "root": { "inputs": { "git-hooks": "git-hooks", diff --git a/justfile b/justfile index 44e29d7..77f8108 100644 --- a/justfile +++ b/justfile @@ -26,7 +26,7 @@ build: update: update_usage cargo update -run: +run port="8080": #!/usr/bin/env bash export STATE_DIRECTORY={{justfile_directory()}}/state mkdir -p $STATE_DIRECTORY @@ -34,4 +34,4 @@ run: [[ -f $password_file ]] || echo user:$(printf "password" | argon2 $(openssl rand -hex 16) -id -e) > $password_file session_secret_file=$STATE_DIRECTORY/session_secret [[ -f $session_secret_file ]] || openssl rand -hex 64 > $session_secret_file - cargo watch --exec "run -- --rp-id=localhost --rp-origin=http://localhost:8080 --password-file=$password_file --session-secret-file=$session_secret_file" + cargo watch --exec "run -- --address=[::]:{{port}} --rp-id=localhost --rp-origin=http://localhost:{{port}} --password-file=$password_file --session-secret-file=$session_secret_file" diff --git a/src/app.rs b/src/app.rs index 237f7ee..a5ae583 100644 --- a/src/app.rs +++ b/src/app.rs @@ -294,7 +294,6 @@ impl App { auth_result: AuthenticationResult, ) -> Result<(), AppError> { let cred_id = serde_json::to_string(auth_result.cred_id())?; - let cred_id_ = cred_id.clone(); // TODO(jared): don't do this let cred_json = self .db @@ -302,18 +301,20 @@ impl App { Ok(conn.query_row( r#"select value from credentials where value->'$.cred.cred_id' = ?1"#, - (cred_id_,), + (cred_id,), |row| row.get::<_, String>(0), )) }) .await??; - let mut credential = serde_json::from_str::(&cred_json)?; - if credential.update_credential(&auth_result).is_none() { + let mut passkey = serde_json::from_str::(&cred_json)?; + if passkey.update_credential(&auth_result).is_none() { return Err(AppError::MismatchingCredential); } - let cred_json = serde_json::to_string(&credential)?; + let cred_id = serde_json::to_string(passkey.cred_id())?; + + let cred_json = serde_json::to_string(&passkey)?; _ = self .db diff --git a/src/main.rs b/src/main.rs index 1b0481f..b42fc1a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -21,7 +21,7 @@ use std::{collections::HashMap, env, net::SocketAddr, path::PathBuf, sync::Arc}; use tokio::sync::RwLock; use tokio_rusqlite::Connection; use tower_http::trace::TraceLayer; -use tower_sessions::SessionManagerLayer; +use tower_sessions::{cookie::Key, SessionManagerLayer}; use tracing::debug; use tracing_subscriber::{fmt, prelude::*, EnvFilter}; use webauthn_rs::{prelude::Url, WebauthnBuilder}; @@ -99,8 +99,10 @@ async fn main() -> anyhow::Result<()> { let store = session::SqliteSessionStore::new(db.clone()); store.init().await?; - // TODO(jared): std::fs::read_to_string(cli.session_secret_file)?.as_bytes(), let session_layer = SessionManagerLayer::new(store) + .with_private(Key::try_from( + std::fs::read_to_string(cli.session_secret_file)?.as_bytes(), + )?) .with_always_save(false) .with_domain(cli.rp_id);