Project

General

Profile

Actions

Feature #91032

closed

FrontendUserAuthentication via email address

Added by C. Gogolin about 4 years ago. Updated over 3 years ago.

Status:
Closed
Priority:
Should have
Assignee:
-
Category:
felogin
Start date:
2020-04-14
Due date:
% Done:

0%

Estimated time:
PHP Version:
7.3
Tags:
felogin services xclass
Complexity:
medium
Sprint Focus:

Description

EN:

Hello,

i hope to find here the developer who created the system extension "felogin".

Currently I'm also trying to build a frontend user login extension, which allows a login via e-mail address.

If I have understood this correctly, the extension "felogin" does not perform its own authorization logic, but leaves that to the FrontendUserAuthentication. which listens for certain GET/POST attributes. This is very clever.

But unfortunately I can't get in between to exchange the email address for the username in my controller.

A redirect is used to... But who wants to have a password in the URL?

    $uri = $this->uriBuilder
                    ->reset()
                    ->setArguments( [
                    'logintype' => 'login',
                    'user' => $username, 
                    'pass' => $password,
                    pid => $this->getStoragePids(),
                    permalogin => $stayLoggedIn ? 1 : 0
                    ])
                    ->build();
      $this->redirectToURI($uri);

Currently I only see the option to extend the FrontendUserAuthentication#getLoginFormData() method via the Xclass API.

But this is not nice either... is there a better option? Is it easy to say from the controller: Please ask user XY to log in? Or a POST-Redirect ... or or or or ...

Unfortunately the services are well described and so are the controllers. But I haven't found anything, for example how the controllers access the services.

Would be really grateful for the help of the core developers.

Greetings
Clemens

Translated with www.DeepL.com/Translator

DE:
Hallo,

ich hoffe hier den Entwickler zu finden, der die System-Erweiterung "felogin" entwickelt hat.

Aktuell versuche ich auch eine Frontend user login Erweiterung zu bauen, welche ein Login auch via E-Mail-Adresse ermöglicht.

Wenn ich das richtig verstanden hab, führt die Erweiterung "felogin" keine eigene Autorisierungslogik durch, sondern überlässt das der FrontendUserAuthentication. Die auf bestimmte GET/POST-Attribute horcht. Das ist sehr clever.

Aber so komme ich leider nicht dazwischen, um in meinem Controller die E-Mail-Adresse gegen den Nutzername auszutauschen.

Über ein Redirect geht es zwar... Aber wer will ein Passwort schon in der URL haben?

    $uri = $this->uriBuilder
                    ->reset()
                    ->setArguments(                    [
                    'logintype' => 'login',
                    'user' => $username, 
                    'pass' => $password,
                    'pid' => $this->getStoragePids(),
                    'permalogin' => $stayLoggedIn ? 1 : 0
                    ])
                    ->build();
      $this->redirectToURI($uri);

Aktuell sehe ich nur die Option über das Xclass-API die Methode FrontendUserAuthentication#getLoginFormData() erweitern.

Das ist aber auch nicht schön... gibt es da noch eine bessere Option? Kann man vom Controller einfach sagen: Bitte den Nutzer XY bitte einloggen? Oder ein POST-Redirect ... oder oder oder....

Leider sind die Services gut beschrieben und die Controller auch. Aber ich habe nichts gefunden, wie beispielsweise die Controller auf die Dienste zugreifen.

Wäre echt dankbar über die geballte Hilfe von den Kernentwicklern.

Grüße
Clemens

Actions #1

Updated by C. Gogolin about 4 years ago

I have extended the FrontendUserAuthentication using the XClass-API.

This is everything but a nice solution, because it manipulates $_POST or $_GET afterwards.

But currently I don't see any other solution. And rebuilding the behaviour of FrontendUserAuthentication as I have seen in other extensions is IMHO even less sustainable.

It would be best if there was a hook or API for the frontend user login process so that it could be easily extended.

ext_localconf.php:

$GLOBALS['TYPO3_CONF_VARS']['SYS']['Objects'][TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication::class] = [
   'className' =>  Cylancer\Usertools\XClass\CyFrontendUserAuthentication::class

\Cylancer\Usertools\XClass\CyFrontendUserAuthentication:

<?php
namespace Cylancer\Usertools\XClass;

use TYPO3\CMS\Core\Utility\GeneralUtility;

/**
 * Extension class for Front End User Authentication.
 *  
 * This extension allows the login via e-mail or via user name.
 * 
 */
class CyFrontendUserAuthentication extends \TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication
{

        protected $email_column = 'email'; 

    /**
     * Returns an info array with Login/Logout data submitted by a form or params
     *
     * @return array
     * @see FrontendUserAuthentication::getLoginFormData()
     */
    public function getLoginFormData()
    {
                $username = GeneralUtility::_POST($this->formfield_uname);
                if($username != null ){
                    $_POST[$this->formfield_uname] = $this->mapEMailToUsername($username);
                }
                $username = GeneralUtility::_GET($this->formfield_uname);
                if($username != null ){
                    $_GET[$this->formfield_uname] = $this->mapEMailToUsername($username);
                }
                return parent::getLoginFormData(); 
    }

    /**
     * If you can deduce exactly one user name from the given e-mail address, 
     * the determined user name is returned. In all other cases the given $email 
     * will be returned unchanged. 
     * @param String $email is possibly an e-mail address. 
     */
    private function mapEMailToUsername($email){

                if(!filter_var($email, FILTER_VALIDATE_EMAIL)) {
                    return $email; 
                }    

                $qb = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Database\ConnectionPool::class)->getQueryBuilderForTable($this->user_table);
                $p_email = $qb->createNamedParameter($email); 
                $rows =  $qb->select($this->username_column, $this->email_column)
                                    ->from($this->user_table)
                                    ->where( $qb->expr()->eq( $this->username_column , $p_email))
                                    ->orWhere( $qb->expr()->eq( $this->email_column , $p_email))
                                    ->execute()
                                    ->fetchAll();

                if(count($rows) == 1) {
                     return $rows[0][$this->username_column]; 
                } else {
                    return $email; 
                }
        }

}

It might help someone...
Greetings
Clemens

Actions #2

Updated by C. Gogolin about 4 years ago

For a simple test use the extension:
https://extensions.typo3.org/extension/loginviaemail

Actions #3

Updated by Georg Ringer over 3 years ago

  • Status changed from New to Closed

thanks for creating this issue/feature request!

I don't see a reason why this shouldn't work by a custom service - see https://docs.typo3.org/m/typo3/reference-coreapi/master/en-us/ApiOverview/Authentication/Index.html for the docs. this allows you to hook into various steps during authentication.

Actions #4

Updated by C. Gogolin over 3 years ago

Thank you... I have now implemented a derivation of the FrontendUserAuthentication as an own service. This works. But I didn't dare to derive only from "AbstractUserAuthentication", too many features are implemented in FrontendUserAuthentication for that. :)

Actions

Also available in: Atom PDF