Adldap2 / Adldap2-Laravel

LDAP Authentication & Management for Laravel
MIT License
911 stars 183 forks source link

These credentials do not match our records #509

Closed treadmillian closed 5 years ago

treadmillian commented 6 years ago

Description:

As others have reported, I receive the error These credentials do not match our records. However, the system does definitely connect to the AD server and the following returns true:

<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;

class LoginController extends Controller
{
    use AuthenticatesUsers;

    /**
     * Where to redirect users after login.
     *
     * @var string
     */
    protected $redirectTo = '/home';

    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $user = \Adldap::auth()->attempt('STC\KS27', 'removed');
        var_dump($user);
        die();

        $this->middleware('guest')->except('logout');
    }

    /**
     * @return string
     */
    public function username()
    {
        return 'username';
    }
}

Steps To Reproduce:

What do remember after tracking the issue as far as I could go, is that $this->query() always returned null. I tried manually sending lots of different combinations of; field and username to whereEquals(), but all returned null.

vendor/adldap2/adldap2-laravel/src/Auth/Resolver.php

    /**
     * {@inheritdoc}
     */
    public function byCredentials(array $credentials = [])
    {
        if (empty($credentials)) {
            return;
        }

        return $this->query()
            ->whereEquals($this->getLdapUsername(), $credentials[$this->getEloquentUsername()])
            ->first();
    }

.env

APP_NAME="APP"
APP_ENV=develop
APP_KEY=base64:ZLxOVCxr/rbEzhOOXoEu4Zzq7WpJHk5NFfPVLHG1lVo=
APP_DEBUG=true
APP_LOG_LEVEL=debug
APP_URL=http://localhost

DB_CONNECTION=mysql
DB_HOST=hostname
DB_PORT=3306
DB_DATABASE=foobar
DB_USERNAME=username
DB_PASSWORD=password
DB_CHARSET=utf8
DB_COLLATION=utf8_bin

ADLDAP_USERNAMES_LDAP=samaccountname
ADLDAP_ADMIN_USERNAME=username
ADLDAP_ADMIN_PASSWORD=password
ADLDAP_CONTROLLERS=foobar.com
ADLDAP_PORT=636
ADLDAP_TIMEOUT=30
ADLDAP_USE_SSL=true
ADLDAP_USE_TLS=false
ADLDAP_BASEDN=

BROADCAST_DRIVER=log
CACHE_DRIVER=file
SESSION_DRIVER=file
QUEUE_DRIVER=sync

MAIL_DRIVER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null

PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=

adldap_auth.php

<?php

return [
    'connection' => env('ADLDAP_CONNECTION', 'default'),
    'provider' => Adldap\Laravel\Auth\DatabaseUserProvider::class,
    'resolver' => Adldap\Laravel\Auth\Resolver::class,
    'importer' => Adldap\Laravel\Auth\Importer::class,
    'rules' => [
        Adldap\Laravel\Validation\Rules\DenyTrashed::class,
    ],
    'scopes' => [
        Adldap\Laravel\Scopes\UpnScope::class,
    ],
    'usernames' => [
        'ldap' => env('ADLDAP_USERNAMES_LDAP', ''),
        'eloquent' => 'username',
    ],
    'login_fallback' => env('ADLDAP_LOGIN_FALLBACK', false),
    'password_sync' => env('ADLDAP_PASSWORD_SYNC', true),
    'windows_auth_attribute' => ['samaccountname' => 'AUTH_USER'],
    'sync_attributes' => [
        'username' => 'uid', //'userprincipalname',
        'name' => 'cn',
    ],
];

adldap.php

<?php

return [
    'connections' => [
        'default' => [
            'auto_connect' => true,
            'connection' => Adldap\Connections\Ldap::class,
            'schema' => Adldap\Schemas\ActiveDirectory::class,
            'connection_settings' => [
                'account_prefix' => env('ADLDAP_ACCOUNT_PREFIX', ''),
                'account_suffix' => env('ADLDAP_ACCOUNT_SUFFIX', ''),
                'domain_controllers' => explode(' ', env('ADLDAP_CONTROLLERS', '')),
                'port' => env('ADLDAP_PORT', 389),
                'timeout' => env('ADLDAP_TIMEOUT', 5),
                'base_dn' => env('ADLDAP_BASEDN', ''),
                'admin_account_suffix' => env('ADLDAP_ADMIN_ACCOUNT_SUFFIX', ''),
                'admin_username' => env('ADLDAP_ADMIN_USERNAME', ''),
                'admin_password' => env('ADLDAP_ADMIN_PASSWORD', ''),
                'follow_referrals' => false,
                'use_ssl' => env('ADLDAP_USE_SSL', false),
                'use_tls' => env('ADLDAP_USE_TLS', false),
            ],
        ],
    ],
];

auth.php

<?php

