PHP-Open-Source-Saver / jwt-auth

🔐 JSON Web Token Authentication for Laravel & Lumen
MIT License
729 stars 113 forks source link

Use with a custom (Statamic flat-file) User model (not Eloquent-based user model) #252

Closed CedsTrash closed 2 months ago

CedsTrash commented 5 months ago

Summary

Hi, I'm not sure if this a feature request or a bug.

I'm trying to implement this package in a Statamic (Flat-file CMS for Laravel) project. Out of the box, Statamic users are stored in flat files (yaml) instead of a database.

I created a new user provider in my AppServiceProvider.php. The provider is exactly the same as the standar Statamic one, with a distinct name:

use Statamic\Auth\UserProvider;

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        Auth::provider('jwt_statamic', function () {
            return new UserProvider;
        });
    }
}

Then I've set my provider in auth.php with my custom User model:

'providers' => [
        'users' => [
            'driver' => 'statamic',
        ],

        'jwt_users' => [
            'driver' => 'jwt_statamic',
            'model' => App\Models\JwtFileUser::class,
        ],
],

Here is my User model:

<?php

namespace App\Models;

use PHPOpenSourceSaver\JWTAuth\Contracts\JWTSubject;
use Statamic\Auth\File\User;

class JwtFileUser extends User implements JWTSubject
{
    /**
     * Get the identifier that will be stored in the subject claim of the JWT.
     *
     * @return mixed
     */
    public function getJWTIdentifier(): mixed
    {
        return $this->getKey();
    }

    /**
     * Return a key value array, containing any custom claims to be added to the JWT.
     *
     * @return array
     */
    public function getJWTCustomClaims(): array
    {
        return [];
    }
}

But I get an error message when I reach Auth::guard('api')->attempt($request->only('email', 'password'));:

<?php

namespace App\Http\Controllers;

use Illuminate\Support\Facades\Auth;
use Statamic\Http\Controllers\User\LoginController as BaseController;
use Statamic\Http\Requests\UserLoginRequest;

class JwtAuthController extends BaseController
{
    public function __construct()
    {
        $this->middleware('auth:api', ['except' => ['login']]);
    }

    public function login(UserLoginRequest $request)
    {
        // removed for simplicity

        $token = Auth::guard('api')->attempt($request->only('email', 'password'));

        // removed for simplicity
    }
}

The error message is the following:

TypeError: PHPOpenSourceSaver\JWTAuth\JWTGuard::login(): Argument #1 ($user) must be of type PHPOpenSourceSaver\JWTAuth\Contracts\JWTSubject, Statamic\Auth\File\User given, called in /vendor/php-open-source-saver/jwt-auth/src/JWTGuard.php on line 151 in file /vendor/php-open-source-saver/jwt-auth/src/JWTGuard.php on line 164

I'm surprised because my Model implements JWTSubject. So I'm guessing this happens because my User model doesn't extend a regular Laravel Eloquent User model?

Thanks for your help.

mfn commented 5 months ago

must be of type PHPOpenSourceSaver\JWTAuth\Contracts\JWTSubject, Statamic\Auth\File\User given

That's the wrong class. It should be JwtFileUser.

You need to configure / resolve to the correct instance

CedsTrash commented 5 months ago

must be of type PHPOpenSourceSaver\JWTAuth\Contracts\JWTSubject, Statamic\Auth\File\User given

That's the wrong class. It should be JwtFileUser.

You need to configure / resolve to the correct instance

Could you give me a hint on how to do this?

I thought this was it:

'providers' => [
    'jwt_users' => [
        'driver' => 'jwt_statamic',
        'model' => App\Models\JwtFileUser::class,
    ],
],

Thanks.

eschricker commented 5 months ago

I am not familiar with statamic, but have you checked, that the driver Statamic\Auth\UserProvider has support for defining own model classes?

CedsTrash commented 5 months ago

I am not familiar with statamic, but have you checked, that the driver Statamic\Auth\UserProvider has support for defining own model classes?

Hi, not out of the box, but I also tried to extend Statamic\Auth\UserProvider in order to pass it the custom model. But in the meantime I realized that this package dosen't separate the concepts of access and refresh tokens, so it won't cut it.

Thanks for your time anyway!