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

**URL:** <https://discourse.cakephp.org/t/help-with-token-authentication-in-cakedc-users-cakephp-4/12430>\
**Category:** Plugins\
**Created:** [February 21, 2025, 1:46pm UTC](https://discourse.cakephp.org/t/help-with-token-authentication-in-cakedc-users-cakephp-4/12430 "2025-02-21T13:46:34Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![atlet](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.cakephp.org/atlet/32/129_2.png) [@atlet](https://discourse.cakephp.org/u/atlet)\
**Post date:** [February 21, 2025, 1:46pm UTC](https://discourse.cakephp.org/t/help-with-token-authentication-in-cakedc-users-cakephp-4/12430/1 "2025-02-21T13:46:34Z")

</div>

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!

---

<div class="post-metadata">

**Author:** ![KevinPfeifer](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.cakephp.org/kevinpfeifer/32/3365_2.png) [@KevinPfeifer](https://discourse.cakephp.org/u/KevinPfeifer)\
**Post date:** [February 22, 2025, 8:53am UTC](https://discourse.cakephp.org/t/help-with-token-authentication-in-cakedc-users-cakephp-4/12430/2 "2025-02-22T08:53:54Z")

</div>

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.

```php
/**
 * @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

```php
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](https://book.cakephp.org/4/en/views/json-and-xml-views.html)

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

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

```

---

<div class="post-metadata">

**Author:** ![atlet](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.cakephp.org/atlet/32/129_2.png) [@atlet](https://discourse.cakephp.org/u/atlet)\
**Post date:** [February 23, 2025, 8:35pm UTC](https://discourse.cakephp.org/t/help-with-token-authentication-in-cakedc-users-cakephp-4/12430/3 "2025-02-23T20:35:35Z")

</div>

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.
