Adldap2 / Adldap2-Laravel

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

I can Adldap::auth() but can't use the normal login #168

Closed alessandrobelli closed 7 years ago

alessandrobelli commented 8 years ago

Hello! If I do this inside the view, I receive 1 (or true with dd): {{\Adldap::auth()->attempt('username', 'password')}}

If I try to log in with login form I receive the error:

These credentials do not match our records.

This is my config.auth:

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

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

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

'providers' => [
        'adldap' => [ // Added 'adldap' provider here.
            'driver' => 'adldap',
            'model'  => App\Models\User::class,
        ],
],

And this is my LoginController:

<?php

namespace App\Http\Controllers\Auth;

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

class LoginController extends Controller
{

    use AuthenticatesUsers;

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

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

    /**
     * Get the login username to be used by the controller.
     *
     * @return string
     */
    public function username()
    {
        return 'username';
    }
        /**
     * Show the application's login form.
     *
     * @return \Illuminate\Http\Response
     */
    public function showLoginForm()
    {
        return view('auth.login');
    }

    public function postLogin(Request $request)
    {
        dd("tet");
        $rules = [
            'username' => 'required|min:3',
            'password' => 'required|min:3'
        ];
        $this->validate($request, $rules);

        // Form validated, check if the authentication matches
        if (Auth::attempt($request->input(), true)) {
            $user = Auth::user();
            // @todo: Sync the groups
            return redirect()->intended('dashboard');
        }
    }

    /**
     * Handle a login request to the application.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function login(Request $request)
    {
        $this->validateLogin($request);

        // If the class is using the ThrottlesLogins trait, we can automatically throttle
        // the login attempts for this application. We'll key this by the username and
        // the IP address of the client making these requests into this application.
        if ($lockedOut = $this->hasTooManyLoginAttempts($request)) {
            $this->fireLockoutEvent($request);

            return $this->sendLockoutResponse($request);
        }

        $credentials = $this->credentials($request);

        if ($this->guard()->attempt($credentials, $request->has('remember'))) {
            return $this->sendLoginResponse($request);
        }

        // If the login attempt was unsuccessful we will increment the number of attempts
        // to login and redirect the user back to the login form. Of course, when this
        // user surpasses their maximum number of attempts they will get locked out.
        if (! $lockedOut) {
            $this->incrementLoginAttempts($request);
        }

        return $this->sendFailedLoginResponse($request);
    }
        /**
     * Log the user out of the application.
     *
     * @param  Request  $request
     * @return \Illuminate\Http\Response
     */
    public function logout(Request $request)
    {
        $this->guard()->logout();

        $request->session()->flush();

        $request->session()->regenerate();

        return redirect('/');
    }

}

$this->guard()->attempt($credentials, $request->has('remember'))

I tried to change this and hard type my username and password, but then I get an error with the Sessionguard, because it needs an array of credentials...

stevebauman commented 8 years ago

Can you post your adldap_auth.php configuration file?

Also, did you change your create_users_table migration to match the username field you're using instead of email?

warlord0 commented 8 years ago

Laravel 5.3? if so replace the

protected $username = 'username';

with

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

in your LoginController.php

alessandrobelli commented 8 years ago

@warlord0 I did what you wrote, but after a while I think my main problem is with apache configuration. I don't have admin rights for security issues, then I can't configure kerberos or NTLM. Or maybe I just misunderstood how the plugin work :smile:

Then I found this way, if it's not wrong, could be useful.

  1. used this script http://blogs.msdn.com/cellfish/pages/ntlm-php.aspx to fake an ntlm auth and get the data of the current user
  2. I just return the $user var from that script.
  3. created this little script to check if the user exists or not
