Adldap2 / Adldap2-Laravel

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

ADLDAP_ACCOUNT_SUFFIX doesn't work #540

Open briancardonas opened 6 years ago

briancardonas commented 6 years ago

Description:

Hello, Guys

First of all, I want you to congrats for this exceptional code. I know it'll help me a lot with my Laravel projects. I make one but I actually have a problem whit the ADLDAP_ACCOUNT_SUFFIX config in my .dev file

I can do login with my ActiveDirectory because I follow this instructions: https://github.com/Adldap2/Adldap2-Laravel/blob/master/docs/quick-start.md

But if I have my .env file whitout the config ADLDAP_ACCOUNT_SUFFIX I have to put in my login form username@mydomain.local

If I put the ADLDAP_ACCOUNT_SUFFIX in my .env file and I put in my login form username It doesn't work...I need your help because is a bad think tell my users they need to use username@mydomain.local when they need to sing in to my app.

I attach my actually conf files:

adlap_auth.php

<?php

return [
    'connection' => env('ADLDAP_CONNECTION', 'default'),
    'provider' => Adldap\Laravel\Auth\DatabaseUserProvider::class,
    'rules' => [
        Adldap\Laravel\Validation\Rules\DenyTrashed::class,
    ],
    'scopes' => [
        Adldap\Laravel\Scopes\UpnScope::class,
    ],
    'usernames' => [
        'ldap' => [
            'discover' => 'userprincipalname',
            'authenticate' => 'distinguishedname',
        ],
        'eloquent' => 'username',
        'windows' => [
            'discover' => 'samaccountname',
            'key' => 'AUTH_USER',
        ],
    ],
    'passwords' => [
        'sync' => env('ADLDAP_PASSWORD_SYNC', false),
        'column' => 'password',
    ],
    'login_fallback' => env('ADLDAP_LOGIN_FALLBACK', false),
    'sync_attributes' => [
        'username' => 'userprincipalname',
        'name' => 'cn',
    ],
    'logging' => [
        'enabled' => 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,
        ],
    ],
];

adldap.php

<?php

return [
    'connections' => [
        'default' => [
            'auto_connect' => env('ADLDAP_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', 'corp-dc1.corp.acme.org corp-dc2.corp.acme.org')),
                'port' => env('ADLDAP_PORT', 389),
                'timeout' => env('ADLDAP_TIMEOUT', 5),          
                'base_dn' => env('ADLDAP_BASEDN', 'dc=corp,dc=acme,dc=org'),
                'admin_account_prefix' => env('ADLDAP_ADMIN_ACCOUNT_PREFIX', ''),
                'admin_account_suffix' => env('ADLDAP_ADMIN_ACCOUNT_SUFFIX', ''),
                'admin_username' => env('ADLDAP_ADMIN_USERNAME', 'username'),
                'admin_password' => env('ADLDAP_ADMIN_PASSWORD', 'password'),
                'follow_referrals' => false,
                'use_ssl' => env('ADLDAP_USE_SSL', false),
                'use_tls' => env('ADLDAP_USE_TLS', false),
            ],
        ],
    ],
];

.env

ADLDAP_CONTROLLERS=myActiveDirectoryIP
ADLDAP_BASEDN="dc=mydomain,dc=local"
ADLDAP_ACCOUNT_SUFFIX=@mydomain.local //doesn't work (this is what I want)

ADLDAP_ADMIN_USERNAME=admin
ADLDAP_ADMIN_PASSWORD=secret
ADLDAP_ADMIN_ACCOUNT_SUFFIX=@mydomain.local

MyLoginForm

