Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel Sanctum with uuid column in User model doesn't save tokenable_id

I'm try to use Laravel 8.x and Laravel sanctum 2.14.2 to authenticate my API and UUIDs as the primary key for my User model.

My custom PersonalAccessToken model

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Laravel\Sanctum\PersonalAccessToken as SanctumPersonalAccessToken;

class PersonalAccessToken extends SanctumPersonalAccessToken
{
    use HasFactory;

    protected $table = 'personal_access_tokens';

    public function tokenable()
    {
        return $this->morphTo('tokenable', "tokenable_type", "tokenable_id", "uuid");
    }
}

My personal_access_tokens migration schema

...
    public function up()
    {
        Schema::dropIfExists('personal_access_tokens');

        Schema::create('personal_access_tokens', function (Blueprint $table) {
            $table->id();
            $table->uuidMorphs('tokenable');
            $table->string('name');
            $table->string('token', 64)->unique();
            $table->text('abilities')->nullable();
            $table->timestamp('last_used_at')->nullable();
            $table->timestamps();
        });
    }
...

My AppServiceProvider

...
use App\Models\PersonalAccessToken;
use Illuminate\Support\Facades\URL;
use Illuminate\Support\ServiceProvider;
use Laravel\Sanctum\Sanctum;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        Sanctum::ignoreMigrations();
    }

    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        if($this->app->environment('production')) {
            URL::forceScheme('https');
        }

        Sanctum::usePersonalAccessTokenModel(PersonalAccessToken::class);
    }
}

When I try to get the token with $user->createToken($user->email)->plainTextToken, I get this error:

SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'tokenable_id' cannot be null (SQL: insert into `personal_access_tokens` (`name`, `token`, `abilities`, `tokenable_id`, `tokenable_type`, `updated_at`, `created_at`) values ([email protected], 85dbe44c32a999a01f4a97d9c9eab0710125a6ac5f861ab546a5822f61015b23, [\"*\"], ?, App\\Models\\User, 2022-03-20 19:16:43, 2022-03-20 19:16:43))

I think the cause of the error is that I am using uuid as the primary key in the users table

Schema::create('users', function (Blueprint $table) {
      $table->uuid('uuid')->primary();
      ...
});

UPDATE

My User Model

...
class User extends Authenticatable
{
    use HasUUID;
    use HasApiTokens;
    use HasFactory;
    use Notifiable;
    use HasRoles;

    ...

    public function tokens()
    {
        return $this->morphMany(Sanctum::$personalAccessTokenModel, 'tokenable', "tokenable_type", "tokenable_id");
    }
    
    ...
}

Any help would be appreciated.

like image 481
Ryo Avatar asked Oct 24 '25 08:10

Ryo


1 Answers

Is there any particular reason for you to create custom PersonalAccessToken model?

If it's just UUID that you want for the primary key of your User model, you can achieve it without creating the custom PersonalAccessToken model.

Your personal_access_tokens migration schema seems fine.

I think the cause of the error is that I am using uuid as the primary key in the users table

Schema::create('users', function (Blueprint $table) {
      $table->uuid('uuid')->primary();
      ...
});

This could be the issue. Try changing the column name to just id from uuid and see if it works

$table->uuid('id')->primary();

If you must use the column name as uuid for primary key, then try adding the following to your User model

protected $primaryKey='uuid'

By default eloquent assumes the name of the primary key column as 'id'. This will let eloquent know to look for 'uuid' as primary key column for User model.

Also since you are not using the default integer data type for primary key make sure you have the following in your User model

public $incrementing=false
protected $keyType='string'

You can refer to Laravel Documentation for Primary Keys

like image 135
Hussain Avatar answered Oct 25 '25 21:10

Hussain



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!