mariovalney / laravel-keycloak-web-guard

Simple Keycloak Guard to Laravel Web Routes - https://packagist.org/packages/vizir/laravel-keycloak-web-guard
146 stars 80 forks source link

question: how i should relationship KeyCloakUser with other entities? #32

Closed gpedro closed 4 years ago

gpedro commented 4 years ago

how i should relationship KeyCloakUser with other entities?

example: a single user can have many Tasks.

gpedro commented 4 years ago

~i found this article to add user uuid, but i need to check how to use this... https://stackoverflow.com/a/45926963~

-- my solution to reference items

step 01

setup our auth driver to use our own model


        'users' => [
            'driver' => 'keycloak-users',
            'model' => \App\User::class,
        ],

step 02

extends our user model to KeyCloakUser

<?php

namespace App;

use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Notifications\Notifiable;
use Vizir\KeycloakWebGuard\Models\KeycloakUser;

class User extends KeycloakUser
{
    use Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name', 'email'
    ];

}

step 03

add sub attribute into $fillable array model

    protected $fillable = [
        'name', 'email', 'sub'
    ];

step 04

override the getKey method to use sub (uuid)


    /**
     * Get the value of the model's primary key.
     *
     * @return mixed
     */
    public function getKey()
    {
        return $this->attributes['sub'];
    }

final user model

<?php

namespace App;

use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Notifications\Notifiable;
use Vizir\KeycloakWebGuard\Models\KeycloakUser;

class User extends KeycloakUser
{
    use Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'sub', 'name', 'email'
    ];

    /**
     * Get the value of the model's primary key.
     *
     * @return mixed
     */
    public function getKey()
    {
        return $this->attributes['sub'];
    }
}

next steps:

mariovalney commented 4 years ago

Nice tutorial. Thanks.

nicosalvadore commented 3 years ago

@gpedro I'm trying to configure Eloquent relationships to other models in my app. But get an error saying the relationship methods are not defined, for example : Call to undefined method App\Models\User::belongsTo()

The User model is correctly extending KeycloakUser as mentionned in your guide. Do you have an idea what could cause this ? Thanks

nicosalvadore commented 3 years ago

I'm asking because your original description on this issue was to link the User model with a Task model, but there is no relationship to the Task model in your code.

Thanks again !

edit : I skipped your next steps while reading your post. Your solution thus needs to sync the info in the local db ? And it's on the local DB that we would do our Eloquent relationships and queries ? @gpedro

sorry for spamming this closed issue :(

nomaniqbal0 commented 1 year ago

@mariovalney , @gpedro ,

I have followed your mentioned steps 1) code changes 2) sync users table still getting the error . eloquent function of user model is not working. Call to undefined method App\Models\User::hasMany() or Call to undefined method App\Models\User::create()

Thanks

nomaniq commented 1 year ago

*

I'm asking because your original description on this issue was to link the User model with a Task model, but there is no relationship to the Task model in your code.

Thanks again !

edit : I skipped your next steps while reading your post. Your solution thus needs to sync the info in the local db ? And it's on the local DB that we would do our Eloquent relationships and queries ? @gpedro

sorry for spamming this closed issue :(

Hi,

i am facing the same issue. i have implemented as mentioned . i have sync the database as well. i am using keycloak with laravel cashier.

auth.php

'defaults' => [ 'guard' => 'web', 'passwords' => 'users', ],

'guards' => [

   'web' => [
        'driver' => 'keycloak-web',
        'provider' => 'users',
    ],

    'admin' => [
        'driver' => 'session',
        'provider' => 'admins',
    ],
],

'providers' => [

    'users' => [
        'driver' => 'keycloak-users',
        'model' => App\Models\User::class,
    ],

    'admins' => [
        'driver' => 'eloquent',
        'model' => App\Models\Admin::class,
    ],

],

User.php model file

namespace App\Models;

use Illuminate\Contracts\Auth\MustVerifyEmail; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; use Laravel\Sanctum\HasApiTokens; use Vizir\KeycloakWebGuard\Models\KeycloakUser; use Laravel\Cashier\Billable; use App\Models\Subscription;

class User extends KeycloakUser { use HasApiTokens, HasFactory, Notifiable, Billable;

/**
 * The attributes that are mass assignable.
 *
 * @var array
 */
protected $primaryKey = 'user_id';

protected $fillable = [
    'sub', 'name', 'email'
];

/**
 * Get the value of the model's primary key.
 *
 * @return mixed
 */
public function getKey()
{
    return $this->attributes['sub'];
}

}

when i am calling User::create or User::update , no eloquent function is working. Please help

mariovalney commented 1 year ago

KeycloakUser only means to encapsulate data from Keycloak: it's not a Eloquent model.

You can check, Laravel's User extends lluminate\Foundation\Auth\User as Authenticatable which extends a Eloquent Model.

You have two options:

  1. Implement these methods.
  2. Use a regular Laravel user and implement in your own UserProvider the retrieveByCredentials method to get the User from Database and add Profile data from Keycloak.

In both cases you should be aware that Eloquent Users must persist on Keycloak if you create it outside Keycloak.