From 7209a32d436c74cf03c270eb4680e4447f4d9402 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 25 Aug 2026 13:18:15 +0000 Subject: [PATCH] Split "disable local login" from the initial SSO setup step MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Confirmed live: offering DISABLE_PASSWORD_AUTH/ALLOW_PASSWORD_LOGIN in the same breath as printing the Authelia paste-in values lets an admin say yes before actually pasting those values into the app's own settings and testing the button — leaving neither login path working (password form gone, OAuth provider never actually finished on the app's side). Both are now their own function, only reachable on a later run (Beszel: independently after the SSO offer; Mealie: from the "already configured, not reconfiguring" branch), and gated behind an explicit "have you already logged in successfully via the Authelia button?" confirmation before the disable prompt is even offered. --- services/beszel.sh | 69 ++++++++++++++++++++++++------------ services/mealie.sh | 87 ++++++++++++++++++++++++++++------------------ 2 files changed, 100 insertions(+), 56 deletions(-) diff --git a/services/beszel.sh b/services/beszel.sh index 1d8ddbf..29fe14b 100644 --- a/services/beszel.sh +++ b/services/beszel.sh @@ -299,30 +299,54 @@ _beszel_offer_authelia_oidc() { declare -F _authelia_scope_access >/dev/null 2>&1 && _authelia_scope_access "beszel" "$APP_DOMAIN" - # DISABLE_PASSWORD_AUTH/USER_CREATION are real, documented env vars - # (beszel.dev's own OAuth guide) — but Beszel has no default account: - # the FIRST person to register becomes admin (see this file's own - # README section), and there's no signup-fallback like Mealie's - # OIDC_SIGNUP_ENABLED convenience wording to lean on if that hasn't - # happened yet. Off by default and gated behind an explicit warning — - # flipping this before a working login exists risks locking the hub's - # UI out with no account able to reach it at all. echo "" - local _disable_local="" - prompt_yn " Also disable Beszel's own password login, so Authelia is the only way in? Only do this AFTER you've registered a working account. (y/n):" "n" _disable_local - if [[ "$_disable_local" =~ ^[Yy]$ ]]; then - local _auto_register="" - prompt_yn " Auto-create Beszel accounts for new Authelia logins? (y/n):" "n" _auto_register - sed -i '/^DISABLE_PASSWORD_AUTH=/d; /^USER_CREATION=/d' "$dir/.env" - { - echo "DISABLE_PASSWORD_AUTH=true" - [[ "$_auto_register" =~ ^[Yy]$ ]] && echo "USER_CREATION=true" - } >> "$dir/.env" - chown "$ACTUAL_USER:$ACTUAL_USER" "$dir/.env" 2>/dev/null || true - ( cd "$dir" && docker compose up -d beszel ) \ - && log_success "Beszel's own password login is now disabled — Authelia is the only way in." \ - || log_warning "Restart failed — check: docker compose -f $dir/docker-compose.yml logs beszel" + log_info "Paste those values into Beszel's Settings -> Auth providers -> OpenID" + log_info "Connect page now, then log out and click through the Authelia login" + log_info "button to confirm it actually works — BEFORE going any further here." + echo "" + log_warning "The next step can disable Beszel's password login entirely. Confirmed" + log_warning "live: saying yes here before actually testing the button leaves NEITHER" + log_warning "login path working — the password form is gone, and the OAuth provider" + log_warning "was never actually finished on Beszel's side, so its button never" + log_warning "appears either. Re-run 'sudo ./setup.sh beszel' (choose update) any time" + log_warning "later to come back to this once you've verified the button works." +} + +# Split out from _beszel_offer_authelia_oidc so it can also be re-reached on +# its own via a later "update" rerun, once the admin has actually gone and +# tested the Authelia login button — see that function's own warning for +# why this can't be offered in the same breath as printing the paste-in +# values. DISABLE_PASSWORD_AUTH/USER_CREATION are real, documented env vars +# (beszel.dev's own OAuth guide). +_beszel_offer_disable_password_auth() { + local dir="$1" + [ -f "$dir/.env" ] || return 0 + grep -qF "client_id: 'beszel'" "$DOCKER_DIR/authelia/config/configuration.yml" 2>/dev/null || return 0 + grep -q '^DISABLE_PASSWORD_AUTH=true' "$dir/.env" 2>/dev/null && return 0 + + echo "" + local _tested="" + prompt_yn " Have you ALREADY logged into Beszel successfully using the Authelia button (not just pasted the values)? (y/n):" "n" _tested + if [[ ! "$_tested" =~ ^[Yy]$ ]]; then + log_info "Skipped. Test the Authelia login button first, then re-run 'sudo ./setup.sh beszel' (choose update) to come back to this." + return 0 fi + + local _disable_local="" + prompt_yn " Disable Beszel's own password login now, so Authelia is the only way in? (y/n):" "n" _disable_local + [[ "$_disable_local" =~ ^[Yy]$ ]] || return 0 + + local _auto_register="" + prompt_yn " Auto-create Beszel accounts for new Authelia logins? (y/n):" "n" _auto_register + sed -i '/^DISABLE_PASSWORD_AUTH=/d; /^USER_CREATION=/d' "$dir/.env" + { + echo "DISABLE_PASSWORD_AUTH=true" + [[ "$_auto_register" =~ ^[Yy]$ ]] && echo "USER_CREATION=true" + } >> "$dir/.env" + chown "$ACTUAL_USER:$ACTUAL_USER" "$dir/.env" 2>/dev/null || true + ( cd "$dir" && docker compose up -d beszel ) \ + && log_success "Beszel's own password login is now disabled — Authelia is the only way in." \ + || log_warning "Restart failed — check: docker compose -f $dir/docker-compose.yml logs beszel" } install_beszel() { @@ -361,6 +385,7 @@ install_beszel() { [[ "$FINISH_AGENT" =~ ^[Yy]$ ]] && _beszel_configure_agent "$DIR" "http://localhost:${_WP} (or its Caddy domain, once configured)" fi _beszel_offer_authelia_oidc "$DIR" + _beszel_offer_disable_password_auth "$DIR" return 0 ;; cancel) diff --git a/services/mealie.sh b/services/mealie.sh index 11c89ab..d64a91a 100644 --- a/services/mealie.sh +++ b/services/mealie.sh @@ -228,7 +228,10 @@ _mealie_offer_authelia_oidc() { log_info "Authelia SSO is already configured for Mealie (OIDC_* already set in $DIR/.env)." local RECONFIGURE="" prompt_yn " Reconfigure it (registers a fresh Authelia client + secret)? (y/n):" "n" RECONFIGURE - [[ "$RECONFIGURE" =~ ^[Yy]$ ]] || return 0 + if [[ ! "$RECONFIGURE" =~ ^[Yy]$ ]]; then + _mealie_offer_disable_password_login "$DIR" + return 0 + fi # ALLOW_PASSWORD_LOGIN isn't OIDC_-prefixed but is written by this # same step (see below) — strip it too so reconfiguring doesn't # leave a stale duplicate line if it's set again. @@ -251,27 +254,6 @@ _mealie_offer_authelia_oidc() { prompt_yn " Require two-factor for Mealie logins via Authelia too? (y/n):" "y" _2fa [[ "$_2fa" =~ ^[Yy]$ ]] || AUTH_POLICY="one_factor" - # Mealie's own docs document ALLOW_PASSWORD_LOGIN (hides the - # username+password fields entirely) and OIDC_AUTO_REDIRECT (skips the - # login page and jumps straight to the identity provider) as the real, - # supported way to make Authelia the only way in — confirmed against - # docs.mealie.io's OIDC and backend-config pages directly, not assumed. - # Off by default: this is a real access-control change (anyone who - # only has a local Mealie account, not an Authelia one, loses their - # login path), not just an additive convenience like the SSO button - # above. Recoverable any time by flipping these back and restarting — - # worth saying so, since a locked-out admin's first instinct otherwise - # is to worry the account itself is gone. - echo "" - local _disable_local="" - prompt_yn " Also disable Mealie's own username/password login, so Authelia is the only way in? (y/n):" "n" _disable_local - local _auto_redirect="" - if [[ "$_disable_local" =~ ^[Yy]$ ]]; then - log_warning "Anyone without an Authelia account (only a local Mealie one) will no longer be able to log in." - log_info "Reversible any time: set ALLOW_PASSWORD_LOGIN back to true in $DIR/.env and 'docker compose up -d'." - prompt_yn " Skip Mealie's login page entirely and jump straight to Authelia? (y/n):" "y" _auto_redirect - fi - if ! _authelia_provision_oidc_client "Mealie" "mealie" "$AUTH_POLICY" "y" "n" "${BASE_URL}/login"; then log_warning "Couldn't register Mealie as an OIDC client in Authelia — skipping SSO setup." return 0 @@ -289,15 +271,6 @@ OIDC_CLIENT_SECRET=$OIDC_CLIENT_SECRET_PLAIN OIDC_CONFIGURATION_URL=$_discovery_url OIDC_PROVIDER_NAME=Authelia ENV - if [[ "$_disable_local" =~ ^[Yy]$ ]]; then - echo "ALLOW_PASSWORD_LOGIN=false" >> "$DIR/.env" - fi - if [[ "$_auto_redirect" =~ ^[Yy]$ ]]; then - { - echo "OIDC_AUTO_REDIRECT=true" - echo "OIDC_REMEMBER_ME=true" - } >> "$DIR/.env" - fi chown "$ACTUAL_USER:$ACTUAL_USER" "$DIR/.env" 2>/dev/null || true # Mealie's OIDC redirect URI generation trusts X-Forwarded-* only from @@ -312,13 +285,59 @@ ENV sed -i "/container_name: ${CONTAINER}\$/a\\ entrypoint: [\"uvicorn\", \"mealie.app:app\", \"--host\", \"0.0.0.0\", \"--port\", \"9000\", \"--forwarded-allow-ips=*\"]" "$DIR/docker-compose.yml" fi - local _success_msg="\"Sign in with Authelia\" added to Mealie — local login still works too." - [[ "$_disable_local" =~ ^[Yy]$ ]] && _success_msg="\"Sign in with Authelia\" added to Mealie — local username/password login is now disabled." (cd "$DIR" && docker compose up -d) \ - && log_success "$_success_msg" \ + && log_success "\"Sign in with Authelia\" added to Mealie — local login still works too." \ || log_warning "Restart failed — check: docker compose -f $DIR/docker-compose.yml logs" declare -F _authelia_scope_access >/dev/null 2>&1 && _authelia_scope_access "mealie" "${BASE_URL#*://}" + + echo "" + log_info "Test the \"Login with Authelia\" button on Mealie's own login page before" + log_info "disabling local login — re-run 'sudo ./setup.sh mealie' (choose update," + log_info "then \"Reconfigure? n\") once you've confirmed it works, and you'll be" + log_info "offered that as a separate step." +} + +# Split out from _mealie_offer_authelia_oidc so disabling local login is +# never offered in the same breath as first setting SSO up — confirmed +# live (on Beszel, same risk class) that saying yes before actually testing +# the Authelia button leaves both login paths broken at once. Only reached +# from a later "update" rerun once OIDC is already configured and the admin +# declines to reconfigure — i.e. after they've had a real chance to test it. +_mealie_offer_disable_password_login() { + local DIR="$1" + grep -q '^ALLOW_PASSWORD_LOGIN=false' "$DIR/.env" 2>/dev/null && return 0 + + echo "" + local _tested="" + prompt_yn " Have you ALREADY logged into Mealie successfully using the Authelia button (not just enabled it)? (y/n):" "n" _tested + if [[ ! "$_tested" =~ ^[Yy]$ ]]; then + log_info "Skipped. Test the Authelia login button first, then re-run 'sudo ./setup.sh mealie' (choose update) to come back to this." + return 0 + fi + + local _disable_local="" + prompt_yn " Also disable Mealie's own username/password login, so Authelia is the only way in? (y/n):" "n" _disable_local + [[ "$_disable_local" =~ ^[Yy]$ ]] || return 0 + + log_warning "Anyone without an Authelia account (only a local Mealie one) will no longer be able to log in." + log_info "Reversible any time: set ALLOW_PASSWORD_LOGIN back to true in $DIR/.env and 'docker compose up -d'." + local _auto_redirect="" + prompt_yn " Skip Mealie's login page entirely and jump straight to Authelia? (y/n):" "y" _auto_redirect + + sed -i '/^ALLOW_PASSWORD_LOGIN=/d; /^OIDC_AUTO_REDIRECT=/d; /^OIDC_REMEMBER_ME=/d' "$DIR/.env" + { + echo "ALLOW_PASSWORD_LOGIN=false" + if [[ "$_auto_redirect" =~ ^[Yy]$ ]]; then + echo "OIDC_AUTO_REDIRECT=true" + echo "OIDC_REMEMBER_ME=true" + fi + } >> "$DIR/.env" + chown "$ACTUAL_USER:$ACTUAL_USER" "$DIR/.env" 2>/dev/null || true + + (cd "$DIR" && docker compose up -d) \ + && log_success "Local username/password login is now disabled — Authelia is the only way in." \ + || log_warning "Restart failed — check: docker compose -f $DIR/docker-compose.yml logs" } install_mealie() {