DirectoryTree / LdapRecord-Laravel

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

[Support] - auth is searching guid on users.id instead of users.custom_guid for some reason #595

Closed HawtDogFlvrWtr closed 1 year ago

HawtDogFlvrWtr commented 1 year ago

Environment:

SQLSTATE[22P02]: Invalid text representation: 7 ERROR: invalid input syntax for type bigint: "410d48e5-989c-4097-b8f4-ec263aaeca02"
SELECT * FROM "users" WHERE "id" = 410d48e5-989c-4097-b8f4-ec263aaeca02 limit 1

Model/User.php

<?php

namespace App\Models;

// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
use LdapRecord\Laravel\Auth\AuthenticatesWithLdap;
use LdapRecord\Laravel\Auth\LdapAuthenticatable;

class User extends Authenticatable implements LdapAuthenticatable
{
    use HasApiTokens, HasFactory, Notifiable, AuthenticatesWithLdap;

    public function getLdapDomainColumn(): String
    {
        return 'ldap_domain';
    }

    public function getLdapGuidColumn(): String
    {
        return 'ldap_guid';
    }
}

LogonRequest.php

<?php

namespace App\Http\Requests\Auth;

use Illuminate\Auth\Events\Lockout;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\Str;
use Illuminate\Validation\ValidationException;

class LoginRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     */
    public function authorize(): bool
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array<string, \Illuminate\Contracts\Validation\Rule|array|string>
     */
    public function rules(): array
    {
        return [
            'username' => 'required|string',
            'password' => 'required|string',
        ];
    }

    /**
     * Attempt to authenticate the request's credentials.
     *
     * @throws \Illuminate\Validation\ValidationException
     */
    public function authenticate()
    {
        $this->ensureIsNotRateLimited();

        $credentials = [
            'samaccountname' => $this->username,
            'password' => $this->password,
        ];

        if (! Auth::attempt($credentials, $this->filled('remember'))) {
            RateLimiter::hit($this->throttleKey());

            throw ValidationException::withMessages([
                'username' => __('auth.failed'),
            ]);
        }

        RateLimiter::clear($this->throttleKey());
    }

    /**
     * Ensure the login request is not rate limited.
     *
     * @throws \Illuminate\Validation\ValidationException
     */
    public function ensureIsNotRateLimited(): void
    {
        if (! RateLimiter::tooManyAttempts($this->throttleKey(), 5)) {
            return;
        }

        event(new Lockout($this));

        $seconds = RateLimiter::availableIn($this->throttleKey());

        throw ValidationException::withMessages([
            'username' => trans('auth.throttle', [
                'seconds' => $seconds,
                'minutes' => ceil($seconds / 60),
            ]),
        ]);
    }

    /**
     * Get the rate limiting throttle key for the request.
     */
    public function throttleKey(): string
    {
        return Str::transliterate(Str::lower($this->input('username')).'|'.$this->ip());
    }
}

Provider in Auth.php

    'providers' => [
        'users' => [
            'driver' => 'ldap',
            'model' => LdapRecord\Models\ActiveDirectory\User::class,
            'rules' => [],
            'scopes' => [],
            'database' => [
                'model' => App\Models\User::class,
                'sync_passwords' => false,
                'password_column' => false,
                'sync_attributes' => [
                    'fullname' => 'cn',
                    'username' => 'samaccountname',
                ],
                'sync_existing' => [
                    'fullname' => 'cn',
                    'username' => [
                        'attribute' => 'samaccountname',
                        'operator' => 'ilike',
                    ]
                ],
            ],
        ],
    ],
HawtDogFlvrWtr commented 1 year ago

I should also mention that import works a treat against the 180 users in active directory, so it knows my custom guild and domain columns.

HawtDogFlvrWtr commented 1 year ago

Never mind. I ran through the install for Plain Auth before DB Auth, and it had a leftover session file that it was using, where the id was the guid. I had to manually remove the session file and refresh. I'm going to look through the documentation and find a good place to submit a change to document this in red bold, ROFL

stevebauman commented 1 year ago

Just got to this, thanks for posting your solution here @HawtDogFlvrWtr! I'm glad you were able to resolve it šŸ™