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 03 · Authenticators, SSO and linked accounts
Authorised applications and signed-in sessions
Authenticators, SSO and linked accountsPage 21 of 36Updated
Two member screens the platform ships routes for: the applications a member has allowed to act for them, with a way to revoke each, and the member's signed-in sessions, with a way to end them. What each shows, the routes behind their buttons, and when a site needs them.
Who this is for. The theme developer deciding which account screens to offer, and building them. Afterwards you know what the two screens do and whether a site needs them.
Authorised applications
Every site is also an OAuth server: an application, such as a mobile app or a partner's service, can ask a member to let it act on their behalf, and the member agrees on a consent screen (OAuth clients). /my-account/applications, route applications in the MyAccount module, lists the applications the member has agreed to, so they can withdraw that permission.
It renders o-auth/user-o-auth-clients/index.html, which your site must write (the framework's copy under users/user-o-auth-clients/ is not read by this route). It receives userOAuthClients, the member's consents, each with:
Method
Returns
getApp()
The application, with getName()
getConsentDate()
When the member agreed
getScope()
What the application was allowed, as the scope string it asked for
getId()
The consent's id, for the revoke button
Revoking is DELETE /oauth/applications/{id}, route deleteApplication in the OAuth module, with the consent's id and the CSRF token. It removes the member's consent for that application and deletes the application's current access and refresh tokens for the member, so the application loses access straight away and must ask again.
When a site needs it: only if outside applications sign members in through the site, such as the client's own mobile app or a partner integration acting for individual members. A brochure or shop site whose members only use the website has nothing to list; leave the screen and its menu link out.
Template codetemplates/o-auth/user-o-auth-clients/index.html, the list
{foreach $userOAuthClients as $consent}
<form method="post" action="{$_url->getPath('OAuth', 'deleteApplication', ['id' => $consent->getId()])}">
<input type="hidden" name="_method" value="DELETE">
<input type="hidden" name="_csrf" value="{$_csrfToken}">
{$consent->getApp()->getName()|escape}, allowed {$consent->getConsentDate()|format:'date'}
<button>Revoke</button>
</form>
{foreachelse}
<p>You have not allowed any applications to use your account.</p>
{/foreach}
{% for consent in userOAuthClients %}
<form method="post" action="{{ _url.getPath('OAuth', 'deleteApplication', {'id': consent.getId()}) }}">
<input type="hidden" name="_method" value="DELETE">
<input type="hidden" name="_csrf" value="{{ _csrfToken }}">
{{ consent.getApp().getName()|e }}, allowed {{ consent.getConsentDate()|date('j F Y') }}
<button>Revoke</button>
</form>
{% else %}
<p>You have not allowed any applications to use your account.</p>
{% endfor %}
Signed-in sessions
/my-account/current-activity, route currentActivity in the MyAccount module, lists every place the member is signed in: each browser, device or application holding a sign-in that has not expired. It renders users/users/current-activity.html, which the framework ships in Smarty, and receives currentActivity, a list of sign-ins, each with:
Method
Returns
getApp()
What the sign-in is for, with getName(): the website itself, or an application
getCreated()
When the member signed in
getUserAgent(), getIpAddress()
The browser and the address it signed in from
isCurrentToken()
Whether this is the session viewing the page
Ending one is DELETE /oauth/access-token/{id}, route deleteAccessToken in the OAuth module, with the CSRF token; that device is signed out at its next request. Sent without an id, it ends every session, the current one included, so label that button "Sign out everywhere" and expect the member to land on the sign-in page. Both return to this screen.
The screen is worth offering on any member site: it answers "am I still signed in on the library computer?" without a support call. Print the user agent in words a member recognises, or at least shortened, and mark the current session so it is not ended by mistake. Changing the password also ends every other session (What happens to other sessions).