diff --git a/crates/frontend/Cargo.toml b/crates/frontend/Cargo.toml index 6bd9d84..15115cf 100644 --- a/crates/frontend/Cargo.toml +++ b/crates/frontend/Cargo.toml @@ -25,3 +25,4 @@ rand.workspace = true chrono.workspace = true uuid.workspace = true url.workspace = true +tracing.workspace = true diff --git a/crates/frontend/src/nextcloud_login.rs b/crates/frontend/src/nextcloud_login.rs index fe69374..ab3cc6e 100644 --- a/crates/frontend/src/nextcloud_login.rs +++ b/crates/frontend/src/nextcloud_login.rs @@ -1,5 +1,9 @@ +use actix_session::{ + SessionMiddleware, config::CookieContentSecurity, storage::CookieSessionStore, +}; use actix_web::{ HttpRequest, HttpResponse, Responder, + cookie::{Key, SameSite}, http::{ StatusCode, header::{self}, @@ -14,6 +18,7 @@ use rustical_store::auth::{AuthenticationMiddleware, AuthenticationProvider, Use use serde::{Deserialize, Serialize}; use std::{collections::HashMap, sync::Arc}; use tokio::sync::RwLock; +use tracing::instrument; use crate::unauthorized_handler; @@ -153,6 +158,7 @@ struct NextcloudLoginPage { app_name: String, } +#[instrument(skip(state, req))] async fn get_nextcloud_flow( user: User, state: Data, @@ -187,6 +193,7 @@ struct NextcloudLoginSuccessPage { app_name: String, } +#[instrument(skip(state, req))] async fn post_nextcloud_flow( user: User, state: Data, @@ -220,11 +227,22 @@ pub fn configure_nextcloud_login( cfg: &mut ServiceConfig, nextcloud_flows_state: Arc, auth_provider: Arc, + frontend_secret: [u8; 64], ) { cfg.service( web::scope("/index.php/login/v2") .wrap(ErrorHandlers::new().handler(StatusCode::UNAUTHORIZED, unauthorized_handler)) .wrap(AuthenticationMiddleware::new(auth_provider.clone())) + .wrap( + SessionMiddleware::builder( + CookieSessionStore::default(), + Key::from(&frontend_secret), + ) + .cookie_secure(true) + .cookie_same_site(SameSite::Strict) + .cookie_content_security(CookieContentSecurity::Private) + .build(), + ) .app_data(Data::from(nextcloud_flows_state)) .app_data(Data::from(auth_provider.clone())) .service(web::resource("").post(post_nextcloud_login)) diff --git a/crates/frontend/src/routes/login.rs b/crates/frontend/src/routes/login.rs index 80d1dea..6750697 100644 --- a/crates/frontend/src/routes/login.rs +++ b/crates/frontend/src/routes/login.rs @@ -9,6 +9,7 @@ use askama::Template; use askama_web::WebTemplate; use rustical_store::auth::AuthenticationProvider; use serde::Deserialize; +use tracing::instrument; #[derive(Template, WebTemplate)] #[template(path = "pages/login.html")] @@ -22,6 +23,7 @@ pub struct GetLoginQuery { redirect_uri: Option, } +#[instrument(skip(req))] pub async fn route_get_login( Query(GetLoginQuery { redirect_uri }): Query, req: HttpRequest, @@ -47,6 +49,7 @@ pub struct PostLoginForm { redirect_uri: Option, } +#[instrument(skip(req, password, auth_provider, session))] pub async fn route_post_login( req: HttpRequest, Form(PostLoginForm { diff --git a/src/app.rs b/src/app.rs index 198bd59..fe8e87e 100644 --- a/src/app.rs +++ b/src/app.rs @@ -51,6 +51,16 @@ pub fn make_app( .service(web::redirect("/carddav", "/carddav")), ); + if nextcloud_login_config.enabled { + app = app.configure(|cfg| { + configure_nextcloud_login( + cfg, + nextcloud_flows_state, + auth_provider.clone(), + frontend_config.secret_key, + ) + }); + } if frontend_config.enabled { app = app .service(web::scope("/frontend").configure(|cfg| { @@ -64,10 +74,5 @@ pub fn make_app( })) .service(web::redirect("/", "/frontend").see_other()); } - if nextcloud_login_config.enabled { - app = app.configure(|cfg| { - configure_nextcloud_login(cfg, nextcloud_flows_state, auth_provider.clone()) - }); - } app }