One of the most popular articles I posted on my old blog was a guide on how to authenticate frontend users against other data sources. This article is of course a bit outdated, so I like to update this guide and show how to do this with a current TYPO3 (9LTS, 10LTS).

Authenticate TYPO3 front end users against external data sources

Authenticate frontend users against other data sources

TYPO3 comes with a flexible and powerful way of user authentication against the local database. Even group rights are possible without problems.

Sometimes, however, it is necessary or desired that the website visitors do not log in against the local database, but that another service should be used. This can be another database, a login service or a web service (or of course something completely different). But how do you teach TYPO3 to use this login source?

Auth Services

First of all, we need to understand how TYPO3 handles the login of a frontend user. The relevant information is stored in the database table fe_users; this information is loaded into a user record during login, which in turn can be used by all plugins and extensions via the known mechanisms.

So we have to make sure that the information of our login also leads to such a user record and provide the necessary information.

This means in particular that this database table must also contain a record for each user, even if we authenticate against another database or against a web service.

In medias res

To create a new Auth service, we have to program an extension. But thanks to the clean API that TYPO3 brings along, this is not very complicated.

In the ext_localconf.php we register the new service:

 

\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addService(
    // Extension Key
    my_authentication,
    // Service type
    'auth',
    // Service key
    'tx_myauthentication_login',
    array(
        "title" => "My Authentication",
        'description' => 'An alternative way to login frontend users',

        "subtype" => '',

        'available' => true,
        priority => 60,
        "quality" => 80,

        "os" => '',
        "exec" => '',

        'className' => \MarcWillmann\MyAuthentication\Service\MyAuthenticatorService::class
    )
);

 

The sequence is determined by the parameters "priority" and "quality". The service with the highest priority (maximum 100) is queried first; then, if necessary (we will come back to this later) the others. If several services with the same priority are registered, the one with the highest quality "wins".

Now that we have registered the service in the system, we have to implement it, of course. To do this we create a class that inherits from the class \TYPO3\CMS\Core\Authentication\AbstractAuthenticationService. Before we do this, however, let us briefly consider how complicated our solution must be:

No personalized content

In some scenarios it is sufficient to allow or deny access to a user group. This is always the case if no personalized texts are to be displayed in the restricted area and if no special rights are assigned. In this simple scenario, the only question is whether a user is allowed to see the contents or not.

Here it is sufficient to have a single record in the VU user table and depending on the data source map to this user (the visitor may "enter") or not.

Or full flexibility

If we want to address the user personally later or take over group rights, we have to create a separate record for each user in the fe_user table. Here we should also consider how we remove these entries from the table when they are no longer needed or have expired.

A simple Auth service

But now it's time for the code. We create a new file Authenticator.php in the directory Classes/Services/ and implement our Authentication Service:

 

<?php
namespace MarcWillmann\MyAuthentication\Service

use \TYPO3\CMS\Core\Authentication\AbstractAuthenticationService;

class MyAuthenticatorService extends AbstractAuthenticationService 
{
   public function init() : boolean
   {
      // do all necessary stuff to enable the connection to external service 
      // and check availability of all necessary tools.

      // returns true if all dependencies are fulfilled, otherwise false.
   }

   public function reset() : void
   {
      // If needed: clean up and forget values of former authentications
   }

   public function authUser(array $user): int
   {
      // decide, if the given $user is allowed to acccess or not
   }

   /**
    * returns false or the user array
    **/ 
   public function getUser() : mixed
   {
      // is called to get additional information after login.
   }
}

 

The init method is called when the service is initialized. Here you should check if the service can work - are all tools available on the system? Is the web service/database/whatever accessible? If everything fits, this method returns true, otherwise false.

If a service is called more than once, no new instance is created. The reset method is the right place if cleanup work has to be done when a service is called more than once.

The authUser() method is the actual check whether or not the user will get access. Important: This method does not return a Boolean value, but an integer! The return code is important for the question whether further authentication services are requested in case the user could not be logged in. (Return code 0 (or smaller): Login failed, no more services are requested. Return code >= 200: Login succeeded, user is logged in. Return code 100 <= x < 200: Service is not responsible, user is not logged in: but the next service in the row should take over).

Here you can also see very clearly that the priority of the services is very important.

Important: As mentioned above, it is important that there is a matching record in the fe_user table. If personalized FE-User records are to be used, it is NOT sufficient to map to an existing user - in this case, the record must first be written to the fe_user table in the authUser() method (from the external data source).

function getUser()

This function is called by TYPO3 when details about the logged in user are requested. Again, the external data source can be queried, the fe_user table can be looked up (if the record was entered there) or a default record can be returned.

Thus, the basic framework for your own Auth service is already complete. Have fun implementing your own data source :-)

Comments (0)

No comments found!

Write new comment reply