diff --git a/.env.example b/.env.example index 4fcf6ea56..585ffcc23 100644 --- a/.env.example +++ b/.env.example @@ -64,6 +64,10 @@ NODE_MAX_OLD_SPACE_SIZE=2048 # Default false. Enable only in trusted self-hosted networks. # OIDC_ALLOW_LOCAL_ISSUERS=false +# Disable username/password sign-in after at least one active administrator has linked an enabled +# OIDC provider. Set false and restart to recover access if the identity provider is unavailable. +# DISABLE_LOCAL_AUTH=false + # Optional: allow Cloudflare Web Analytics beacon when using automatic setup. # Keep unset/false to preserve strict CSP (`script-src 'self'`). # CSP_ALLOW_CLOUDFLARE_INSIGHTS=false diff --git a/README.md b/README.md index b823fed1a..898307823 100644 --- a/README.md +++ b/README.md @@ -95,6 +95,8 @@ docker compose up -d Open `http://your-server-ip:3000` and complete setup using your `SETUP_BOOTSTRAP_TOKEN`. +After configuring OIDC and linking at least one active administrator, you can set `DISABLE_LOCAL_AUTH=true` and restart BookOrbit to remove and reject password sign-in. BookOrbit refuses to start if that would leave no usable OIDC administrator. Set it back to `false` and restart to recover access during an identity-provider outage. + For the full installation guide including reverse proxy setup, file permissions on NAS, external databases, and environment variable reference, see **[bookorbit.app/installation](https://bookorbit.app/installation)**. ## KOReader Plugin diff --git a/client/src/features/admin/UserFormDrawer.vue b/client/src/features/admin/UserFormDrawer.vue index 4d975c020..7367991ca 100644 --- a/client/src/features/admin/UserFormDrawer.vue +++ b/client/src/features/admin/UserFormDrawer.vue @@ -37,6 +37,7 @@ const props = defineProps<{ canManageSuperuser?: boolean currentUserId?: number canDelete?: boolean + passwordLoginEnabled?: boolean }>() const emit = defineEmits<{ @@ -203,6 +204,14 @@ watch( }, ) +watch( + [() => props.user, () => props.passwordLoginEnabled], + ([user, passwordLoginEnabled]) => { + if (!user && passwordLoginEnabled !== true) isSharedAccount.value = true + }, + { immediate: true }, +) + function selectSection(section: UserFormSection) { activeSection.value = section } @@ -339,7 +348,10 @@ async function handleSubmit() {
-