return [
    'defaults' => [
        'guard' => 'web',
        'passwords' => 'users',
    ],
    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],

        'api' => [
            'driver' => 'token',
            'provider' => 'users',
        ],
    ],
    'providers' => [
        'users' => [
            'driver' => 'adldap',
            'model' => App\User::class,
        ],
    ],
    'passwords' => [
        'users' => [
            'provider' => 'users',
            'table' => 'password_resets',
            'expire' => 60,
        ],
    ],
];

app.php

<?php

return [
    'name' => env('APP_NAME', 'Laravel'),
    'env' => env('APP_ENV', 'production'),
    'debug' => env('APP_DEBUG', false),
    'url' => env('APP_URL', 'http://localhost'),
    'timezone' => 'UTC',
    'locale' => 'en',
    'fallback_locale' => 'en',
    'key' => env('APP_KEY'),
    'cipher' => 'AES-256-CBC',
    'log' => env('APP_LOG', 'single'),
    'log_level' => env('APP_LOG_LEVEL', 'debug'),
    'providers' => [
        /*
         * Laravel Framework Service Providers...
         */
        Illuminate\Auth\AuthServiceProvider::class,
        Illuminate\Broadcasting\BroadcastServiceProvider::class,
        Illuminate\Bus\BusServiceProvider::class,
        Illuminate\Cache\CacheServiceProvider::class,
        Illuminate\Foundation\Providers\ConsoleSupportServiceProvider::class,
        Illuminate\Cookie\CookieServiceProvider::class,
        Illuminate\Database\DatabaseServiceProvider::class,
        Illuminate\Encryption\EncryptionServiceProvider::class,
        Illuminate\Filesystem\FilesystemServiceProvider::class,
        Illuminate\Foundation\Providers\FoundationServiceProvider::class,
        Illuminate\Hashing\HashServiceProvider::class,
        Illuminate\Mail\MailServiceProvider::class,
        Illuminate\Notifications\NotificationServiceProvider::class,
        Illuminate\Pagination\PaginationServiceProvider::class,
        Illuminate\Pipeline\PipelineServiceProvider::class,
        Illuminate\Queue\QueueServiceProvider::class,
        Illuminate\Redis\RedisServiceProvider::class,
        Illuminate\Auth\Passwords\PasswordResetServiceProvider::class,
        Illuminate\Session\SessionServiceProvider::class,
        Illuminate\Translation\TranslationServiceProvider::class,
        Illuminate\Validation\ValidationServiceProvider::class,
        Illuminate\View\ViewServiceProvider::class,

        /*
         * Package Service Providers...
         */
        Laravel\Tinker\TinkerServiceProvider::class,

        /*
         * Application Service Providers...
         */
        App\Providers\AppServiceProvider::class,
        App\Providers\AuthServiceProvider::class,
        // App\Providers\BroadcastServiceProvider::class,
        App\Providers\EventServiceProvider::class,
        App\Providers\RouteServiceProvider::class,
        Adldap\Laravel\AdldapServiceProvider::class,
        Adldap\Laravel\AdldapAuthServiceProvider::class,
    ],
    'aliases' => [
        'App' => Illuminate\Support\Facades\App::class,
        'Artisan' => Illuminate\Support\Facades\Artisan::class,
        'Auth' => Illuminate\Support\Facades\Auth::class,
        'Blade' => Illuminate\Support\Facades\Blade::class,
        'Broadcast' => Illuminate\Support\Facades\Broadcast::class,
        'Bus' => Illuminate\Support\Facades\Bus::class,
        'Cache' => Illuminate\Support\Facades\Cache::class,
        'Config' => Illuminate\Support\Facades\Config::class,
        'Cookie' => Illuminate\Support\Facades\Cookie::class,
        'Crypt' => Illuminate\Support\Facades\Crypt::class,
        'DB' => Illuminate\Support\Facades\DB::class,
        'Eloquent' => Illuminate\Database\Eloquent\Model::class,
        'Event' => Illuminate\Support\Facades\Event::class,
        'File' => Illuminate\Support\Facades\File::class,
        'Gate' => Illuminate\Support\Facades\Gate::class,
        'Hash' => Illuminate\Support\Facades\Hash::class,
        'Lang' => Illuminate\Support\Facades\Lang::class,
        'Log' => Illuminate\Support\Facades\Log::class,
        'Mail' => Illuminate\Support\Facades\Mail::class,
        'Notification' => Illuminate\Support\Facades\Notification::class,
        'Password' => Illuminate\Support\Facades\Password::class,
        'Queue' => Illuminate\Support\Facades\Queue::class,
        'Redirect' => Illuminate\Support\Facades\Redirect::class,
        'Redis' => Illuminate\Support\Facades\Redis::class,
        'Request' => Illuminate\Support\Facades\Request::class,
        'Response' => Illuminate\Support\Facades\Response::class,
        'Route' => Illuminate\Support\Facades\Route::class,
        'Schema' => Illuminate\Support\Facades\Schema::class,
        'Session' => Illuminate\Support\Facades\Session::class,
        'Storage' => Illuminate\Support\Facades\Storage::class,
        'URL' => Illuminate\Support\Facades\URL::class,
        'Validator' => Illuminate\Support\Facades\Validator::class,
        'View' => Illuminate\Support\Facades\View::class,
        'Adldap' => Adldap\Laravel\Facades\Adldap::class,
    ],
];
stevebauman commented 6 years ago

