From 4bacba7cece901f9c25a450eb4b7bc8969bb5e9e Mon Sep 17 00:00:00 2001 From: Vika Date: Tue, 9 Jul 2024 00:36:48 +0300 Subject: Start working on login functionality --- Cargo.lock | 5 +++++ Cargo.toml | 2 +- src/lib.rs | 1 + src/login.rs | 45 +++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 5 ++++- templates/src/templates.rs | 2 +- 6 files changed, 57 insertions(+), 3 deletions(-) create mode 100644 src/login.rs diff --git a/Cargo.lock b/Cargo.lock index 226a14d..fb53133 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -600,7 +600,12 @@ version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7efb37c3e1ccb1ff97164ad95ac1606e8ccd35b3fa0a7d99a304c7f4a428cc24" dependencies = [ + "base64 0.21.2", + "hmac", "percent-encoding", + "rand 0.8.5", + "sha2", + "subtle", "time 0.3.23", "version_check", ] diff --git a/Cargo.toml b/Cargo.toml index c38dabd..b71ac4e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -124,7 +124,7 @@ version = "^0.6.18" features = ["multipart", "json", "headers", "form", "macros"] [dependencies.axum-extra] version = "^0.7.4" -features = ["cookie"] +features = ["cookie", "cookie-signed"] [dependencies.chrono] # Date and time library for Rust version = "^0.4.19" features = ["serde"] diff --git a/src/lib.rs b/src/lib.rs index c1bd965..04b3298 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,6 +8,7 @@ pub mod media; pub mod micropub; pub mod indieauth; pub mod webmentions; +pub mod login; pub mod companion { use std::{collections::HashMap, sync::Arc}; diff --git a/src/login.rs b/src/login.rs new file mode 100644 index 0000000..7f0314f --- /dev/null +++ b/src/login.rs @@ -0,0 +1,45 @@ +use axum_extra::extract::cookie; + +/// Show a login page. +async fn get() { + todo!() +} + +/// Accept login and start the IndieAuth dance. +async fn post() { + todo!() +} + +/// Accept the return of the IndieAuth dance. Set a cookie for the +/// required session. +async fn callback() { + todo!() +} + +/// Show the form necessary for logout. If JS is enabled, +/// automatically POST the form. +/// +/// This is essentially protection from CSRF and also from some kind +/// of crawlers working with a user's cookies (wget?). If a crawler is +/// stupid enough to execute JS and send a POST request though, that's +/// on the crawler. +async fn logout_page() { + todo!() +} + +/// Erase the necessary cookies for login and invalidate the session. +async fn logout() { + todo!() +} + +/// Produce a router for all of the above. +fn router(key: cookie::Key) -> axum::routing::Router { + axum::routing::Router::new() + .route("/start", axum::routing::get(get).post(post)) + .route("/finish", axum::routing::get(callback)) + .route("/logout", axum::routing::get(logout_page).post(logout)) + // I'll need some kind of session store here too. It should be + // a key from UUIDs (128 bits is enough for a session token) + // to at least a URL, if not something more. + .with_state(key) +} diff --git a/src/main.rs b/src/main.rs index b7a6035..9e541b9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -221,6 +221,9 @@ async fn compose_kittybox( other => unimplemented!("Unsupported backend: {other}") }; + // TODO: load from environment + let cookie_key = axum_extra::extract::cookie::Key::generate(); + let router = router .route( "/.kittybox/static/:path", @@ -228,11 +231,11 @@ async fn compose_kittybox( ) .route("/.kittybox/coffee", teapot_route()) .nest("/.kittybox/micropub/client", kittybox::companion::router()) + .nest("/.kittybox/login", kittybox::login::router(cookie_key)) .layer(tower_http::trace::TraceLayer::new_for_http()) .layer(tower_http::catch_panic::CatchPanicLayer::new()) .layer(tower_http::sensitive_headers::SetSensitiveHeadersLayer::new([ axum::http::header::AUTHORIZATION, - // Not used yet, but will be eventually axum::http::header::COOKIE, axum::http::header::SET_COOKIE, ])); diff --git a/templates/src/templates.rs b/templates/src/templates.rs index 63c67c5..0196289 100644 --- a/templates/src/templates.rs +++ b/templates/src/templates.rs @@ -42,7 +42,7 @@ markup::define! { } li.shiftright { @if user.is_none() { - a #login[href="/login"] { "Sign in" } + a #login[href="/login/start"] { "Sign in" } } else { span { @user.as_ref().unwrap() " - " a #logout[href="/logout"] { "Sign out" } -- cgit 1.4.1