fix(desec): only reveal the deSEC password for AIO-created accounts

The containers page showed "Reveal deSEC password" for every deSEC domain,
but when the user logs in with their own existing account AIO stores an
empty password, so the reveal exposed nothing useful. Gate the reveal on a
stored password: AIO-created accounts show the generated credentials as
before; existing accounts now just say the domain is managed via that
account and to log in at desec.io with your own password.

Also clear the stored generated password in the awaiting-verification path
when the user logs in with their own password (the email already had an
account), so a non-empty stored password reliably means "AIO generated this
account" — and report the account as not-new so no wildcard CNAME is created
on a domain the user manages themselves.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Simon L. <szaimen@e.mail.de>
This commit is contained in:
Simon L.
2026-06-22 15:38:51 +02:00
parent ebad4fd06f
commit 0d2ce61af3
2 changed files with 22 additions and 6 deletions
+10 -2
View File
@@ -99,12 +99,20 @@ class DesecManager {
if ($this->configurationManager->isDesecAwaitingVerification()) {
$storedEmail = $this->configurationManager->desecEmail;
// Prefer a freshly entered password (e.g. the user changed it), else the generated one.
$loginPassword = $validatedPassword !== '' ? $validatedPassword : $this->configurationManager->desecPassword;
$userSuppliedPassword = $validatedPassword !== '';
$loginPassword = $userSuppliedPassword ? $validatedPassword : $this->configurationManager->desecPassword;
$token = $this->loginAfterVerification($storedEmail, $loginPassword);
// Storing the token flips the state from "awaiting verification" to "account
// registered" (see ConfigurationManager::isDesecAwaitingVerification()).
$this->configurationManager->desecToken = $token;
return [$token, true];
// If the user logged in with their own password (the email already had a deSEC
// account, so no AIO account was created), the previously generated password is
// wrong and must not be persisted or later revealed. Clear it so a stored,
// non-empty password reliably means "AIO generated this account".
if ($userSuppliedPassword) {
$this->configurationManager->desecPassword = '';
}
return [$token, !$userSuppliedPassword];
}
$validatedEmail = $this->validateEmail($email);
+12 -4
View File
@@ -404,10 +404,18 @@
{% if is_desec_domain %}
<h2>deSEC account credentials</h2>
<p>Your domain <strong>{{ domain }}</strong> is managed via <a target="_blank" href="https://desec.io">deSEC</a>. Below are your deSEC account credentials. You can use them to log in at <a target="_blank" href="https://desec.io">desec.io</a> to manage your domain directly.</p>
<p>Email: <strong>{{ desec_email }}</strong></p>
<p><details class="inline-details"><summary>Reveal deSEC password</summary><strong>{{ desec_password }}</strong></details></p>
<p>Please save these credentials in a safe place.</p>
{% if desec_password %}
{# AIO created this account, so it generated and stored the password.
Show it so the user can log in at desec.io if they ever need to. #}
<p>Your domain <strong>{{ domain }}</strong> is managed via <a target="_blank" href="https://desec.io">deSEC</a>. Below are your deSEC account credentials. You can use them to log in at <a target="_blank" href="https://desec.io">desec.io</a> to manage your domain directly.</p>
<p>Email: <strong>{{ desec_email }}</strong></p>
<p><details class="inline-details"><summary>Reveal deSEC password</summary><strong>{{ desec_password }}</strong></details></p>
<p>Please save these credentials in a safe place.</p>
{% else %}
{# The user logged in with their own existing deSEC account; AIO never
stored their password, so there is nothing to reveal. #}
<p>Your domain <strong>{{ domain }}</strong> is managed via your existing <a target="_blank" href="https://desec.io">deSEC</a> account (<strong>{{ desec_email }}</strong>). Log in at <a target="_blank" href="https://desec.io">desec.io</a> with your own password to manage your domain directly.</p>
{% endif %}
{% endif %}
{% if is_backup_section_enabled == false %}