Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

SunnyBoy's avatar

Adldap2-Laravel with Windows Active Directory

Hi Laravel Gurus,

I'm new to LDAP and for a project, the requirement is to use username instead of email for authentication. For username authentication i need to connect to the company's active directory.

I tried this https://github.com/jotaelesalinas/laravel-simple-ldap-auth which works perfectly as the way it should with OpenLDAP, but when i am trying the same with the company's Active Directory using my credentials it throws error "Invalid Credentials". There is no issue with the credentials, I'm able to connect using AD Explorer (LDAP Browser).

Does anyone know what needs to be configured differently? Do I need to change something to connect to Active Directory? Is it something to do with the structure of the directory?

PLEASE HELP!!!

Thanks

0 likes
23 replies
Sinnbeck's avatar

Be aware that you need so setup an account that can be used for lookups. It should be in the config. If it still does not work, I can post my settings that works with AD

1 like
SunnyBoy's avatar

@sinnbeck: thanks for the heads-up but as i mentioned I am new to LDAP, how would that look like in config.ldap? Regarding the account for lookup i think it is all set by the admin as it is being used in other projects in the company.

I would really appreciate if you can share some your AD settings!

Thanks

1 like
Sinnbeck's avatar

Here is what I changed in ldap.php

'hosts' => explode(' ', env('LDAP_HOSTS', '192.168.1.75')), //The ip for the AD server

'base_dn' => env('LDAP_BASE_DN', 'dc=mycompany,dc=lan'), //you should be able to find this on one of the account on the AD server

'username' => env('LDAP_ADMIN_USERNAME'),
'password' => env('LDAP_ADMIN_PASSWORD'), //These 2 are set in the .env file. I made a new ad service account just for this :) Username is the fully quallified adrees (eg. [email protected])

And ldap_auth.php

'provider' => Adldap\Laravel\Auth\NoDatabaseUserProvider::class, //I prefer that users log in using the AD server each time


'ldap' => [

            'locate_users_by' => 'samaccountname', //Changed to samaccountname which means users can login using their username. Use the one that works for you :) https://www.faqforge.com/windows/samaccountname-vs-userprincipalname/

            'bind_users_by' => 'distinguishedname',

        ],

Oh and I changed this in my LoginController.php

public function username()
    {
        return 'samaccountname';
    }
1 like
SunnyBoy's avatar

Thanks for the response, last night I tried the solution but it din't work need to check with the active directory admin regarding the permissions. Will update as soon I get the confirmation on the account, but ya so far no luck. I tried you solution but it seems I am still missing something.

1 like
Sinnbeck's avatar

Yeah just be sure that the user can query and run operations (domain admin is not needed)

SunnyBoy's avatar

@sinnbeck I tried all possible ways but no luck! Can you share your LoginController please? Thanks

Sinnbeck's avatar

Naturally :)

<?php

namespace App\Http\Controllers\Auth;

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

class LoginController extends Controller
{
    /*
    |--------------------------------------------------------------------------
    | Login Controller
    |--------------------------------------------------------------------------
    |
    | This controller handles authenticating users for the application and
    | redirecting them to your home screen. The controller uses a trait
    | to conveniently provide its functionality to your applications.
    |
    */

    use AuthenticatesUsers;

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

    /**
     * Create a new controller instance.
     * @return void
     */
    public function __construct()
    {
        $this->middleware('guest')->except('logout');
    }

    public function username()
    {
        return 'samaccountname';
    }

    /**
     * Send the response after the user was authenticated.
     *
     * @param \Illuminate\Http\Request $request
     *
     * @return \Illuminate\Http\Response
     */
    protected function sendLoginResponse(Request $request)
    {
        $request->session()->regenerate();

        $this->clearLoginAttempts($request);

        $user = $this->guard()->user();

        if ($this->authenticated($request, $user)) {
            return response()->json([
                'success'  => true,
                'username' => $user->getAccountName(),
                'name'     => $user->getName(),
                'email'    => $user->getEmail(),
            ], 200);
        }
    }

    /**
     * The user has been authenticated.
     *
     * @param \Illuminate\Http\Request $request
     * @param mixed                    $user
     *
     * @return mixed
     */
    protected function authenticated(Request $request, $user)
    {
        return true;
    }
}
1 like
Sinnbeck's avatar

