diff --git a/crates/frontend/public/templates/pages/login.html b/crates/frontend/public/templates/pages/login.html index 77ef407..ff9739f 100644 --- a/crates/frontend/public/templates/pages/login.html +++ b/crates/frontend/public/templates/pages/login.html @@ -7,6 +7,8 @@ {% if let Some(redirect_uri) = redirect_uri %}

and redirect to {{redirect_uri}}

{% endif %} + + {% if allow_password_login %}
@@ -19,6 +21,7 @@ {% endif %}
+ {% endif %} {% if let Some(OidcProviderData {name, redirect_url}) = oidc_data %}
@@ -28,6 +31,12 @@
{% endif %} + + {% if !allow_password_login && oidc_data.is_none() %} +

+ No login method available +

+ {% endif %} {% endblock %} diff --git a/crates/frontend/src/config.rs b/crates/frontend/src/config.rs index ba49206..d378cde 100644 --- a/crates/frontend/src/config.rs +++ b/crates/frontend/src/config.rs @@ -1,7 +1,7 @@ use openidconnect::{ClientId, ClientSecret, IssuerUrl, Scope}; use serde::{Deserialize, Serialize}; -fn default_enabled() -> bool { +fn default_true() -> bool { true } @@ -21,8 +21,10 @@ pub struct FrontendConfig { #[serde(serialize_with = "hex::serde::serialize")] #[serde(deserialize_with = "hex::serde::deserialize")] pub secret_key: [u8; 64], - #[serde(default = "default_enabled")] + #[serde(default = "default_true")] pub enabled: bool, #[serde(default)] pub oidc: Option, + #[serde(default = "default_true")] + pub allow_password_login: bool, } diff --git a/crates/frontend/src/routes/login.rs b/crates/frontend/src/routes/login.rs index 25240ed..31f6bee 100644 --- a/crates/frontend/src/routes/login.rs +++ b/crates/frontend/src/routes/login.rs @@ -2,7 +2,7 @@ use crate::{FrontendConfig, oidc::OidcProviderData}; use actix_session::Session; use actix_web::{ HttpRequest, HttpResponse, Responder, - error::ErrorUnauthorized, + error::{ErrorNotFound, ErrorUnauthorized}, web::{Data, Form, Query, Redirect}, }; use askama::Template; @@ -16,6 +16,7 @@ use tracing::instrument; struct LoginPage<'a> { redirect_uri: Option, oidc_data: Option>, + allow_password_login: bool, } #[derive(Debug, Deserialize)] @@ -31,6 +32,7 @@ pub async fn route_get_login( ) -> impl Responder { LoginPage { redirect_uri, + allow_password_login: config.allow_password_login, oidc_data: config.oidc.as_ref().map(|oidc| OidcProviderData { name: &oidc.name, redirect_url: req @@ -49,7 +51,7 @@ pub struct PostLoginForm { redirect_uri: Option, } -#[instrument(skip(req, password, auth_provider, session))] +#[instrument(skip(req, password, auth_provider, session, config))] pub async fn route_post_login( req: HttpRequest, Form(PostLoginForm { @@ -59,7 +61,11 @@ pub async fn route_post_login( }): Form, session: Session, auth_provider: Data, + config: Data, ) -> HttpResponse { + if !config.allow_password_login { + return ErrorNotFound("Password authentication disabled").error_response(); + } // Ensure that redirect_uri never goes cross-origin let default_redirect = "/frontend/user".to_string(); let redirect_uri = redirect_uri.unwrap_or(default_redirect.clone()); diff --git a/src/commands/mod.rs b/src/commands/mod.rs index d179d32..5b4af30 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -36,6 +36,7 @@ pub fn cmd_gen_config(_args: GenConfigArgs) -> anyhow::Result<()> { secret_key: generate_frontend_secret(), enabled: true, oidc: None, + allow_password_login: true, }, dav_push: DavPushConfig::default(), nextcloud_login: Default::default(),