cakephp / authentication

Authentication plugin for CakePHP. Can also be used in PSR7 based applications.
MIT License
117 stars 100 forks source link

FAILURE_IDENTITY_NOT_FOUND #567

Closed berwynn closed 2 years ago

berwynn commented 2 years ago

Hello all,

Been to the support Slack and @LordSimal had a look at this issue, but I thought I might put it out there just in case anyone else has come across this.

First, the error message: FAILURE_IDENTITY_NOT_FOUND, I got this by adding debug($result) to the login method under UsersController.

public function login()
    {
        debug($_REQUEST);
        $result = $this->Authentication->getResult();
        debug($result);
        // If the user is logged in send them away.
        if ($result->isValid()) {
            $target = $this->Authentication->getLoginRedirect() ?? '/home';
            return $this->redirect($target);
        }
        if ($this->request->is('post')) {
            $this->Flash->error('Invalid username or password');
        }
    }

The entire message looks like this:

APP/Controller\UsersController.php (line 28)
object(Authentication\Authenticator\Result) id:0 {
protected _status => 'FAILURE_IDENTITY_NOT_FOUND'
protected _data => null
protected _errors => [
'Password' => [ ],
]
}

This is how my getAuthenticationService() from Application.php method looks like:

public function getAuthenticationService(ServerRequestInterface $request): AuthenticationServiceInterface
    {
        $service = new AuthenticationService();

        // Define where users should be redirected to when they are not authenticated
        $service->setConfig([
            'unauthenticatedRedirect' => Router::url([
                    'prefix' => false,
                    'plugin' => null,
                    'controller' => 'Users',
                    'action' => 'login',
            ]),
            'queryParam' => 'redirect',
        ]);

        $fields = [
            IdentifierInterface::CREDENTIAL_USERNAME => 'username',
            IdentifierInterface::CREDENTIAL_PASSWORD => 'password'
        ];
        // Load the authenticators. Session should be first.
        $service->loadAuthenticator('Authentication.Session');
        $service->loadAuthenticator('Authentication.Form', [
            'fields' => $fields,
            'loginUrl' => Router::url([
                'prefix' => false,
                'plugin' => null,
                'controller' => 'Users',
                'action' => 'login',
            ]),
        ]);

        // Load identifiers
        $service->loadIdentifier('Authentication.Password', compact('fields'));

        return $service;
    }

What my login.php looks like:

<?php
/**
 * @var \App\View\AppView $this
 * @var \App\Model\Entity\User $user
 * @var \Cake\Collection\CollectionInterface|string[] $accounts
 * @var \Cake\Collection\CollectionInterface|string[] $userGroups
 */
?>
<div class="row">
    <aside class="column">
        <div class="side-nav">
            <h4 class="heading"><?= __('Actions') ?></h4>
            <?= $this->Html->link(__('List Users'), ['action' => 'index'], ['class' => 'side-nav-item']) ?>
        </div>
    </aside>
    <div class="users form content">
        <?= $this->Form->create() ?>
        <fieldset>
            <legend><?= __('Please enter your email and password') ?></legend>
            <?= $this->Form->control('username') ?>
            <?= $this->Form->control('password') ?>
        </fieldset>
        <?= $this->Form->button(__('Login')); ?>
        <?= $this->Form->end() ?>
    </div>
</div>

I've implemented hashing on User.php:

// Hashing method
    protected function _setPassword(string $password) : ?string
    {
        if (strlen($password) > 0) {
            return (new DefaultPasswordHasher())->hash($password);
        }
    }

Can confirm that the account exists on the db: image

Beyond the above details, I am happy to provide any required information, but I hit a hard wall with this one, any help would be appreciated.

Thank you in advance!

berwynn commented 2 years ago

Well, this is a classic scenario, soon as I post a request, I find the solution.

Just in case anyone else runs into this issue here is what I got from: https://stackoverflow.com/questions/56148927/cakephp-authentication-login-action

It's Fernand Diaz's answer.

I was handed a copy of a DB of the original project, and upon looking turns out the type for the passwords was set to 40 characters. Which conflicted with the 60 that was generated by Cake.

Updated the column to varchar 255 and now it's working like a charm.

I hope my findings will helps other with the same issue.