When I set ours up I had a really hard time getting it working as well. My solution was getting a working admin account set up, removing account_prefix and account_suffix (settitng them to '') as I am using samaccountname :)

How is you scope setup? I just use this Adldap\Laravel\Scopes\UpnScope::class,

SunnyBoy's avatar
SunnyBoy
OP
Best Answer
Level 5

@sinnbeck Here is my working code setup what I have, I tried all I could:

.env (ldap variables)

LDAP_HOSTS=xxx.xxx.xx.xx // to be replaced
LDAP_BASE_DN="DC=example,DC=com" // to be replaced
LDAP_USER_ATTRIBUTE=samaccountname 
LDAP_USER_FORMAT=%[email protected] // to be replaced
LDAP_CONNECTION=default

LDAP_USERNAME=username // to be replaced with admin or user with lookup permission
LDAP_PASSWORD=password

config\auth.php

...

    'providers' => [
        'users' => [
            'driver' => 'ldap', // was 'eloquent'
            'model' => App\User::class,
        ],
    ],

...

ldap.php // don't have change anything

<?php

return [

    'logging' => env('LDAP_LOGGING', false),

    'connections' => [

        'default' => [
            'auto_connect' => env('LDAP_AUTO_CONNECT', false),
            'connection' => Adldap\Connections\Ldap::class,
            'settings' => [
    
                'schema' => Adldap\Schemas\ActiveDirectory::class,
                'account_prefix' => env('LDAP_ACCOUNT_PREFIX', ''),
                'account_suffix' => env('LDAP_ACCOUNT_SUFFIX', ''),
                'hosts' => explode(' ', env('LDAP_HOSTS', 'corp-dc1.corp.acme.org corp-dc2.corp.acme.org')),
                'port' => env('LDAP_PORT', 389),
                'timeout' => env('LDAP_TIMEOUT', 5),
                'base_dn' => env('LDAP_BASE_DN', 'ou=corp,dc=acme,dc=org'),
                'username' => env('LDAP_USERNAME', ''),
                'password' => env('LDAP_PASSWORD', ''),
                'follow_referrals' => env('LDAP_FOLLOW_REFERRALS', false),
                'use_ssl' => env('LDAP_USE_SSL', false),
                'use_tls' => env('LDAP_USE_TLS', false),
            ],
        ],
    
    ],

];

ldap_auth.php

<?php

return [

    'connection' => env('LDAP_CONNECTION', 'default'),

// Yes, I am using DatabaseUserProvider cause my users table has items related to

    'provider' => Adldap\Laravel\Auth\DatabaseUserProvider::class,

    'model' => App\User::class,

    'rules' => [

        Adldap\Laravel\Validation\Rules\DenyTrashed::class,

    ],

    'scopes' => [

    ],

    'identifiers' => [

        'ldap' => [

            'locate_users_by' => 'sAMAccountName',

            'bind_users_by' => 'distinguishedname',

        ],

        'database' => [

            'guid_column' => 'objectguid',

            'username_column' => 'username',

        ],

        'windows' => [

            'locate_users_by' => 'sAMAccountName',

            'server_key' => 'AUTH_USER',

        ],

    ],

    'passwords' => [

        'sync' => env('LDAP_PASSWORD_SYNC', false),

        'column' => 'password',

    ],

    'login_fallback' => env('LDAP_LOGIN_FALLBACK', false),

    'sync_attributes' => [

        'name' => 'cn',
        
        'email' => 'userPrincipalName',
        
        'username' => 'sAMAccountName',
    ],

    'logging' => [

        'enabled' => env('LDAP_LOGGING', true),

        'events' => [

            \Adldap\Laravel\Events\Importing::class => \Adldap\Laravel\Listeners\LogImport::class,
            \Adldap\Laravel\Events\Synchronized::class => \Adldap\Laravel\Listeners\LogSynchronized::class,
            \Adldap\Laravel\Events\Synchronizing::class => \Adldap\Laravel\Listeners\LogSynchronizing::class,
            \Adldap\Laravel\Events\Authenticated::class => \Adldap\Laravel\Listeners\LogAuthenticated::class,
            \Adldap\Laravel\Events\Authenticating::class => \Adldap\Laravel\Listeners\LogAuthentication::class,
            \Adldap\Laravel\Events\AuthenticationFailed::class => \Adldap\Laravel\Listeners\LogAuthenticationFailure::class,
            \Adldap\Laravel\Events\AuthenticationRejected::class => \Adldap\Laravel\Listeners\LogAuthenticationRejection::class,
            \Adldap\Laravel\Events\AuthenticationSuccessful::class => \Adldap\Laravel\Listeners\LogAuthenticationSuccess::class,
            \Adldap\Laravel\Events\DiscoveredWithCredentials::class => \Adldap\Laravel\Listeners\LogDiscovery::class,
            \Adldap\Laravel\Events\AuthenticatedWithWindows::class => \Adldap\Laravel\Listeners\LogWindowsAuth::class,
            \Adldap\Laravel\Events\AuthenticatedModelTrashed::class => \Adldap\Laravel\Listeners\LogTrashedModel::class,

        ],
    ],

];

