Backend login form API

Registering a login provider

The concept of the backend login is based on "login providers".

A login provider can be registered within your config/system/settings.php or config/system/additional.php like this:

config/system/additional.php | typo3conf/system/additional.php
$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['backend']['loginProviders'][1433416020] = [
    'provider' => \MyVendor\MyExtension\LoginProvider\CustomLoginProvider::class,
    'sorting' => 50,
    'iconIdentifier' => 'actions-key',
    'label' => 'LLL:EXT:backend/Resources/Private/Language/locallang.xlf:login.link'
];
Copied!

The settings are defined as:

provider
The login provider class name, which must implement \TYPO3\CMS\Backend\LoginProvider\LoginProviderInterface .
sorting
The sorting is important for the ordering of the links to the possible login providers on the login screen.
iconIdentifier
Accepts any icon identifier that is available in the Icon Registry.
label
The label for the login provider link on the login screen.

For a new login provider you have to register a new key - by best practice the current unix timestamp - in $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['backend']['loginProviders'] .

If your login provider extends another one, you may only overwrite necessary settings. An example would be to extend an existing provider and replace its registered provider class with your custom class.

config/system/additional.php | typo3conf/system/additional.php
$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['backend']['loginProviders'][1433416020]['provider'] =
    \MyVendor\MyExtension\LoginProvider\CustomProviderExtendingUsernamePasswordLoginProvider::class
Copied!

LoginProviderInterface

Deprecated since version 13.3

Method LoginProviderInterface->render() has been marked as deprecated and is substituted by LoginProviderInterface->modifyView() that will be added to the interface in TYPO3 v14, removing render() from the interface in v14. See section Migration.

The LoginProviderInterface contains only the deprecated render() method in TYPO3 v13.

interface LoginProviderInterface
Fully qualified name
\TYPO3\CMS\Backend\LoginProvider\LoginProviderInterface

Interface for Backend Login providers

modifyView ( \Psr\Http\Message\ServerRequestInterface $request, \TYPO3\CMS\Core\View\ViewInterface $view)

Interface to render the backend login view.

See UsernamePasswordLoginProvider on how this can be used.

param $request

the request

param $view

the view

Return description

Template file to render

Returns
string

Migration

Consumers of LoginProviderInterface should implement the modifyView() method and and retain a stub for the render() method to satisfy the interface. See the example below.

The transition should be smooth. Consumers that need \TYPO3\CMS\Core\Page\PageRenderer for JavaScript magic, should use dependency injection to receive an instance of it.

An implementation of LoginProviderInterface could look like this for TYPO3 v13:

EXT:my_extension/Classes/Login/MyLoginProvider.php
<?php

namespace MyVendor\MyExtension\Login;

use Psr\Http\Message\ServerRequestInterface;
use Symfony\Component\DependencyInjection\Attribute\Autoconfigure;
use TYPO3\CMS\Backend\LoginProvider\LoginProviderInterface;
use TYPO3\CMS\Core\Page\PageRenderer;
use TYPO3\CMS\Core\View\ViewInterface;
use TYPO3\CMS\Fluid\View\FluidViewAdapter;

#[Autoconfigure(public: true)]
final readonly class MyLoginProvider implements LoginProviderInterface
{
    public function __construct(
        private PageRenderer $pageRenderer,
    ) {}

    public function modifyView(ServerRequestInterface $request, ViewInterface $view): string
    {
        $this->pageRenderer->addJsFile('someFile');
        // Custom login provider implementations can add custom fluid lookup paths.
        if ($view instanceof FluidViewAdapter) {
            $templatePaths = $view->getRenderingContext()->getTemplatePaths();
            $templateRootPaths = $templatePaths->getTemplateRootPaths();
            $templateRootPaths[] = 'EXT:my_extension/Resources/Private/Templates';
            $templatePaths->setTemplateRootPaths($templateRootPaths);
        }
        $view->assign('Some Variable', 'some value');
        return 'Login/MyLoginForm';
    }
}
Copied!

The default implementation in UsernamePasswordLoginProvider is a good example. Extensions that need to configure additional template, layout or partial lookup paths can extend them, see lines 23-28 in the example above.

Consumers of ModifyPageLayoutOnLoginProviderSelectionEvent should use the request instead, and/or should get an instance of PageRenderer injected as well.

The view

Deprecated since version 13.3

Method LoginProviderInterface->render() has been marked as deprecated and is substituted by LoginProviderInterface->modifyView() that will be added to the interface in TYPO3 v14, removing render() from the interface in v14. See section Migration.

The name of the template must be returned by the modifyView() method of the login provider. Variables can be assigned to the view supplied as second parameter.

The template file must only contain the form fields, not the form-tag. Later on, the view renders the complete login screen.

View requirements:

  • The template must use the Login-layout provided by the Core <f:layout name="Login">.
  • Form fields must be provided within the section <f:section name="loginFormFields">.
EXT:my_sitepackage/Resources/Private/Templates/MyLoginForm.html
<f:layout name="Login" />
<f:section name="loginFormFields">
    <div class="form-group t3js-login-openid-section" id="t3-login-openid_url-section">
        <div class="input-group">
            <input
                type="text"
                id="openid_url"
                name="openid_url"
                value="{presetOpenId}"
                autofocus="autofocus"
                placeholder="{f:translate(key: 'openId', extensionName: 'openid')}"
                class="form-control input-login t3js-clearable t3js-login-openid-field"
            >
            <div class="input-group-addon">
                <span class="fa fa-openid"></span>
            </div>
        </div>
    </div>
</f:section>
Copied!

Examples

Within the Core you can find the standard implementation in the system extension backend:

See class EXT:backend/Classes/LoginProvider/UsernamePasswordLoginProvider.php (GitHub) with its template EXT:backend/Resources/Private/Templates/Login/UserPassLoginForm.html (GitHub).