From 8ab969a3de2ffa559f5a050ad3534abc2c1b175a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Baylac=20Jacqu=C3=A9?= Date: Wed, 27 Sep 2023 18:31:17 +0200 Subject: [PATCH] wip --- Cargo.lock | 335 ------------------------------------------- Cargo.toml | 1 - src/app/mod.rs | 21 --- src/filters/mod.rs | 43 ------ src/handlers/mod.rs | 52 ++++--- src/main.rs | 32 +++-- src/templates/mod.rs | 7 +- 7 files changed, 56 insertions(+), 435 deletions(-) delete mode 100644 src/filters/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 25127e8..0377296 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -340,22 +340,6 @@ dependencies = [ "alloc-stdlib", ] -[[package]] -name = "buf_redux" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b953a6887648bb07a535631f2bc00fbdb2a2216f135552cb3f534ed136b9c07f" -dependencies = [ - "memchr", - "safemem", -] - -[[package]] -name = "byteorder" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" - [[package]] name = "bytes" version = "1.3.0" @@ -569,15 +553,6 @@ dependencies = [ "libc", ] -[[package]] -name = "fastrand" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" -dependencies = [ - "instant", -] - [[package]] name = "flate2" version = "1.0.26" @@ -618,16 +593,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "futures-channel" -version = "0.3.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed" -dependencies = [ - "futures-core", - "futures-sink", -] - [[package]] name = "futures-core" version = "0.3.25" @@ -653,11 +618,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6" dependencies = [ "futures-core", - "futures-sink", "futures-task", "pin-project-lite", "pin-utils", - "slab", ] [[package]] @@ -726,31 +689,6 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" -[[package]] -name = "headers" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3e372db8e5c0d213e0cd0b9be18be2aca3d44cf2fe30a9d46a65581cd454584" -dependencies = [ - "base64 0.13.1", - "bitflags", - "bytes", - "headers-core", - "http", - "httpdate", - "mime", - "sha1", -] - -[[package]] -name = "headers-core" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" -dependencies = [ - "http", -] - [[package]] name = "heck" version = "0.4.0" @@ -792,17 +730,6 @@ dependencies = [ "itoa", ] -[[package]] -name = "http-body" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" -dependencies = [ - "bytes", - "http", - "pin-project-lite", -] - [[package]] name = "httparse" version = "1.8.0" @@ -815,30 +742,6 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" -[[package]] -name = "hyper" -version = "0.14.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "034711faac9d2166cb1baf1a2fb0b60b1f277f8492fd72176c17f3515e1abd3c" -dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "socket2", - "tokio", - "tower-service", - "tracing", - "want", -] - [[package]] name = "idna" version = "0.3.0" @@ -859,15 +762,6 @@ dependencies = [ "hashbrown", ] -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if", -] - [[package]] name = "io-lifetimes" version = "1.0.3" @@ -978,16 +872,6 @@ version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" -[[package]] -name = "mime_guess" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" -dependencies = [ - "mime", - "unicase", -] - [[package]] name = "minimal-lexical" version = "0.2.1" @@ -1015,24 +899,6 @@ dependencies = [ "windows-sys", ] -[[package]] -name = "multipart" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00dec633863867f29cb39df64a397cdf4a6354708ddd7759f70c7fb51c5f9182" -dependencies = [ - "buf_redux", - "httparse", - "log", - "mime", - "mime_guess", - "quick-error", - "rand", - "safemem", - "tempfile", - "twoway", -] - [[package]] name = "nix-cache-bucket-gc" version = "0.1.0" @@ -1044,7 +910,6 @@ dependencies = [ "serde_json", "tokio", "url", - "warp", "webauthn-rs", ] @@ -1237,26 +1102,6 @@ dependencies = [ "sha1", ] -[[package]] -name = "pin-project" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "pin-project-lite" version = "0.2.9" @@ -1314,12 +1159,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "quick-error" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" - [[package]] name = "quote" version = "1.0.23" @@ -1397,15 +1236,6 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" -[[package]] -name = "remove_dir_all" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" -dependencies = [ - "winapi", -] - [[package]] name = "rustc_version" version = "0.4.0" @@ -1438,33 +1268,12 @@ dependencies = [ "windows-sys", ] -[[package]] -name = "rustls-pemfile" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eebeaeb360c87bfb72e84abdb3447159c0eaececf1bef2aecd65a8be949d1c9" -dependencies = [ - "base64 0.13.1", -] - [[package]] name = "ryu" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" -[[package]] -name = "safemem" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" - -[[package]] -name = "scoped-tls" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" - [[package]] name = "scopeguard" version = "1.1.0" @@ -1530,17 +1339,6 @@ dependencies = [ "serde", ] -[[package]] -name = "sha-1" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - [[package]] name = "sha1" version = "0.10.5" @@ -1615,20 +1413,6 @@ dependencies = [ "unicode-xid", ] -[[package]] -name = "tempfile" -version = "3.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" -dependencies = [ - "cfg-if", - "fastrand", - "libc", - "redox_syscall", - "remove_dir_all", - "winapi", -] - [[package]] name = "termcolor" version = "1.1.3" @@ -1731,29 +1515,6 @@ dependencies = [ "syn", ] -[[package]] -name = "tokio-stream" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d660770404473ccd7bc9f8b28494a811bc18542b915c0855c51e8f419d5223ce" -dependencies = [ - "futures-core", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "tokio-tungstenite" -version = "0.17.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f714dd15bead90401d77e04243611caec13726c2408afd5b31901dfcdcb3b181" -dependencies = [ - "futures-util", - "log", - "tokio", - "tungstenite", -] - [[package]] name = "tokio-util" version = "0.7.4" @@ -1768,12 +1529,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "tower-service" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" - [[package]] name = "tracing" version = "0.1.37" @@ -1807,40 +1562,6 @@ dependencies = [ "once_cell", ] -[[package]] -name = "try-lock" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" - -[[package]] -name = "tungstenite" -version = "0.17.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e27992fd6a8c29ee7eef28fc78349aa244134e10ad447ce3b9f0ac0ed0fa4ce0" -dependencies = [ - "base64 0.13.1", - "byteorder", - "bytes", - "http", - "httparse", - "log", - "rand", - "sha-1", - "thiserror", - "url", - "utf-8", -] - -[[package]] -name = "twoway" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59b11b2b5241ba34be09c3cc85a36e56e48f9888862e19cedf23336d35316ed1" -dependencies = [ - "memchr", -] - [[package]] name = "typenum" version = "1.16.0" @@ -1853,15 +1574,6 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81" -[[package]] -name = "unicase" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" -dependencies = [ - "version_check", -] - [[package]] name = "unicode-bidi" version = "0.3.8" @@ -1901,12 +1613,6 @@ dependencies = [ "serde", ] -[[package]] -name = "utf-8" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" - [[package]] name = "uuid" version = "1.2.2" @@ -1929,47 +1635,6 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" -[[package]] -name = "want" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" -dependencies = [ - "log", - "try-lock", -] - -[[package]] -name = "warp" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed7b8be92646fc3d18b06147664ebc5f48d222686cb11a8755e561a735aacc6d" -dependencies = [ - "bytes", - "futures-channel", - "futures-util", - "headers", - "http", - "hyper", - "log", - "mime", - "mime_guess", - "multipart", - "percent-encoding", - "pin-project", - "rustls-pemfile", - "scoped-tls", - "serde", - "serde_json", - "serde_urlencoded", - "tokio", - "tokio-stream", - "tokio-tungstenite", - "tokio-util", - "tower-service", - "tracing", -] - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" diff --git a/Cargo.toml b/Cargo.toml index 6ab9029..35739b0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,6 @@ actix-web = "4" clap = { version = "4.0.29", features = ["derive"] } tokio = { version = "1", features = ["full"] } url = "*" -warp = "0.3" webauthn-rs = "0.4.8" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" diff --git a/src/app/mod.rs b/src/app/mod.rs index 803a8e5..e69de29 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -1,21 +0,0 @@ -use actix_web::{App, web}; - -use crate::{handlers, models}; - -pub async fn app() -> App { - let state = models::AppState{ - webauthn: todo!(), - db: todo!(), - hbs: todo!(), - session: todo!(), - }; - let app = App::new(). - app_data(web::Data::new(state)) - .service(|| { - web::scope("/") - .route("/", web::get().to(handlers::landing_page)) - .route("/account/register-init", web::post().to(handlers::start_webauthn_registration)) - .route("/account/register-finish", web::post().to(handlers::finish_webauthn_registration)) - }); - app -} diff --git a/src/filters/mod.rs b/src/filters/mod.rs deleted file mode 100644 index 01cbfc8..0000000 --- a/src/filters/mod.rs +++ /dev/null @@ -1,43 +0,0 @@ -use serde::de::DeserializeOwned; -use warp::Filter; -use webauthn_rs::prelude::RegisterPublicKeyCredential; - -use crate::handlers; -use crate::models; - - -pub fn all(state: models::AppState) -> impl Filter + Clone + '_{ - landing(state.clone()) - .or(start_webauthn_registration(state.clone())) - .or(finish_webauthn_registration(state.clone())) -} - -pub fn landing(state: models::AppState) -> impl Filter + Clone + '_ { - warp::path::end() - .and(warp::any().map(move || state.clone())) - .and_then(handlers::landing_page) -} - -pub fn start_webauthn_registration<'a>(state: models::AppState<'a>) -> impl Filter + Clone + 'a { - warp::path!("account" / "register-init") - .and(warp::post()) - .and(json_body::()) - .and(warp::any().map(move || state.clone())) - .and_then(handlers::start_webauthn_registration) -} - -pub fn finish_webauthn_registration<'a>(state: models::AppState<'a>) -> impl Filter + Clone + 'a { - warp::path!("account" / "register-finish") - .and(warp::post()) - .and(json_body::()) - .and(warp::any().map(move || state.clone())) - .and(warp::cookie("uuid")) - .and_then(handlers::finish_webauthn_registration) -} - -fn json_body<'a, M: Send + DeserializeOwned>() -> impl Filter + Clone { - // When accepting a body, we want a JSON body - // (and to reject huge payloads)... - warp::body::content_length_limit(1024 * 16) - .and(warp::body::json()) -} diff --git a/src/handlers/mod.rs b/src/handlers/mod.rs index b350288..ddec8d2 100644 --- a/src/handlers/mod.rs +++ b/src/handlers/mod.rs @@ -1,17 +1,16 @@ -use std::convert::Infallible; use webauthn_rs::prelude::{RegisterPublicKeyCredential, Uuid}; -use actix_web::{HttpResponse, http::Error, ResponseError, web}; +use actix_web::{error, HttpResponse, http::header::{ContentType, self}, web, cookie::{Cookie, SameSite}, HttpRequest}; use crate::{models::{AppState, User}, templates}; -type Response = Result; - -pub async fn landing_page (app_state: AppState<'_>) -> Response { - let content: String = templates::landing_page(app_state).unwrap(); - Ok(warp::reply::html(content)) +pub async fn landing_page (app_state: web::Data>) -> HttpResponse { + let content: String = templates::landing_page(app_state.hbs.clone()).unwrap(); + HttpResponse::Ok() + .content_type(ContentType::html()) + .body(content) } -pub async fn start_webauthn_registration(app_state: web::Data>, user: web::Json) -> Response { +pub async fn start_webauthn_registration(app_state: web::Data>, user: web::Json) -> HttpResponse { let (creation_challenge_response, passkey_registration) = app_state.webauthn.start_passkey_registration(user.uuid, &user.user_name, &user.display_name, None).unwrap(); let uuid_str = user.uuid.to_string(); { @@ -20,13 +19,22 @@ pub async fn start_webauthn_registration(app_state: web::Data>, use } { let mut uuid_db = app_state.db.user_uuid_object.write().await; - uuid_db.insert(user.uuid, user); + uuid_db.insert(user.uuid, user.into_inner()); } - let json_reply = warp::reply::json(&creation_challenge_response); - Ok(warp::reply::with_header(json_reply, "Set-Cookie", format!("uuid={};SameSite=Strict", &uuid_str))) + let res = serde_json::to_string(&creation_challenge_response).unwrap(); + let cookie = Cookie::build("uuid", &uuid_str) + .secure(true) + .same_site(SameSite::Strict) + .finish(); + HttpResponse::Ok() + .content_type(ContentType::json()) + .insert_header((header::SET_COOKIE, cookie.encoded().to_string())) + .body(res) } -pub async fn finish_webauthn_registration(register: RegisterPublicKeyCredential, app_state: AppState<'_>, uuid: Uuid) -> Response { +pub async fn finish_webauthn_registration(req: HttpRequest, app_state: web::Data>, register: web::Json) -> impl actix_web::Responder { + let cook = req.cookie("uuid"); + let uuid = Uuid::parse_str(cook.unwrap().value()).unwrap(); let registration_result = { let users = app_state.db.user_uuid_object.read().await; let user = users.get(&uuid).unwrap(); @@ -34,14 +42,14 @@ pub async fn finish_webauthn_registration(register: RegisterPublicKeyCredential, let passkey_registration = session.get(&user).unwrap(); app_state.webauthn.finish_passkey_registration(®ister, passkey_registration) }; - let reply = { - let mut user_keys = app_state.db.user_keys.write().await; - registration_result.map_or( - warp::reply::with_status("Challenge failed, cannot register key", warp::http::StatusCode::UNAUTHORIZED), - |passkey| { - user_keys.insert(uuid, passkey); - warp::reply::with_status("ok",warp::http::StatusCode::OK) - }) - }; - Ok(reply) + let mut user_keys = app_state.db.user_keys.write().await; + match registration_result { + Ok(passkey) => { + user_keys.insert(uuid, passkey); + HttpResponse::Ok() + .body("ok") + }, + Err(_) => + HttpResponse::from_error(error::ErrorUnauthorized("Webauthn challenge failed")) + } } diff --git a/src/main.rs b/src/main.rs index 537414c..393e0ab 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,10 @@ use std::net::SocketAddr; +use actix_web::{App, web, HttpServer}; use clap::Parser; +use std::borrow::Borrow; + mod app; -mod filters; mod handlers; mod models; mod templates; @@ -15,16 +17,30 @@ struct CLIArgs { } #[tokio::main] -async fn main() { +async fn main() -> std::io::Result<()> { let args = CLIArgs::parse(); - let addr: SocketAddr = args.bind.parse().expect(&format!("Cannot bind to {}. Please provide a host and port like [::1]:8000", &args.bind)); + let _addr: SocketAddr = args.bind.parse().expect(&format!("Cannot bind to {}. Please provide a host and port like [::1]:8000", &args.bind)); println!("Server listening to {}", &args.bind); - let routes = filters::all(models::AppState::new()); - warp::serve(routes).run(addr).await; + let state = models::AppState{ + webauthn: todo!(), + db: todo!(), + hbs: todo!(), + session: todo!(), + }; - - println!("Turning out server"); - println!("Adieu, goodbye, auf wiedersehen"); + HttpServer::new( + || + App::new().app_data(web::Data::new(state.borrow())) + .service(|| -> actix_web::Scope { + web::scope("/") + .route("/", web::get().to(handlers::landing_page)) + .route("/account/register-init", web::post().to(handlers::start_webauthn_registration)) + .route("/account/register-finish", web::post().to(handlers::finish_webauthn_registration)) + }())) + .bind(("::1", 8080)) + .unwrap() + .run() + .await } diff --git a/src/templates/mod.rs b/src/templates/mod.rs index 08eab02..155c8d9 100644 --- a/src/templates/mod.rs +++ b/src/templates/mod.rs @@ -2,9 +2,7 @@ use handlebars::RenderError; use serde_json::json; use handlebars::Handlebars; -use std::path::PathBuf; - -use crate::models::AppState; +use std::{path::PathBuf, sync::Arc}; pub fn new<'a>() -> Result, RenderError> { let rootpath = PathBuf::from(env!("CARGO_MANIFEST_DIR")); @@ -19,8 +17,7 @@ pub fn new<'a>() -> Result, RenderError> { return Ok(hbs) } -pub fn landing_page(app_state: AppState<'_>) -> Result { - let hb = app_state.hbs; +pub fn landing_page<'a>(hb: Arc>) -> Result { let data = json!({ }); hb.render("landing", &data)