Building a member area on Core dna: who a member is in the data, the sign-in flows and their templates, single sign-on and passkeys, the my-account routing convention, members-only content, sessions and the page cache, and the security checks to run before launch.
L2
Unit 02 · Registration, sign-in and password recovery
Forgotten and reset passwords
Registration, sign-in and password recoveryPage 10 of 36Updated
A member who has forgotten their password asks for a link, the emailed link signs them in, and they choose a new password. Both halves, the link's lifetime and number of uses, the reset email and how to override it, and what a reset changes on the account.
Who this is for. The theme developer building the two password pages and the reset email. Afterwards you can build both halves, brand the email, and answer "how long does the link work?"
Asking for a link
users/forgot-password.html, which you write, posts email to /forgot-password. The form is for signed-out visitors. Whatever address is entered, the visitor is redirected to /login with the same message:
"If a user account with the specified email address exists, a password reset link has been sent to it."
So the form never reveals whether an address has an account. Behind that message, an email is sent only when the address belongs to a person whose user is active. An empty field re-renders the form with "The email address needs to be specified".
The link
The email holds a sign-in link, /token-login?t=…, built on a sign-in token made for the member (One-click sign-in links):
Property
Value
Works for
Two days from the request
After its first use
One more hour, if that is sooner
Uses
Up to ten, within those times
Lands on
/reset-password
Following the link signs the member in, with a full session, and then shows the reset page. If they close the tab there, they are still signed in. The link is therefore a credential, equal to the password for as long as it works: never log it, forward it or show it anywhere but in the email (Personal data in logs, emails and the browser). A link that has expired or been used up sends the visitor to /login with "Could not login using token: The token has expired".
Setting the new password
users/reset-password.html, which you write, posts password and confirmPassword to /reset-password as a PUT, with the CSRF token, since the member is signed in by then. It does not ask for the current password, because the emailed link proved the member's identity. Link to this page only from that flow; everywhere else, a member changes a known password at /change-password (Changing a password).
On success the member is sent to their account with "The password has been successfully changed". The page receives localPasswordEnabled and passkeyEnabled; where passkeys are on, it is also where a member can add a passkey instead (Passkeys). Setting a password needs password sign-in to be enabled for the site.
A reset also changes the account:
Password sign-in is switched on for the member if they did not have it, so a member who only ever used Google can sign in with the new password from then on.
Their other signed-in sessions are ended, apart from a device kept signed in with Remember me, and the one the link started is kept.
Template codetemplates/users/forgot-password.html, the form
<form method="post" action="{$_url->getPath('forgotPassword')}">
<label>Email address <input type="email" name="email" autocomplete="email" required></label>
<button>Send me a link</button>
</form>
<p>The link works for two days. Not there? Check your spam folder, or <a href="/contact">contact us</a>.</p>
<form method="post" action="{{ _url.getPath('forgotPassword') }}">
<label>Email address <input type="email" name="email" autocomplete="email" required></label>
<button>Send me a link</button>
</form>
<p>The link works for two days. Not there? Check your spam folder, or <a href="/contact">contact us</a>.</p>
The reset email
The email's body is a file, looked for first in your site and then in the framework:
templates/users/emails/reset-password-smarty.html on a Smarty site. The framework ships one, branded "Core dna".
templates/users/emails/reset-password-twig.html on a Twig site. The framework ships none, so a Twig site must supply it.
The file is not rendered as a page template. It is read as it stands, and placeholders written as %name% are replaced:
Any of the member's own person fields (%recipient.firstName%, %recipient.email%, and so on)
%showInBrowserUrl%
A link to view the email in the browser
A file that contains <body is sent as HTML; any other is sent as plain text. On a Twig site the placeholders are turned into Twig variables and the file is rendered with Twig, falling back to plain replacement if that fails, so keep Twig syntax out of the file unless you mean it.
The subject and sender are settings in the Users module, under Forgot password email in frontend. Their defaults name the platform, not the client, so change all three:
Setting
Default
Subject
Core dna: Password Reset
From email
no-reply@coredna.com
From name
Core dna DXP
Send from an address on the client's own domain, authenticated for sending, or the email is likely to be filtered as spam (The password reset email never arrives).
HTMLtemplates/users/emails/reset-password-smarty.html, a minimal HTML version
<html>
<body>
<p>Hello %firstName%,</p>
<p>Someone asked to reset the password for your account, %username%. To choose a new password, open this link within two days:</p>
<p><a href="%resetUrl%">Choose a new password</a></p>
<p>If it was not you, ignore this email: your password has not changed.</p>
</body>
</html>