$check = Adldap::search()->where('samaccountname', '=', $user )->first();  
        if(isset($check)){
            # in here so the user exist on the server
            # check if exists in the local db
            # if not then create and login
            # if yes login
            $exist = User::where('username', '=', $user)->first();

            if (isset($exist) && !rAuth::user()) {
             rAuth::login($exist);
             return true;
         }elseif(!rAuth::user()){
            # create user
            $newuser= User::create([
            'username' => $user,
            'password' => bcrypt('randomstring'),
            'name' => $user
        ]);

            rAuth::login($newuser);
         }

where: use Illuminate\Support\Facades\Auth as rAuth;

warlord0 commented 8 years ago

Ahh, ntlm :( Not something I use as my clients could be anything and my choice of server is nginx which doesn't play well with ntlm.

If you really in need to using the $_SERVER remote_user or auth_user stuff then you have to have Apache configured with ntlm support. The fudge looks interesting though.

stevebauman commented 8 years ago

I did what you wrote, but after a while I think my main problem is with apache configuration. I don't have admin rights for security issues, then I can't configure kerberos or NTLM. Or maybe I just misunderstood how the plugin work

You shouldn't need admin rights on the domain if you just need to query for users.

You mention NTLM authentication. You can utilize the WindowsAuthenticate middleware for this to automatically log in users if you wish. You'll just need to change the windows_auth_attribute config array:

https://github.com/Adldap2/Adldap2-Laravel/blob/master/src/Config/auth.php#L125-L151

'windows_auth_attribute' => ['samaccountname' => 'REMOTE_USER'] // Was `AUTH_USER`,

With your regular login issues, I'm not sure what the issue may be. Your connection is definitely configured correctly, but there may be issues with your adldap_auth.php config (which still needs to be posted for me to help further).

alessandrobelli commented 8 years ago

@stevebauman sorry I forgot to post the adldap_auth.php

   'connection' => env('ADLDAP_CONNECTION', 'default'),
   'username_attribute' => ['username' => 'samaccountname'],
   'limitation_filter' => env('ADLDAP_LIMITATION_FILTER', ''),
    'login_fallback' => env('ADLDAP_LOGIN_FALLBACK', false),
  'password_key' => env('ADLDAP_PASSWORD_KEY', 'password'),

    'password_sync' => env('ADLDAP_PASSWORD_SYNC', false),

    'login_attribute' => env('ADLDAP_LOGIN_ATTRIBUTE', 'samaccountname'),
    'windows_auth_attribute' => ['samaccountname' => 'AUTH_USER'],
    'bind_user_to_model' => env('ADLDAP_BIND_USER_TO_MODEL', true),
    'sync_attributes' => [
'username' => 'samaccountname'

    ],

    'select_attributes' => [

        //

    ],

You shouldn't need admin rights on the domain if you just need to query for users. no I can query users perfectly, as my method above is working for me.

I would need to populate $_SERVER with the data of the authenticated user... so I need admin right to configure apache...

stevebauman commented 8 years ago

Ok, can you post your auth/login.blade.php file as well (or wherever your login form is stored)?

Also just to note, you can remove the 'username' => 'samaccountname' from your sync_attributes array. It's already synchronized since it's the login attribute.

alessandrobelli commented 8 years ago

@stevebauman This is auth.login.blade.php

@extends('layouts.app')

@section('content')
<div class="container">

    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            <div class="panel panel-default">
                <div class="panel-heading">Login</div>
                <div class="panel-body">
                    <form class="form-horizontal" role="form" method="POST" action="{{ url('/login') }}">
                        {{ csrf_field() }}

                        <div class="form-group{{ $errors->has('username') ? ' has-error' : '' }}">
                            <label for="username" class="col-md-4 control-label">Username</label>

                            <div class="col-md-6">
                                <input id="username" type="username" class="form-control" name="username" value="{{ old('username') }}" autofocus>

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

                        <div class="form-group{{ $errors->has('password') ? ' has-error' : '' }}">
                            <label for="password" class="col-md-4 control-label">Password</label>

                            <div class="col-md-6">
                                <input id="password" type="password" class="form-control" name="password" >
                                @if ($errors->has('password'))
                                    <span class="help-block">
                                        <strong>{{ $errors->first('password') }}</strong>
                                    </span>
                                @endif
                            </div>
                        </div>

                        <div class="form-group">
                            <div class="col-md-6 col-md-offset-4">
                                <div class="checkbox">
                                    <label>
                                        <input type="checkbox" name="remember"> Remember Me
                                    </label>
                                </div>
                            </div>
                        </div>

                        <div class="form-group">
                            <div class="col-md-8 col-md-offset-4">
                                <button type="submit" class="btn btn-primary">
                                    Login
                                </button>

                                <a class="btn btn-link" href="{{ url('/password/reset') }}">
                                    Forgot Your Password?
                                </a>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection
warlord0 commented 8 years ago

input type="username"? Should that be "text"?

alessandrobelli commented 8 years ago

oh yes sorry, I hard replaced email with username :astonished:

warlord0 commented 8 years ago

Been there done that ;)

stevebauman commented 8 years ago

Is this still an issue?