From 9d3801494a882dfbd7935567aaf537084448a5dd Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 1 Sep 2026 19:26:29 +0000 Subject: [PATCH] Allow typing a password when adding/resetting Authelia users add_authelia_user() and the per-user "Reset password" action always auto-generated a random password with no way to set a specific one. Adds _authelia_prompt_password(), a shared masked-input prompt (same "[Enter = auto-generate]" convention already used by backup.sh/ borg-backup.sh/koha.sh) that both call sites now use, so an admin can type their own password or fall back to auto-generation as before. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_016oxpDzv7qfV7RDvKHp1sPD --- services/authelia.sh | 59 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 46 insertions(+), 13 deletions(-) diff --git a/services/authelia.sh b/services/authelia.sh index d2331bd..f4ed201 100644 --- a/services/authelia.sh +++ b/services/authelia.sh @@ -1356,6 +1356,29 @@ _authelia_gen_temp_password() { | fold -w1 | shuf | tr -d '\n' } +# Lets the admin type a specific password instead of always getting an +# auto-generated one — same masked-input, "[Enter = auto-generate]" +# convention services/backup.sh/borg-backup.sh/koha.sh already use for their +# own passwords, rather than inventing a separate typed-vs-generated menu +# choice here. Sets two out-params (not `local` — read them after the call +# returns, same convention as OIDC_CLIENT_SECRET_PLAIN elsewhere in this +# file): AUTHELIA_CHOSEN_PASSWORD (the plaintext, never written to disk — +# only its argon2 hash is) and AUTHELIA_PASSWORD_AUTO_GENERATED (so callers +# can word their own "here's the password" message correctly either way). +_authelia_prompt_password() { + AUTHELIA_CHOSEN_PASSWORD="" + AUTHELIA_PASSWORD_AUTO_GENERATED=false + local _pw="" + if [ "$UNATTENDED" != true ]; then + read -rsp " Password [Enter = auto-generate]: " _pw; echo + fi + if [ -z "$_pw" ]; then + _pw="$(_authelia_gen_temp_password)" + AUTHELIA_PASSWORD_AUTO_GENERATED=true + fi + AUTHELIA_CHOSEN_PASSWORD="$_pw" +} + # Adds a new user to an EXISTING Authelia instance's users.yml — the scripted # version of the manual "generate a hash, paste a users.yml block, restart" # steps this file's own generated README already documents. Non-destructive: @@ -1376,8 +1399,9 @@ add_authelia_user() { echo "" echo " Add a new user to this Authelia instance." - echo " They log in with their username (not email). A temporary password" - echo " is generated below — hand it to them directly. \"Forgot Password\"" + echo " They log in with their username (not email). You'll set a password" + echo " next — type your own or leave it blank to auto-generate one — shown" + echo " once here either way, never stored in plaintext. \"Forgot Password\"" echo " and Authelia's own Settings → Change Password both require working" echo " SMTP (both email a one-time code), so until that's fixed, use this" echo " menu's \"Edit an existing user\" → \"Reset password\" for future resets." @@ -1399,9 +1423,9 @@ add_authelia_user() { local NEW_ADMIN_YN="" prompt_yn " Grant admin group membership too? (y/n):" "n" NEW_ADMIN_YN - log_info "Generating temporary password + hash..." - local TEMP_PASS NEW_HASH - TEMP_PASS="$(_authelia_gen_temp_password)" + _authelia_prompt_password + local TEMP_PASS="$AUTHELIA_CHOSEN_PASSWORD" NEW_HASH + log_info "Generating password hash..." NEW_HASH=$(docker run --rm authelia/authelia:4.39.20 \ authelia crypto hash generate argon2 --password "$TEMP_PASS" 2>/dev/null \ | grep -oP '(?<=Digest: ).*') @@ -1439,8 +1463,12 @@ ${GROUPS_BLOCK}" fi echo "" - echo " New user: ${NEW_USERNAME}" - echo " Temp password: ${TEMP_PASS}" + echo " New user: ${NEW_USERNAME}" + if [ "$AUTHELIA_PASSWORD_AUTO_GENERATED" = true ]; then + echo " Temp password: ${TEMP_PASS}" + else + echo " Password: ${TEMP_PASS} (the one you just typed)" + fi echo " Give this to them directly (it's shown once, nothing stores it in" echo " plaintext). They can log in with it as-is and keep using it, or" echo " change it themselves from Authelia's Settings page — but that page" @@ -2697,7 +2725,7 @@ _authelia_manage_one_user() { echo "" echo " Editing user: $TARGET (admin: $IS_ADMIN, 2FA-exempt: $IS_EXEMPT)" echo " 1) Edit email / display name" - echo " 2) Reset password" + echo " 2) Set/reset password (type your own, or auto-generate)" echo " 3) Reset 2FA device (they register a new one on next login)" if [ "$IS_EXEMPT" = "yes" ]; then echo " 4) Restore the 2FA requirement for this user" @@ -2729,9 +2757,9 @@ _authelia_manage_one_user() { log_success "Updated $TARGET's email/display name." ;; 2) - log_info "Generating a new temporary password + hash..." - local NEW_TEMP_PASS NEW_HASH - NEW_TEMP_PASS="$(_authelia_gen_temp_password)" + _authelia_prompt_password + local NEW_TEMP_PASS="$AUTHELIA_CHOSEN_PASSWORD" NEW_HASH + log_info "Generating password hash..." NEW_HASH=$(docker run --rm authelia/authelia:4.39.20 \ authelia crypto hash generate argon2 --password "$NEW_TEMP_PASS" 2>/dev/null \ | grep -oP '(?<=Digest: ).*') @@ -2740,8 +2768,13 @@ _authelia_manage_one_user() { else _authelia_set_user_field "$USERS_FILE" "$START" "$END" "password" " password: \"${NEW_HASH}\"" chown 1000:1000 "$USERS_FILE" 2>/dev/null || true - log_success "Password reset for $TARGET." - echo " New password: ${NEW_TEMP_PASS}" + if [ "$AUTHELIA_PASSWORD_AUTO_GENERATED" = true ]; then + log_success "Password reset for $TARGET (auto-generated)." + echo " New password: ${NEW_TEMP_PASS}" + else + log_success "Password set for $TARGET." + echo " Password: ${NEW_TEMP_PASS} (the one you just typed)" + fi echo " Give this to them directly — shown once, not stored in plaintext anywhere." fi ;;