DirectoryTree / LdapRecord-Laravel

Multi-domain LDAP Authentication & Management for Laravel.
https://ldaprecord.com/docs/laravel/v3
MIT License
483 stars 51 forks source link

[Support] Upgrade Problems. #651

Closed stephenucr closed 2 months ago

stephenucr commented 2 months ago

Environment:

Currently getting this error: Type of App\Ldap\User::$objectClasses must be array (as in class LdapRecord\Models\Model)

Context :

We were using v1 on Laravel with PHP 7.4 .. I rebuilt a new server, with PHP 8.2, Laravel 11, and LdapRecord 3.0. Did all my configurations, and then tested, worked perfect on the cli : php artisan ldap:test BULLY!

The login process is working as well, as far as I can tell.. However .. once it redirects to the post login landing page. I am getting the above error.

I have seen in the docs that the app/Ldap/User.php is no longer there, and should be in the app/User.php location.. However, I use the app/User.php for my own stuff.

I feel like I have hit a wall on what I am trying to do, which may not be the best way to manage my situation.

I would appreciate some guidance.

stephenucr commented 2 months ago

Additional Info:
Relevant files:

app/ Ldap/ User.php

 <?php
namespace App\Ldap;

use LdapRecord\Models\Model;
class User extends Model
{
    /**
     * The object classes of the LDAP model.
     *
     * @var array
     */

    public static $objectClasses = [
        'top',
        'person',
        'organizationalperson',
        'user',
    ];
}
stephenucr commented 2 months ago
app/User.php 

<?php

namespace App;
use Auth;

use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Facades\DB;

use LdapRecord\Laravel\Auth\AuthenticatesWithLdap;
use LdapRecord\Laravel\Auth\LdapAuthenticatable;
use LdapRecord\Laravel\Auth\HasLdapUser;

class User extends Authenticatable implements LdapAuthenticatable
{
    use Notifiable, AuthenticatesWithLdap;
    use HasLdapUser;
    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $table = 'user_login';

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

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token',
    ];

    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
    ];

    public function user_roles() { 

        $user_id = Auth::user()->id;

        $roles_list_db = DB::connection('doav3')->table('user_roles as ur')
                                                        ->join('roles as r', 'r.id', '=', 'ur.role_id')
                                                        ->where('user_id', '=', $user_id)
                                                        ->get(); 

        $roles_list = array();

        foreach( $roles_list_db as $rl ) { 

            $roles_list[] = $rl->name; 

        }

        return $roles_list; 

    }       
    public function isAdmin()
    {
        $user_roles = $this->user_roles(); 

        if(in_array('DOA-ADMIN', $user_roles)) { 
           return true; 
        } else { 
            return false; 
        }

    }
    public function hasAccess($access)
    {
        $user_roles = $this->user_roles(); 

        if($access != 'DOA-DEV'){ 
            if(in_array($access, $user_roles) || in_array('DOA-ADMIN', $user_roles)) { 
               return true; 
            } else { 
                return false; 
            }
        } else { 
            if(in_array($access, $user_roles)) { 
               return true; 
            } else { 
                return false; 
            }
        }
    }

}
stevebauman commented 2 months ago

Hi @stephenucr!

With the upgrade to LdapRecord v3, strict PHP types are implemented across all classes, so you'll have to update your app/Ldap/User model to be:

 <?php
namespace App\Ldap;

use LdapRecord\Models\Model;
class User extends Model
{
    /**
     * The object classes of the LDAP model.
     *
     * @var array
     */
-    public static $objectClasses = [
+    public static array $objectClasses = [
        'top',
        'person',
        'organizationalperson',
        'user',
    ];
}

That should resolve the exception you're seeing. Let me know! πŸ‘

stephenucr commented 2 months ago

That did resolve it .. thanks!

However, it leads me to my next question .. The User class is attempting to access the db rather than the Ldap server .. so I get column missing errors.

` $user_info = User::where('cn', '=', $name)->get();

`

SQLSTATE[42703]: Undefined column: 7 ERROR: column "cn" does not exist LINE 1: select * from "user_login" where "cn" = $1 ^

My auth.php provider reference.

` /* -------------------------------------------------------------------------- User Providers
All authentication drivers have a user provider. This defines how the
users are actually retrieved out of your database or other storage
mechanisms used by this application to persist your user's data.
If you have multiple user tables or models you may configure multiple
sources which represent each model / table. These sources may then
be assigned to any extra authentication guards you have defined.
Supported: "database", "eloquent"
*/

'providers' => [
    'users' => [
        'driver' => 'eloquent',
        'model' => App\User::class,
    ],
    'ldap' => [
        'driver' => 'ldap',
        'model' => LdapRecord\Models\ActiveDirectory\User::class,
        'rules' => [],
        'database' => [
            'model' => App\User::class,
            'password_column' => false,
            'sync_passwords' => false,
            'sync_attributes' => [
                'name' => 'cn',
                'username' => 'samaccountname',
                'email' => 'mail',
            ],
        ],
    ],
    // 'users' => [
    //     'driver' => 'database',
    //     'table' => 'users',
    // ],
],

`

stevebauman commented 2 months ago

No problem!

Are you accessing the appropriate LdapRecord model with the code you've shown here:

$user_info = User::where('cn', '=', $name)->get();

In your case, the imported User class at the top of the file should be either:

use App\Ldap\User;

Or:

use LdapRecord\Models\ActiveDirectory\User;

Can you double check?


I also noticed you're using two different User LdapRecord models (shown above). Is this intended? Typically only one is necessary across the application.

Since you're using Active Directory, the LdapRecord\Models\ActiveDirectory\User class should be sufficient -- and if you need to add additional functionality to this class, you may extend it with your own:

namespace App\Ldap;

use LdapRecord\Models\ActiveDirectory\User as BaseUser;

class User extends BaseUser
{
    // ...
}
stephenucr commented 2 months ago

Some of this code is several years old, and not all written by me.

We started out using Adldap libraries, and eventually that moved into v1 of LdapRecord .. so a lot of this code may not be workable with the newer version ?

Our app/User.php extends Illuminate\Foundation\Auth\User as Authenticable.

If I try and add the App\Ldap\User class to this, it will obviously error out.

I replaced the Foundation class with the Ldap class, and I get some more errors that I think are related to the strict requirements.

stevebauman commented 2 months ago

Ok cool understood. You'll definitely have to make some small adjustments due to the shift from Adldap2 to LdapRecord, then the major upgrades to v3.

Would you like to hop on a call and I can take a look with you?

stephenucr commented 2 months ago

That would be great .. if you don't mind.

stevebauman commented 2 months ago

Cool sounds good! Not at all πŸ™ . Here's a Google Meet link:

https://meet.google.com/xki-wsvi-tvf

stevebauman commented 2 months ago

Was great meeting and talking to you @stephenucr! πŸ‘Š

Feel free to drop by anytime you have issues! πŸ™