Help with Token Authentication in CakeDC/Users (CakePHP 4)

Hi everyone,

I’m using the CakeDC/Users plugin in my CakePHP 4 application for user authentication via form login. Now, I’m working on an API that uses token-based authentication, and so far, everything is working well.

However, I’m struggling with creating an API endpoint that allows users to obtain a token by sending their username and password via a POST request. Ideally, I’d like to implement a function that verifies the credentials and returns a valid authentication token.

Has anyone done something similar with CakeDC/Users? What would be the best approach to achieve this?

Thanks in advance for any guidance!

There are multiple ways how you can achieve that, but the most straight forward way would be to just manually create a controller action, create the hashed password and check, if a user is present with the given username and password.

/**
 * @return \Cake\Http\Response
 */
public function login(): Response
{
    $this->request->allowMethod(['post']);
    $data = $this->request->getData();
    $username = $data['username'];
    $password = $data['password'];

    $user = $this->Users->find()
        ->where([
            'username' => $username,
            'is_active' => true,
        ])
        ->first();

    if ($user=== null) {
        $result = ['error' => __('Invalid username or password.')];
        $this->setSerialized(compact('result'));

        return $this->render();
    }

    // Check if password matches
    $defaultPasswordHasher = new DefaultPasswordHasher();
    $hashedPassword = $user->get('password');
    $passwordMatches = $defaultPasswordHasher->check($password, $hashedPassword);
    if (!$passwordMatches) {
        $result = ['error' => __('Invalid username or password.')];
        $this->setSerialized(compact('result'));

        return $this->render();
    }

    $token = $user->get('api_token');
    $this->setSerialized(compact('token'));

    return $this->render();
}

I have this controller configured to also allow to send back JSON responses via

use Cake\View\JsonView;

public function viewClasses(): array
{
    return [JsonView::class];
}

if you don’t know what that is see JSON and XML views - 4.x

setSerialized() is just a helper method I added in my AppController to easily set view data which should be - well - serialized.

    public function setSerialized(array $data): void
    {
        $this->set($data);
        $this->viewBuilder()->setOption('serialize', array_keys($data));
    }
2 Likes

Tnx @KevinPfeifer for a really helpful response. This is what I was thinking of last resort so I asked here for a better solution. But for now this will be the solution. Tnx again.