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 %}
+ {% endif %}
{% if let Some(OidcProviderData {name, redirect_url}) = oidc_data %}
{% 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(),