Fix frontend login for nextcloud flows

This commit is contained in:
Lennart
2025-04-13 20:22:15 +02:00
parent b2c1bd6b8d
commit 354c6c97eb
4 changed files with 32 additions and 5 deletions

View File

@@ -25,3 +25,4 @@ rand.workspace = true
chrono.workspace = true chrono.workspace = true
uuid.workspace = true uuid.workspace = true
url.workspace = true url.workspace = true
tracing.workspace = true

View File

@@ -1,5 +1,9 @@
use actix_session::{
SessionMiddleware, config::CookieContentSecurity, storage::CookieSessionStore,
};
use actix_web::{ use actix_web::{
HttpRequest, HttpResponse, Responder, HttpRequest, HttpResponse, Responder,
cookie::{Key, SameSite},
http::{ http::{
StatusCode, StatusCode,
header::{self}, header::{self},
@@ -14,6 +18,7 @@ use rustical_store::auth::{AuthenticationMiddleware, AuthenticationProvider, Use
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::{collections::HashMap, sync::Arc}; use std::{collections::HashMap, sync::Arc};
use tokio::sync::RwLock; use tokio::sync::RwLock;
use tracing::instrument;
use crate::unauthorized_handler; use crate::unauthorized_handler;
@@ -153,6 +158,7 @@ struct NextcloudLoginPage {
app_name: String, app_name: String,
} }
#[instrument(skip(state, req))]
async fn get_nextcloud_flow( async fn get_nextcloud_flow(
user: User, user: User,
state: Data<NextcloudFlows>, state: Data<NextcloudFlows>,
@@ -187,6 +193,7 @@ struct NextcloudLoginSuccessPage {
app_name: String, app_name: String,
} }
#[instrument(skip(state, req))]
async fn post_nextcloud_flow( async fn post_nextcloud_flow(
user: User, user: User,
state: Data<NextcloudFlows>, state: Data<NextcloudFlows>,
@@ -220,11 +227,22 @@ pub fn configure_nextcloud_login<AP: AuthenticationProvider>(
cfg: &mut ServiceConfig, cfg: &mut ServiceConfig,
nextcloud_flows_state: Arc<NextcloudFlows>, nextcloud_flows_state: Arc<NextcloudFlows>,
auth_provider: Arc<AP>, auth_provider: Arc<AP>,
frontend_secret: [u8; 64],
) { ) {
cfg.service( cfg.service(
web::scope("/index.php/login/v2") web::scope("/index.php/login/v2")
.wrap(ErrorHandlers::new().handler(StatusCode::UNAUTHORIZED, unauthorized_handler)) .wrap(ErrorHandlers::new().handler(StatusCode::UNAUTHORIZED, unauthorized_handler))
.wrap(AuthenticationMiddleware::new(auth_provider.clone())) .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(nextcloud_flows_state))
.app_data(Data::from(auth_provider.clone())) .app_data(Data::from(auth_provider.clone()))
.service(web::resource("").post(post_nextcloud_login)) .service(web::resource("").post(post_nextcloud_login))

View File

@@ -9,6 +9,7 @@ use askama::Template;
use askama_web::WebTemplate; use askama_web::WebTemplate;
use rustical_store::auth::AuthenticationProvider; use rustical_store::auth::AuthenticationProvider;
use serde::Deserialize; use serde::Deserialize;
use tracing::instrument;
#[derive(Template, WebTemplate)] #[derive(Template, WebTemplate)]
#[template(path = "pages/login.html")] #[template(path = "pages/login.html")]
@@ -22,6 +23,7 @@ pub struct GetLoginQuery {
redirect_uri: Option<String>, redirect_uri: Option<String>,
} }
#[instrument(skip(req))]
pub async fn route_get_login( pub async fn route_get_login(
Query(GetLoginQuery { redirect_uri }): Query<GetLoginQuery>, Query(GetLoginQuery { redirect_uri }): Query<GetLoginQuery>,
req: HttpRequest, req: HttpRequest,
@@ -47,6 +49,7 @@ pub struct PostLoginForm {
redirect_uri: Option<String>, redirect_uri: Option<String>,
} }
#[instrument(skip(req, password, auth_provider, session))]
pub async fn route_post_login<AP: AuthenticationProvider>( pub async fn route_post_login<AP: AuthenticationProvider>(
req: HttpRequest, req: HttpRequest,
Form(PostLoginForm { Form(PostLoginForm {

View File

@@ -51,6 +51,16 @@ pub fn make_app<AS: AddressbookStore, CS: CalendarStore, S: SubscriptionStore>(
.service(web::redirect("/carddav", "/carddav")), .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 { if frontend_config.enabled {
app = app app = app
.service(web::scope("/frontend").configure(|cfg| { .service(web::scope("/frontend").configure(|cfg| {
@@ -64,10 +74,5 @@ pub fn make_app<AS: AddressbookStore, CS: CalendarStore, S: SubscriptionStore>(
})) }))
.service(web::redirect("/", "/frontend").see_other()); .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 app
} }