Merge feature/otp-off-by-default
This commit is contained in:
+4
-3
@@ -13,10 +13,11 @@ EMIT_SECRET=
|
|||||||
SMTP_USERNAME=
|
SMTP_USERNAME=
|
||||||
SMTP_PASSWORD=
|
SMTP_PASSWORD=
|
||||||
|
|
||||||
# Email OTP on sign-in. Leave true; only the exact value "false" makes sign-in
|
# Email OTP on sign-in. Off by default; only the exact value "true" turns it on,
|
||||||
# password only (logged as OTP_BYPASSED, shown on the login page and top bar).
|
# and that needs working SMTP. While off, sign-in is password only (logged as
|
||||||
|
# OTP_BYPASSED, shown on the login page and top bar).
|
||||||
# Applied to app/config.php by the php container on every start.
|
# Applied to app/config.php by the php container on every start.
|
||||||
OTP_REQUIRED=true
|
OTP_REQUIRED=false
|
||||||
|
|
||||||
# Port to expose the web app on (default 80)
|
# Port to expose the web app on (default 80)
|
||||||
HTTP_PORT=80
|
HTTP_PORT=80
|
||||||
|
|||||||
@@ -3,21 +3,22 @@
|
|||||||
//
|
//
|
||||||
// Email OTP login policy, set by OTP_REQUIRED in config.php.
|
// Email OTP login policy, set by OTP_REQUIRED in config.php.
|
||||||
//
|
//
|
||||||
// Fails safe: the OTP step is off only when the constant is defined and is
|
// OFF BY DEFAULT: the OTP step runs only when the constant is defined and is
|
||||||
// exactly the boolean false. A missing constant (any config.php written before
|
// exactly the boolean true. A missing constant (any config.php written before
|
||||||
// this switch existed), 0, 'false' or a typo all keep it on.
|
// this switch existed), 1, 'true' or a typo all leave it off, so sign-in is
|
||||||
|
// password only and no SMTP is needed to log in.
|
||||||
//
|
//
|
||||||
// While it is off, every sign-in that skips the OTP because of it is logged as
|
// While it is off, every sign-in that skips the OTP because of it is logged as
|
||||||
// OTP_BYPASSED, and the login page and top bar both say so on screen — a
|
// OTP_BYPASSED, and the login page and top bar both say so on screen — a
|
||||||
// weakened sign-in must never be invisible to whoever is using it.
|
// password-only sign-in must never be invisible to whoever is using it.
|
||||||
//
|
//
|
||||||
// Only the login OTP is affected. The staff/viewer and no-SMTP skips in
|
// Only the login OTP is affected. When it is on, the staff/viewer and no-SMTP
|
||||||
// login_otp.php still apply when it is on, and password-reset OTPs
|
// skips in login_otp.php still apply; password-reset OTPs (PasswordResetManager)
|
||||||
// (PasswordResetManager) are a separate flow that stays on regardless.
|
// are a separate flow that stays on regardless.
|
||||||
|
|
||||||
if (!function_exists('otp_required')) {
|
if (!function_exists('otp_required')) {
|
||||||
function otp_required(): bool {
|
function otp_required(): bool {
|
||||||
return !(defined('OTP_REQUIRED') && OTP_REQUIRED === false);
|
return defined('OTP_REQUIRED') && OTP_REQUIRED === true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -26,7 +27,7 @@ if (!function_exists('otp_log_bypass')) {
|
|||||||
// log (the container's Apache log) under a fixed, greppable tag.
|
// log (the container's Apache log) under a fixed, greppable tag.
|
||||||
function otp_log_bypass($user_id, string $where): void {
|
function otp_log_bypass($user_id, string $where): void {
|
||||||
error_log(sprintf(
|
error_log(sprintf(
|
||||||
'[auth] OTP_BYPASSED user_id=%d ip=%s where=%s -- OTP_REQUIRED=false in config.php',
|
'[auth] OTP_BYPASSED user_id=%d ip=%s where=%s -- OTP_REQUIRED is not true in config.php',
|
||||||
(int)$user_id,
|
(int)$user_id,
|
||||||
$_SERVER['REMOTE_ADDR'] ?? '-',
|
$_SERVER['REMOTE_ADDR'] ?? '-',
|
||||||
$where
|
$where
|
||||||
|
|||||||
@@ -39,13 +39,12 @@ if (!defined('NODE_EMIT_SECRET')) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ── Login OTP ────────────────────────────────────────────────────────────────
|
// ── Login OTP ────────────────────────────────────────────────────────────────
|
||||||
// Email OTP on sign-in. LEAVE THIS TRUE unless password-only sign-in is wanted
|
// Email OTP on sign-in. OFF BY DEFAULT: only the boolean true turns it on —
|
||||||
// on purpose (e.g. a demo). It fails safe: anything other than the boolean
|
// anything else, the constant being absent included, leaves sign-in password
|
||||||
// false — the constant being absent included — keeps the OTP step on. While it
|
// only (logged as OTP_BYPASSED, shown on the login page and top bar). Turn it
|
||||||
// is off, every sign-in is logged as OTP_BYPASSED and the login page and top
|
// on only with working SMTP. Password-reset OTPs are not affected.
|
||||||
// bar both say so. Password-reset OTPs are not affected.
|
|
||||||
if (!defined('OTP_REQUIRED')) {
|
if (!defined('OTP_REQUIRED')) {
|
||||||
define('OTP_REQUIRED', true);
|
define('OTP_REQUIRED', false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Usage packages ───────────────────────────────────────────────────────────
|
// ── Usage packages ───────────────────────────────────────────────────────────
|
||||||
|
|||||||
@@ -199,12 +199,12 @@ $_usage_full = $_usage_max_pct >= 100;
|
|||||||
</li>
|
</li>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<!-- Email OTP off: a weakened sign-in must never be invisible to whoever is using it -->
|
<!-- Email OTP off (the default): a password-only sign-in must never be invisible to whoever is using it -->
|
||||||
<?php if (!otp_required()): ?>
|
<?php if (!otp_required()): ?>
|
||||||
<li class="d-none d-md-block">
|
<li class="d-none d-md-block">
|
||||||
<span class="badge bg-warning text-dark d-flex align-items-center gap-1 px-2 py-1"
|
<span class="badge bg-warning text-dark d-flex align-items-center gap-1 px-2 py-1"
|
||||||
style="font-size:11px; cursor:default;"
|
style="font-size:11px; cursor:default;"
|
||||||
title="OTP_REQUIRED=false in config.php">
|
title="OTP_REQUIRED is not true in config.php">
|
||||||
<i class="ti ti-shield-off"></i>
|
<i class="ti ti-shield-off"></i>
|
||||||
OTP off
|
OTP off
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
+4
-4
@@ -34,10 +34,10 @@
|
|||||||
|
|
||||||
<form class="needs-validation mt-3" novalidate id="login-form">
|
<form class="needs-validation mt-3" novalidate id="login-form">
|
||||||
<?php if (!otp_required()): ?>
|
<?php if (!otp_required()): ?>
|
||||||
<!-- OTP_REQUIRED=false in config.php: a weakened sign-in must never be invisible -->
|
<!-- OTP_REQUIRED is not true in config.php (the default): a password-only sign-in must never be invisible -->
|
||||||
<div class="alert alert-warning small py-2 mb-3" title="OTP_REQUIRED=false in config.php">
|
<div class="alert alert-warning small py-2 mb-3" title="OTP_REQUIRED is not true in config.php">
|
||||||
<i class="ti ti-alert-triangle me-1"></i>
|
<i class="ti ti-alert-triangle me-1"></i>
|
||||||
Email OTP is temporarily disabled — sign-in is password only.
|
Email OTP is off — sign-in is password only.
|
||||||
</div>
|
</div>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<!-- first step login [OTP] -->
|
<!-- first step login [OTP] -->
|
||||||
@@ -59,7 +59,7 @@
|
|||||||
|
|
||||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||||
<!-- "Remember me" is intentionally excluded.
|
<!-- "Remember me" is intentionally excluded.
|
||||||
This login uses 2FA (OTP via email) on every session, unless OTP_REQUIRED=false in config.php.
|
This login uses 2FA (OTP via email) on every session when OTP_REQUIRED=true in config.php (off by default).
|
||||||
A persistent login would bypass the OTP step and undermine the security model.
|
A persistent login would bypass the OTP step and undermine the security model.
|
||||||
Do not add this back. -->
|
Do not add this back. -->
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+1
-1
@@ -22,7 +22,7 @@ services:
|
|||||||
EMIT_SECRET: ${EMIT_SECRET}
|
EMIT_SECRET: ${EMIT_SECRET}
|
||||||
SMTP_USERNAME: ${SMTP_USERNAME}
|
SMTP_USERNAME: ${SMTP_USERNAME}
|
||||||
SMTP_PASSWORD: ${SMTP_PASSWORD}
|
SMTP_PASSWORD: ${SMTP_PASSWORD}
|
||||||
OTP_REQUIRED: ${OTP_REQUIRED:-true}
|
OTP_REQUIRED: ${OTP_REQUIRED:-false}
|
||||||
volumes:
|
volumes:
|
||||||
- .:/var/www/html/wms-app
|
- .:/var/www/html/wms-app
|
||||||
ports:
|
ports:
|
||||||
|
|||||||
+1
-1
@@ -55,7 +55,7 @@ PUBLIC_HOST=$public_host
|
|||||||
EMIT_SECRET=$emit_secret
|
EMIT_SECRET=$emit_secret
|
||||||
SMTP_USERNAME=$smtp_user
|
SMTP_USERNAME=$smtp_user
|
||||||
SMTP_PASSWORD=$smtp_pass
|
SMTP_PASSWORD=$smtp_pass
|
||||||
OTP_REQUIRED=true
|
OTP_REQUIRED=false
|
||||||
HTTP_PORT=$http_port
|
HTTP_PORT=$http_port
|
||||||
EOF
|
EOF
|
||||||
chmod 600 "$ENV_FILE"
|
chmod 600 "$ENV_FILE"
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ if (!defined('NODE_EMIT_SECRET')) {
|
|||||||
|
|
||||||
// ── Login OTP ────────────────────────────────────────────────────────────────
|
// ── Login OTP ────────────────────────────────────────────────────────────────
|
||||||
// Set from OTP_REQUIRED in .env and reconciled by the entrypoint on every start.
|
// Set from OTP_REQUIRED in .env and reconciled by the entrypoint on every start.
|
||||||
// Fails safe: anything other than the boolean false keeps the OTP step on.
|
// Off by default: anything other than the boolean true leaves the OTP step off.
|
||||||
if (!defined('OTP_REQUIRED')) {
|
if (!defined('OTP_REQUIRED')) {
|
||||||
define('OTP_REQUIRED', ${OTP_REQUIRED});
|
define('OTP_REQUIRED', ${OTP_REQUIRED});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ set -e
|
|||||||
APP_DIR=/var/www/html/wms-app
|
APP_DIR=/var/www/html/wms-app
|
||||||
CONFIG=$APP_DIR/app/config.php
|
CONFIG=$APP_DIR/app/config.php
|
||||||
|
|
||||||
# Email OTP on sign-in. Anything but the exact string "false" means required,
|
# Email OTP on sign-in, OFF BY DEFAULT. Only the exact string "true" turns it
|
||||||
# so a typo or a missing variable can never switch it off.
|
# on; a missing variable or anything else means false.
|
||||||
: "${OTP_REQUIRED:=true}"
|
: "${OTP_REQUIRED:=false}"
|
||||||
[ "$OTP_REQUIRED" = "false" ] || OTP_REQUIRED=true
|
[ "$OTP_REQUIRED" = "true" ] || OTP_REQUIRED=false
|
||||||
export OTP_REQUIRED
|
export OTP_REQUIRED
|
||||||
|
|
||||||
# Generate app/config.php from template on first run only.
|
# Generate app/config.php from template on first run only.
|
||||||
@@ -34,7 +34,7 @@ else
|
|||||||
echo "[entrypoint] added OTP_REQUIRED = ${OTP_REQUIRED} to an existing config.php"
|
echo "[entrypoint] added OTP_REQUIRED = ${OTP_REQUIRED} to an existing config.php"
|
||||||
fi
|
fi
|
||||||
if [ "$OTP_REQUIRED" = "false" ]; then
|
if [ "$OTP_REQUIRED" = "false" ]; then
|
||||||
echo "[entrypoint] WARNING -- email OTP is OFF; sign-in is password only."
|
echo "[entrypoint] email OTP is off (OTP_REQUIRED=false); sign-in is password only."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
mkdir -p "$APP_DIR/app/uploads"
|
mkdir -p "$APP_DIR/app/uploads"
|
||||||
|
|||||||
Reference in New Issue
Block a user