Split "disable local login" from the initial SSO setup step

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.
This commit is contained in:
Claude
2026-08-25 13:18:15 +00:00
parent 49b965bd1d
commit 7209a32d43
2 changed files with 100 additions and 56 deletions
+47 -22
View File
@@ -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)
+53 -34
View File
@@ -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() {