Guide 07 · Developer docs

Members, accounts and gated content

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

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:

MethodReturns
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 code templates/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:

MethodReturns
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).

Go deeper

Was this page helpful?

Your answer goes to the docs team.