Auth\LoginController.php

<?php

namespace App\Http\Controllers\Auth;

use Illuminate\Http\Request;
use Adldap\Laravel\Facades\Adldap;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;

class LoginController extends Controller
{
    use AuthenticatesUsers;

    protected $redirectTo = '/home';

    public function __construct()
    {
        $this->middleware('guest')->except('logout');
    }

    public function username()
    {
        return 'username';
    }

    protected function validateLogin(Request $request)
    {
        $this->validate($request, [
            $this->username() => 'required|string|regex:/^[A-Za-z]+\.[A-Za-z]+$/',
            'password' => 'required|string',
        ]);
    }

    protected function attemptLogin(Request $request)
    {
        
        $credentials = $request->only($this->username(), 'password');
        $username = $credentials[$this->username()];
        $password = $credentials['password'];

        $user_format = env('LDAP_USER_FORMAT');
        $userdn = sprintf($user_format, $username);
        
        if (Adldap::auth()->attempt($userdn, $password, $bindAsUser = true)) {

            $user = \App\User::where($this->username(), $username)->first();
            
            if (!$user) {
                
                $user = new \App\User();
                $user->username = $username;
                $user->password = '';

                $sync_attrs = $this->retrieveSyncAttributes($username);
                foreach ($sync_attrs as $field => $value) {
                    $user->$field = $value !== null ? $value : '';
                }
            }

            $this->guard()->login($user, true);
            return true;
        }
        // the user doesn't exist in the LDAP server or the password is wrong
        // log error
        return false;
    }

    protected function retrieveSyncAttributes($username)
    {
        $ldapuser = Adldap::search()->where(env('LDAP_USER_ATTRIBUTE'), '=', $username)->first();
        if (!$ldapuser) {
            // log error
            return false;
        }
        
        $ldapuser_attrs = null;

        $attrs = [];

        foreach (config('ldap_auth.sync_attributes') as $local_attr => $ldap_attr) {
            if ($local_attr == 'username') {
                continue;
            }

            $method = 'get' . $ldap_attr;
            if (method_exists($ldapuser, $method)) {
                $attrs[$local_attr] = $ldapuser->$method();
                continue;
            }

            if ($ldapuser_attrs === null) {
                $ldapuser_attrs = self::accessProtected($ldapuser, 'attributes');
            }

            if (!isset($ldapuser_attrs[$ldap_attr])) {
                // an exception could be thrown
                $attrs[$local_attr] = null;
                continue;
            }

            if (!is_array($ldapuser_attrs[$ldap_attr])) {
                $attrs[$local_attr] = $ldapuser_attrs[$ldap_attr];
            }

            if (count($ldapuser_attrs[$ldap_attr]) == 0) {
                // an exception could be thrown
                $attrs[$local_attr] = null;
                continue;
            }

            $attrs[$local_attr] = $ldapuser_attrs[$ldap_attr][0];
            //$attrs[$local_attr] = implode(',', $ldapuser_attrs[$ldap_attr]);
        }

        return $attrs;
    }

    protected static function accessProtected($obj, $prop)
    {
        $reflection = new \ReflectionClass($obj);
        $property = $reflection->getProperty($prop);
        $property->setAccessible(true);
        return $property->getValue($obj);
    }
}
1 like
sadi78's avatar

