0

Morning, I keep getting the message "A username must be specified." when trying to login my app. Connection to LDAP is OK, sync also, in my database/table users i see all username with password. But can't login with anyone username. Trying to dd($username) into LoginController, "guard()->attempt" show me "null". Thanks for your help !

My version

Laravel Version: ^7.0
Adldap2-Laravel Version: ^6.1
PHP Version: ^7.2.5
LDAP Type: OpenLDAP

my .env

LDAP_HOSTS=ldap.forumsys.com
LDAP_BASE_DN=dc=example,dc=com
LDAP_USERNAME=cn=read-only-admin,dc=example,dc=com
LDAP_PASSWORD=password
LDAP_PASSWORD_SYNC=true

my ldap.php

<?php

return [

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

     'connections' => [

        'default' => [

                  'auto_connect' => env('LDAP_AUTO_CONNECT', true),

                  'connection' => Adldap\Connections\Ldap::class,

               'settings' => [

               'schema' => Adldap\Schemas\OpenLDAP::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', 'dc=corp,dc=acme,dc=org'),

                'username' => env('LDAP_USERNAME', 'username'),
                'password' => env('LDAP_PASSWORD', 'secret'),

                'follow_referrals' => false,

                'use_ssl' => env('LDAP_USE_SSL', false),
                'use_tls' => env('LDAP_USE_TLS', false),

            ],

        ],

    ],

];

my ldap_auth

<?php

return [

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

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

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

    'rules' => [

        // Denys deleted users from authenticating.

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

        // Allows only manually imported users to authenticate.

        // Adldap\Laravel\Validation\Rules\OnlyImported::class,

    ],

    'scopes' => [

        // Only allows users with a user principal name to authenticate.
        // Suitable when using ActiveDirectory.
        // Adldap\Laravel\Scopes\UpnScope::class,

        // Only allows users with a uid to authenticate.
        // Suitable when using OpenLDAP.
        // Adldap\Laravel\Scopes\UidScope::class,

    ],

    'identifiers' => [

        'ldap' => [

            'locate_users_by' => 'uid',

            'bind_users_by' => 'distinguishedname',

        ],

        'database' => [

         'guid_column' => 'objectguid',

            'username_column' => 'username', //'email',

        ],

        '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' => [

        //'email' => 'userprincipalname',

        'username' => 'uid', 

        'name' => 'cn',

    ],

    '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,

        ],
    ],

];

my loginController

<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
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 = RouteServiceProvider::HOME;

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

    public function username()
    {
        return 'username';
    }
}
Black-Rabbit
  • 67
  • 1
  • 9

2 Answers2

0

Been through this pain myself.

It looks like you are connecting to LDAP with your service account, but I don't see where you are logging the authenticated user into Laravel. Do your users have to supply a username and password on a screen somewhere? If not, how do you grab the user and log them in to Laravel?

The way I did this in the businesses that had to go through LDAP was to have the normal Laravel login page, but a middle method within the login controller which sent a message to LDAP through the service account with the PW. If this succeeded, then login with Laravel's standard method. Basically just check the PW against LDAP and then log in rather than checking against the Laravel DB.

Example code - this will vary wildly but can give you an idea of what might work:

  if(env('LOGIN', false) === 'LDAP'){
        $ldap = new \App\Http\Controllers\ClientSpecific\BaseLDAPController();
        $username = $request->input('username');
        if($ldap->authenticate($username, $request->input('password'))){
            return $this->sendLoginResponse($request);
        }
    }else {
        if ($this->guard()->attempt($credentials, $request->has('remember'))) {
            return $this->sendLoginResponse($request);
        }
    }
Watercayman
  • 7,970
  • 10
  • 31
  • 49
  • Thanks @watercayman for your response. I use laravel standard view (login.blade.php) to connect with username and password. i just replace "email" into this view by "username". I use also laravel standard function login to authenticate after sync of my database. Result of this sync (php artisan adlap:import) is "succes'. – Black-Rabbit Jun 17 '20 at 12:08
  • Morning,See below my larevel_log when i try to login : [2020-06-17 13:09:17] local.INFO: User 'Isaac Newton' has been successfully found for authentication. [2020-06-17 13:09:17] local.INFO: User 'Isaac Newton' is being synchronized. [2020-06-17 13:09:17] local.INFO: User 'Isaac Newton' has been successfully synchronized. [2020-06-17 13:09:17] local.INFO: User 'Isaac Newton' is authenticating with username: '' [2020-06-17 13:09:17] local.ERROR: A username must be specified. {"exception":"[object] (Adldap\\Auth\\UsernameRequiredException(code: 0): A username must be specified. – Black-Rabbit Jun 17 '20 at 13:16
  • I did all this manually - I had issues with the packages for ldap too. For me, I connected and then drew the user name manually as you can see in the above code - I got it from `$request`. As I mentioned in the answer above, your log is showing that ldap is using the correct AD USER, but does not have a handle on the Laravel USERNAME. (Or maybe its the reverse, I don't know by the log). Either way, there is a link missing between your AD service account and your Laravel user. Look at whatever is input in the `sendLoginResponse()` method - if this is blank you know where the issue is. – Watercayman Jun 17 '20 at 13:57
  • Thks @watercayman to assist me. After many dd of my login controller i notice that there is no link between Auth\guard->attempt function into adlap2 and Auth\guard->attempt function into illuminate (façade). It's because adlap2 return empty. So how to make link between these to function ? – Black-Rabbit Jun 18 '20 at 20:01
  • Yep - this is what I thought. You've got an issue with the way you've set up adlap2. I can only tell you the answer to your problem (above) -- you'll need to go back to the package instructions to see where that link is meant to be, if it is installed correctly, if there is a breakdown, etc. There's a lot of places where you might have missed wiring it up. Now that you know what the issue is, I think you'll have to go back to the instructions with that in mind and try to find what's missing. Sorry - I know what a pain AD is. – Watercayman Jun 18 '20 at 20:30
0

I know this is an old question, but I was still facing this issue even in 2020 and it took a lot of my time. Actually the problem is very silly if you are also trying to bind an OpenLDAP server with your Laravel application using Adldap2-Laravel package. Adldap2-Laravel is by default configured for Microsoft's Active Directory. But for OpenLDAP, we need to properly change the Identifiers array as follows..

<?php

return [

     // configurations settings...

    'identifiers' => [

        'ldap' => [

            'locate_users_by' => 'uid', // changed from userprincipalname

            'bind_users_by' => 'dn', // changed from distinguishedname

        ],

        'database' => [

         'guid_column' => 'objectguid',

            'username_column' => 'username', //'email',

        ],

        'windows' => [

            'locate_users_by' => 'samaccountname',

            'server_key' => 'AUTH_USER',

        ],

    ],

    // rest of the configurations...

];

Do tell me if my answer is not clear for new comers since I'm also a newbie. I'll try to explain the solution further better :)

Fahad Javed
  • 338
  • 3
  • 8