@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">{{ __('Login') }}</div>

                <div class="card-body">
                    <form method="POST" action="{{ route('login') }}">
                        @csrf

                        <div class="form-group row">
                            <label for="username" class="col-sm-4 col-form-label text-md-right">{{ __('Username') }}</label>

                            <div class="col-md-6">
                                <input id="username" type="text" class="form-control{{ $errors->has('username') ? ' is-invalid' : '' }}" name="username" value="{{ old('username') }}" required autofocus>

                                @if ($errors->has('username'))
                                    <span class="invalid-feedback">
                                        <strong>{{ $errors->first('username') }}</strong>
                                    </span>
                                @endif
                            </div>
                        </div>

                        <div class="form-group row">
                            <label for="password" class="col-md-4 col-form-label text-md-right">{{ __('Password') }}</label>

                            <div class="col-md-6">
                                <input id="password" type="password" class="form-control{{ $errors->has('password') ? ' is-invalid' : '' }}" name="password" required>

                                @if ($errors->has('password'))
                                    <span class="invalid-feedback">
                                        <strong>{{ $errors->first('password') }}</strong>
                                    </span>
                                @endif
                            </div>
                        </div>

                        <div class="form-group row">
                            <div class="col-md-6 offset-md-4">
                                <div class="checkbox">
                                    <label>
                                        <input type="checkbox" name="remember" {{ old('remember') ? 'checked' : '' }}> {{ __('Remember Me') }}
                                    </label>
                                </div>
                            </div>
                        </div>

                        <div class="form-group row mb-0">
                            <div class="col-md-8 offset-md-4">
                                <button type="submit" class="btn btn-primary">
                                    {{ __('Login') }}
                                </button>

                                <a class="btn btn-link" href="{{ route('password.request') }}">
                                    {{ __('Forgot Your Password?') }}
                                </a>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

Thank you very much for your help. I apologize for my bad English...I wish you could understand what I want and what is not working...

royalroot commented 6 years ago

Hello,

on this part I set both to samaccountname and it worked in my environment: 'usernames' => [ 'ldap' => [ 'discover' => 'userprincipalname', 'authenticate' => 'distinguishedname',

Maybe it works for you.

Nico

briancardonas commented 6 years ago

Hello, Nico

Thank you for comment...When I do that I get another error (something I use to) the code try to insert again my user data and my database get an error because username is unique...The exact error is: Integrity constraint violation: 1062 Duplicate entry for mi account...

Brian

stevebauman commented 6 years ago

Hi @briancardonas, what database are you using?

If you're using Postgre or other case-sensitive databases, you need to call strtolower() on usernames prior to authenticating users.

briancardonas commented 6 years ago

Hi @stevebauman,

I'm using MySQL and the problem is when I try to autenticate my users using ADLDAP_ACCOUNT_SUFFIX in my .env file It doesn't work I need to override login action to make it works...But...In my opinion I'll prefered if the ADLDAP_ACCOUNT_SUFFIX work's

public function login(Request $request) {
  $credentials` = $request->only('username', 'password');
  ['username'] = $credentials['username'].'@mydomain.local';
  (Auth::attempt($credentials)) {
    redirect()->route('home');
  }
}
miikee-us commented 6 years ago

I am also experiencing this same issue with my application on a MYSQL database.

stevebauman commented 6 years ago

Hey everyone, I promise I'm not ignoring you! Just really swamped with internal projects at the moment.

A new user will only be created if the initial lookup of the active directory user in your database returns null.

This lookup is done in the Import::findByCredentials() method:

https://github.com/Adldap2/Adldap2-Laravel/blob/master/src/Commands/Import.php

Quickest way to debug would be to dump and die the passed in credentials to see what is being queried in your database.

I'll be building in some tools for easier debugging, but for right now that's the quickest way.

Will comment again when I'm on a computer (using phone at the moment).

Thanks for your patience!

miikee-us commented 6 years ago

No worries, Thanks for the recommendation.

FrancisBou commented 6 years ago

I'm new to this framwork and I can confirm I have the same problem. It works perfectly for the admin suffix but the user suffix won't authenticate the user.

murrant commented 5 years ago

Would be great if this did a simple Str::finish() to append the domain so I can search with userPrincipalName and allow short or long logins.

stevebauman commented 5 years ago

Hi @murrant,

Mind sending a PR so I know what you mean for implementation?

murrant commented 5 years ago

I haven't gotten that far yet, need adldap2 working in my project first. We'll see if I get that far...