Dear @sunnyboy , bear in mind that the tutorial for the "adminless ldap auth" is meant for the cases where there is no admin user in the ldap server.

In your case -it's impossible to know without asking the administrator first- you most probably need to connect with the admin username and password... the same way that you need a username and password to connect to MySQL before being able to perform any queries.

If that's the case, forget about this tutorial, because it won't help you.

SunnyBoy's avatar

@sadi78 Thanks for the tip, but this issue is already resolved. Appreciated

raelo's avatar

Hello @sunnyboy ! Since your problem is solved, can you share with me your workable code please? Thanks!

1 like
raelo's avatar

Hello @sinnbeck ! Can you share with me your complete workable code for this (Without Database) please?

SunnyBoy's avatar

It's all in there what one would need, I have to look into my archive and probably upload it to github or something if you still looking.

1 like
alinad's avatar

can you help me with ldaprecord ?

Sinnbeck's avatar

Please create a new thread, so we can give you some help :) Install the above package and describe your problems in a new thread.

1 like
alinad's avatar

can you help me with ldaprecord ? I'm trying to implements an LDAP authentication in an application for my company. I'm using Laravel 5.8 and the LdapRecord package

I have succeed to connect the application with the LDAP server test see Successfully connected and my to authenticate with openldap to online server its also Successfully. but when i want to do the authentication with active directory to my app it not working , Why who can help me? Here is my code :

The .env

LDAP_LOGGING=true
LDAP_CONNECTION=default
LDAP_HOST=server
LDAP_PORT=389
LDAP_BASE_DN="dc=mydomain,dc=local"
LDAP_TIMEOUT=5
LDAP_SSL=false
LDAP_TLS=false

The ldap.php

return [

 'default' => env('LDAP_CONNECTION', 'default'),



'connections' => [

    'default' => [
        'hosts' => [env('LDAP_HOST', 'server')],
        'username' => env('LDAP_USERNAME', ''),
        'password' => env('LDAP_PASSWORD', ''),
        'port' => env('LDAP_PORT', 389),
        'base_dn' => env('LDAP_BASE_DN', 'dc=mydomain,dc=local'),
        'timeout' => env('LDAP_TIMEOUT', 5),
        'use_ssl' => env('LDAP_SSL', false),
        'use_tls' => env('LDAP_TLS', false),
    ],

],



'logging' => env('LDAP_LOGGING', true),



'cache' => [
    'enabled' => env('LDAP_CACHE', false),
    'driver' => env('CACHE_DRIVER', 'file'),
],

];

The auth.php.

return [

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

'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'ldap',
    ],

    'api' => [
        'driver' => 'token',
        'provider' => 'users',
        'hash' => false,
    ],
],



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

    // 'users' => [
    //     'driver' => 'database',
    //     'table' => 'users',
    // ],
],



'passwords' => [
    'users' => [
        'provider' => 'users',
        'table' => 'password_resets',
        'expire' => 60,
        'throttle' => 60,
    ],
],



'password_timeout' => 10800,

];

The user.php model

namespace App; use Illuminate\Contracts\Auth\MustVerifyEmail; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; use LdapRecord\Laravel\Auth\LdapAuthenticatable; use LdapRecord\Laravel\Auth\AuthenticatesWithLdap;

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

protected $fillable = [
    'name',
    'email',
    'password',

];

protected $hidden = [
    'password', 'remember_token' ,
];


protected $casts = [
    'email_verified_at' => 'datetime',
];

}

The LoginController

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;
    class LoginController extends Controller
	{



	use AuthenticatesUsers;

	protected $redirectTo = RouteServiceProvider::HOME;


public function __construct()
{
    $this->middleware('guest')->except('logout');
}

protected function credentials(Request $request)
{
    return [
        'uid' => $request->get('username'),
        'password' => $request->get('password'),
    ];
}

public function username()
{
    return 'username';
}

Is there anyone who has already used this package and can help me on my code ? thank you in advance :)

alinad's avatar

Hi raelo , are you completed your auth with ldap ?

crypcode's avatar

Dammit doing everything the same, connection works, but auth doesnt ir goes to login every time it doesn't matter if credentials good or bad but i can get data through my connection can someone help to find mistake i'am doing?

Please or to participate in this conversation.