Identity from Custom Authentication

Hello everyone. I am hoping someone can point me in the right direction. I am working on migrating a project from CakePHP 3 to CakePHP 5. The old project used a custom Auth component and I am struggling to migrate this to the new Authentication framework. I have created a custom identifier and can successfully authenticate. The problem is with the Identifier/Identity/Resolver portions of Authentication. The documentation, which seems to be limited, primarily references pulling identity information via a database and ORM. In this project, the user data is not stored in the local database. It is queried via API calls from a 3rd party system.

In the old Auth component, the API was queried as part of a custom authentication() function and set as follows.

$authenticate['id']             = $contact['id'];
$authenticate['username']       = $username;
$authenticate['role']           = $contact['role'];
$authenticate['first_name']     = $contact['first_name'];
$authenticate['last_name']      = $contact['last_name'];

This data was then available under the Auth key in the session.

What I cannot replicate is how to get the data for the user that is returned from the API call into CakePHP. Authentication->getIdentity() and Authentication->getIdentifier() both return null after a successful login.

Does anyone have a simple example setting the authentication identity to an array of information that is NOT from an SQL query?

Thank you.

Isnt the identity available as

$result = $this->Authentication->getResult();

if ($result && $result->isValid()) {
    /** @var \Authentication\Identity|null $identity */
    $identity = $this->request
        ->getAttribute('identity');

I have added the following helper method in my AppController to make sure I always get a user instance

    /**
     * @return \AlfredStaffMembers\Model\Entity\StaffMember
     */
    public function getLoggedInUser(): StaffMember
    {
        $staffMember = $this->Authentication->getIdentity()?->getOriginalData();

        if (!$staffMember instanceof StaffMember) {
            throw new RedirectException('/logout');
        }

        return $staffMember;
    }

I have a custom User rmodel called “StaffMember” as you can see.

It is not. It returns null.

Then you are not logged in / don’t have a persistent authenticator set up (like Session Authenticator)

According to the output of Authentication->getResult(), I am logged in (‘_status’ => ‘SUCCESS’).

2025-09-04 13:58:50 debug: Authentication->getResult() = \Authentication\Authenticator\Result::__set_state(array(
   '_status' => 'SUCCESS',
   '_data' =>
  array (
    'login_type' => 'customer',
    'contact' =>
    array (
      'id' => 1000,
      'custid' => 14175,
      'first_name' => 'Jim',
      'last_name' => 'Lohiser',
      'role' => 'Administrative',
    ),
    'customer' =>
    array (
      'id' => 14175,
      'name' => 'Jim Lohiser',
      'username' => 'jiml',
      'password' => 'xxxxxxxx',
    ),
    'fields' =>
    array (
      'id' => 1000,
      'email' => NULL,
    ),
  ),
   '_errors' =>
  array (
  ),
))

$service->loadAuthenticator() is being called in src/Application.php for both Authentication.Session and Authentication.Form, so session authentication should be enabled.

So I have made an incremental bit of progress. Authentication appears to be successful and I am able to pass all of the needed data from my custom Identifier class and then access it in a controller using the example below. This gives me access to the data in the “_data” protected property.

$authenticationResult = $this->Authentication->getResult();
    if ($authenticationResult && $authenticationResult->isValid()) {
        $authenticationData = $authenticationResult->getData();
    }
}

I am left with the issue of the missing identity, which I still have no idea how to solve. I am trying to find out where or how the identity is set. It does not appear to be set via the identify() function in the Identifier class or, if it is, I do not understand how to do it. Do I need to create a custom Resolver class in order to get getIdentity()/getIdentifier() return a result?

A little more progress. In identify() in my custom Identifier class, I am now returning an Identity object rather than just an array.

$data = [
    'id'         => $authPlatypus['contact']['id'],
    'login_type' => 'customer',
    'contact'    => $authPlatypus['contact'],
    'customer'   => $authPlatypus['customer'],
];
$identity = new Identity($data);
return $identity;

Then I added some temporary debug logging to vendor/cakephp/authentication/src/AuthenticationService.php to see what is happening.

getIdentity() gets the data from _result. Data looks ok.

2025-09-04 18:15:10 debug: Authentication\AuthenticationService->getIdentity() $this->_result = \Authentication\Authenticator\Result::__set_state(array(
   '_status' => 'SUCCESS',
   '_data' =>
  \Authentication\Identity::__set_state(array(
     '_defaultConfig' =>
    array (
      'fieldMap' =>
      array (
        'id' => 'id',
      ),
    ),
     'data' =>
    array (
      'id' => 1000,
      'login_type' => 'customer',
      'contact' =>
      array (
        'id' => 1000,
        'custid' => 14175,
        'first_name' => 'Jim',
        'last_name' => 'Lohiser',
        'role' => 'Administrative',
      ),
      'customer' =>
      array (
        'id' => 14175,
        'name' => 'Jim Lohiser',
        'username' => 'jiml',
        'password' => '********',
      ),
    ),
     '_config' =>
    array (
      'fieldMap' =>
      array (
        'id' => 'id',
      ),
    ),
     '_configInitialized' => true,
  )),
   '_errors' =>
  array (
  ),
))

getIdentity() then strips out the Identity object, puts it into $identityData, and then passes that to buildIdentity(). buildIdentity() checks to see if it is already an Identity object (it is) and then simply returns $identityData back to getIdentity(). getIdentity() ultimately returns the data in $identityData.

2025-09-04 18:15:10 debug: Authentication\AuthenticationService->getIdentity() $identityData = \Authentication\Identity::__set_state(array(
   '_defaultConfig' =>
  array (
    'fieldMap' =>
    array (
      'id' => 'id',
    ),
  ),
   'data' =>
  array (
    'id' => 1000,
    'login_type' => 'customer',
    'contact' =>
    array (
      'id' => 1000,
      'custid' => 14175,
      'first_name' => 'Jim',
      'last_name' => 'Lohiser',
      'role' => 'Administrative',
    ),
    'customer' =>
    array (
      'id' => 14175,
      'name' => 'Jim Lohiser',
      'username' => 'jiml',
      'password' => '********',
    ),
  ),
   '_config' =>
  array (
    'fieldMap' =>
    array (
      'id' => 'id',
    ),
  ),
   '_configInitialized' => true,
))

However, the next debug log is from the login() function in the controller right after it passes the authentication.

$result = $this->Authentication->getResult();
Log::debug('Authentication->getResult() = '.var_export($result, TRUE));
// If the user is logged in send them away.
if ($result && $result->isValid()) {
    Log::debug('Authentication->getIdentity() = '.var_export($this->Authentication->getIdentity(), TRUE));
    Log::debug('Authentication->getIdentifier() = '.var_export($this->Authentication->getIdentifier(), TRUE));
    return $this->redirect('/dashboard');
} 

And getIdentity() is now NULL.

2025-09-04 18:15:11 debug: Authentication->getIdentity() = NULL

Something is happening between these few lines of code above that seems to be causing the identity to be lost.

Solved. In my login() function, I was calling logout() before calling the example Authentication calls for logging in. This was a conversion from my old code for Auth. The reasoning behind it was that if a logged in user called the login action, then log them out and start a new login process. This does not work with the Authentication function. I removed the following line and everything is now working.

$this->Authentication->logout();