Hi @treadmillian,

Is your base_dn missing on purpose or no? This is crucial for locating records on your LDAP server.

If nothing is given, you won't receive any search results.

treadmillian commented 6 years ago

Good point, I found one of our Symfony3 projects that implements LDAP and this works fine. So I've now added, however, it's still not working. I noted from my Symfony3 config that it uses:

accountCanonicalForm: 3 # ACCTNAME_FORM_BACKSLASH this is only needed if your users have to login with something like HOST\User
filter: (&(ObjectClass=Person))
usernameAttribute: sAMAccountName # Optional

Can these be set in Adldap? I tried using combinations of these:

ADLDAP_ADMIN_ACCOUNT_SUFFIX=stc
ADLDAP_ACCOUNT_SUFFIX=stc
ADLDAP_ACCOUNT_PREFIX=stc

...but always get errors like;

(1/1) BindExceptionInvalid credentials
--
in Guard.php (line 80)
at Guard->bind('username', 'removed', '', 'stc')in Guard.php (line 94)

Full config file:

fr3d_ldap:
    driver:
        host: "%ldap_host%"
        port: "%ldap_port%"
        username: "%ldap_username%"
        password: "%ldap_password%"
        allowEmptyPassword: false  # Optional
        #bindRequiresDn: true   # Optional
        baseDn: removed
        #accountFilterFormat: (&(sAMAccountName=%s)) # Optional. sprintf format %s will be the username
        #optReferrals: false  # Optional
        useSsl: true   # Enable SSL negotiation. Optional
        #useStartTls: true   # Enable TLS negotiation. Optional
        accountCanonicalForm: 3 # ACCTNAME_FORM_BACKSLASH this is only needed if your users have to login with something like HOST\User
        accountDomainNameShort: stc # if you use the Backslash form set both to Hostname than the Username will be converted to HOST\User
    user:
        baseDn: removed
        filter: (&(ObjectClass=Person))
        usernameAttribute: sAMAccountName # Optional
        attributes:          # Specify ldap attributes mapping [ldap attribute, user object method]
            - { ldap_attr: samaccountname, user_method: setUsername }
            - { ldap_attr: givenname, user_method: setFirstName }
            - { ldap_attr: sn, user_method: setLastName }
            - { ldap_attr: mail, user_method: setEmailAddress }
    service:
        user_hydrator: model.user.ldap.hydrator
treadmillian commented 6 years ago

One thing I did noticed, my login is STC\KS27. However, if I try and login as KS27, I get this error:

(1/1) UsernameRequiredExceptionA username must be specified.
--
in Guard.php (line 110)
at Guard->validateCredentials(null, 'removed')in Guard.php (line 34)
at Guard->attempt(null, 'removed')in Resolver.php (line 67)
at Resolver->authenticate(object(User), array('username' => 'KS27', 'password' => 'removed'))in DatabaseUserProvider.php (line 131)
at DatabaseUserProvider->validateCredentials(object(User), array('username' => 'KS27', 'password' => 'removed'))in SessionGuard.php (line 380)
at SessionGuard->hasValidCredentials(object(User), array('username' => 'KS27', 'password' => 'removed'))in SessionGuard.php (line 357)
at SessionGuard->attempt(array('username' => 'KS27', 'password' => 'removed'), false)in AuthenticatesUsers.php (line 77)
at LoginController->attemptLogin(object(Request))in AuthenticatesUsers.php (line 41)
treadmillian commented 6 years ago

@stevebauman Is this something you can help with?

stevebauman commented 6 years ago

Hi @treadmillian,

Is this something you can help with?

Of course, I'm absolutely here to help. We'll get you up and running.

Are you possibly able to upgrade to the newest v4.0 version? There are only configuration changes, but these changes may greatly reduce the time needed for debugging.

If you can upgrade, you will need to delete and re-publish the adldap_auth.php configuration file.

Please let me know, thanks!

treadmillian commented 6 years ago

Hi @stevebauman

Unfortunately, that isn't an option for us at the moment, i.e. upgrading to PHP7.x

But more than willing to persevere to resolve the issue :)

warlord0 commented 6 years ago

Have you tried the prefix as stc\ or stc\\ (double slash for escaping the first, might need "quotes" in .env)? Could you use the userprincipalname to logon with so you could have a suffix of @domain.local? If your upn consists of the samaccount that is.

stevebauman commented 5 years ago

Closing due to inactivity.