Adldap2 / Adldap2-Laravel

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

Adldap Authenticate Missing argument 2 #185

Closed guihig closed 7 years ago

guihig commented 8 years ago

Hi,

I've been trying to do an Active Directory authenticate in laravel by this packge, but at this action its returning the following error message:

ErrorException in AdldapServiceProvider.php line 81: Missing argument 2 for Adldap\Laravel\AdldapServiceProvider::Adldap\Laravel{closure}()

Any help to my problem?

guihig commented 8 years ago

Here's my AuthController.

`<?php namespace App\Http\Controllers\Auth;

use Illuminate\Http\Request; use App\Http\Controllers\Controller; use Illuminate\Contracts\Auth\Guard; use Illuminate\Contracts\Auth\Registrar; use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers;

class AuthController extends Controller {

/*
|--------------------------------------------------------------------------
| Registration & Login Controller
|--------------------------------------------------------------------------
|
| This controller handles the registration of new users, as well as the
| authentication of existing users. By default, this controller uses
| a simple trait to add these behaviors. Why don't you explore it?
|
*/

use AuthenticatesAndRegistersUsers;

protected $username = 'username';

/**
 * Create a new authentication controller instance.
 *
 * @param  \Illuminate\Contracts\Auth\Guard  $auth
 * @param  \Illuminate\Contracts\Auth\Registrar  $registrar
 * @return void
 */
public function __construct(Guard $auth, Registrar $registrar)
{
    $this->auth = $auth;
    $this->registrar = $registrar;

    $this->middleware('guest', ['except' => 'getLogout']);
}

public function postLogin(Request $request)
{
         //pass through validation rules
         $this->validate($request, ['username' => 'required', 'password' => 'required']);

         $credentials = [
                 'username' => trim($request->get('username')),
                 'password' => trim($request->get('password'))
         ];

         $remember = $request->has('remember');

         //log in the user
         if ($this->auth->attempt($credentials)) {
                 return redirect()->intended('/');
         }

         //show error if invalid data entered
         return redirect()->back()->withErrors('Login/Pass do not match')->withInput();
}

}`

stevebauman commented 8 years ago

Did you recently upgrade from Adldap2 Laravel v1 to v2?

guihig commented 8 years ago

Sorry, i'm just new on laravel and Adldap, i'v installed Adldap2 v2 directly to a fresh installation of laravel 5.0

guihig commented 8 years ago

Only a extra information, the error keep ocurring in this line.

//log in the user
if ($this->auth->attempt($credentials, $remember)) {
    return redirect()->intended('/');
 }
stevebauman commented 8 years ago

Can you post your config/adldap.php file?

guihig commented 8 years ago

<?php

return [

/*
|--------------------------------------------------------------------------
| Connections
|--------------------------------------------------------------------------
|
| This array stores the connections that are added to Adldap. You can add
| as many connections as you like.
|
| The key is the name of the connection you wish to use and the value is
| an array of configuration settings.
|
*/

'connections' => [

    'default' => [

        /*
        |--------------------------------------------------------------------------
        | Auto Connect
        |--------------------------------------------------------------------------
        |
        | If auto connect is true, anytime Adldap is instantiated it will automatically
        | connect to your AD server. If this is set to false, you must connect manually
        | using: Adldap::connect().
        |
        */

        'auto_connect' => true,

        /*
        |--------------------------------------------------------------------------
        | Connection
        |--------------------------------------------------------------------------
        |
        | The connection class to use to run operations on.
        |
        | You can also set this option to `null` to use the default connection class.
        |
        | Custom connection classes must implement \Adldap\Contracts\Connections\ConnectionInterface
        |
        */

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

        /*
        |--------------------------------------------------------------------------
        | Schema
        |--------------------------------------------------------------------------
        |
        | The schema class to use for retrieving attributes and generating models.
        |
        | You can also set this option to `null` to use the default schema class.
        |
        | Custom schema classes must implement \Adldap\Contracts\Schemas\SchemaInterface
        |
        */

        'schema' => Adldap\Schemas\ActiveDirectory::class,

        /*
        |--------------------------------------------------------------------------
        | Connection Settings
        |--------------------------------------------------------------------------
        |
        | This connection settings array is directly passed into the Adldap constructor.
        |
        | Feel free to add or remove settings you don't need.
        |
        */

        'connection_settings' => [

            /*
            |--------------------------------------------------------------------------
            | Account Prefix
            |--------------------------------------------------------------------------
            |
            | The account prefix option is the prefix of your user accounts in AD.
            |
            | For example, if you'd prefer your users to use only their username instead
            | of specifying a domain ('ACME\jdoe'), enter your domain name.
            |
            */

            'account_prefix' => 'xxxxx\\',

            /*
            |--------------------------------------------------------------------------
            | Account Suffix
            |--------------------------------------------------------------------------
            |
            | The account suffix option is the suffix of your user accounts in AD.
            |
            | For example, if your domain DN is DC=corp,DC=acme,DC=org, then your
            | account suffix would be @corp.acme.org. This is then appended to
            | then end of your user accounts on authentication.
            |
            */

            'account_suffix' => '',

            /*
            |--------------------------------------------------------------------------
            | Domain Controllers
            |--------------------------------------------------------------------------
            |
            | The domain controllers option is an array of servers located on your
            | network that serve Active Directory. You can insert as many servers or
            | as little as you'd like depending on your forest (with the
            | minimum of one of course).
            |
            | These can be IP addresses of your server(s), or the host name.
            |
            */

            'domain_controllers' => ['xxxx.xxxxx.xxx.xxx'],

            /*
            |--------------------------------------------------------------------------
            | Port
            |--------------------------------------------------------------------------
            |
            | The port option is used for authenticating and binding to your AD server.
            |
            */

            'port' => 389,

            /*
            |--------------------------------------------------------------------------
            | Timeout
            |--------------------------------------------------------------------------
            |
            | The timeout option allows you to configure the amount of time in
            | seconds that your application waits until a response
            | is received from your LDAP server.
            |
            */

            'timeout' => 5,

            /*
            |--------------------------------------------------------------------------
            | Base Distinguished Name
            |--------------------------------------------------------------------------
            |
            | The base distinguished name is the base distinguished name you'd like
            | to perform operations on. An example base DN would be DC=corp,DC=acme,DC=org.
            |
            | If one is not defined, then Adldap will try to find it automatically
            | by querying your server. It's recommended to include it to
            | limit queries executed per request.
            |
            */

            'base_dn' => 'dc=corp,dc=acme,dc=org',

            /*
            |--------------------------------------------------------------------------
            | Administrator Account Suffix
            |--------------------------------------------------------------------------
            |
            | This option allows you to set a different account suffix for your
            | configured administrator account upon binding.
            |
            | If left empty, your `account_suffix` option will be used.
            |
            */

            'admin_account_suffix' => '',

            /*
            |--------------------------------------------------------------------------
            | Administrator Username & Password
            |--------------------------------------------------------------------------
            |
            | When connecting to your AD server, a username and password is required
            | to be able to query and run operations on your server(s). You can
            | use any user account that has these permissions. This account
            | does not need to be a domain administrator unless you
            | require changing and resetting user passwords.
            |
            */

            'admin_username' => env('ADLDAP_ADMIN_USERNAME', 'username'),
            'admin_password' => env('ADLDAP_ADMIN_PASSWORD', 'password'),

            /*
            |--------------------------------------------------------------------------
            | Follow Referrals
            |--------------------------------------------------------------------------
            |
            | The follow referrals option is a boolean to tell active directory
            | to follow a referral to another server on your network if the
            | server queried knows the information your asking for exists,
            | but does not yet contain a copy of it locally.
            |
            | This option is defaulted to false.
            |
            */

            'follow_referrals' => false,

            /*
            |--------------------------------------------------------------------------
            | SSL & TLS
            |--------------------------------------------------------------------------
            |
            | If you need to be able to change user passwords on your server, then an
            | SSL or TLS connection is required. All other operations are allowed
            | on unsecured protocols. One of these options are definitely recommended
            | if you have the ability to connect to your server securely.
            |
            */

            'use_ssl' => false,
            'use_tls' => false,

        ],

    ],

],

];

guihig commented 8 years ago

Man, i've corriged the missing 2 arguments by installing the laravel 5.3, but now it seens to have the problem of not auth any credentials by the Auth:attempt() method, only by \Adldap::auth()->attempt(). Is there any config that i've missed, can u help me?

stevebauman commented 8 years ago

Hi @guihig, there's many things that could be going on here.

Your controller and config/adldap.php file are fine, but can you post your config/adldap_auth.php file as well as your login view file?

stevebauman commented 8 years ago

Oh also, your base_dn isn't correct in your config/adldap.php file:

'base_dn' => 'dc=corp,dc=acme,dc=org',

You need to change it to your current directory's base distinguished name.

guihig commented 8 years ago

Follow the adldap_auth

`<?php

return [

/*
|--------------------------------------------------------------------------
| Connection
|--------------------------------------------------------------------------
|
| The connection to use for authentication.
|
| You must specify connections in your `config/adldap.php` configuration file.
|
| This must be a string.
|
*/

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

/*
|--------------------------------------------------------------------------
| Username Attribute
|--------------------------------------------------------------------------
|
| The username attribute is an array of the html input name and the LDAP
| attribute to discover the user by. The reason for this is to hide
| the attribute that you're using to login users.
|
| For example, if your HTML input name is `email` and you'd like users
| to login by their LDAP `mail` attribute, then keep the
| configuration below. However, if you'd like to login users
| by their usernames, then change `mail` to `samaccountname`.
| and `email` to `username`.
|
| This must be an array with a key - value pair.
|
*/

'username_attribute' => ['username' => 'samaccountname'],

/*
|--------------------------------------------------------------------------
| Limitation Filter
|--------------------------------------------------------------------------
|
| The limitation filter allows you to enter a raw filter to only allow
| specific users / groups / ous to authenticate.
|
| This should be a standard LDAP filter.
|
*/

'limitation_filter' => env('ADLDAP_LIMITATION_FILTER', ''),

/*
|--------------------------------------------------------------------------
| Login Fallback
|--------------------------------------------------------------------------
|
| The login fallback option allows you to login as a user located on the
| local database if active directory authentication fails.
|
| Set this to true if you would like to enable it.
|
| This option must be true or false.
|
*/

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

/*
|--------------------------------------------------------------------------
| Password Key
|--------------------------------------------------------------------------
|
| The password key is the name of the input array key located inside
| the user input array given to the auth driver.
|
| Change this if you change your password fields input name.
|
| This option must be a string.
|
*/

'password_key' => env('ADLDAP_PASSWORD_KEY', 'password'),

/*
|--------------------------------------------------------------------------
| Password Sync
|--------------------------------------------------------------------------
|
| The password sync option allows you to automatically synchronize
| users AD passwords to your local database. These passwords are
| hashed natively by laravel.
|
| Enabling this option would also allow users to login to their
| accounts using the password last used when an AD connection
| was present.
|
| If this option is disabled, the local user account is applied
| a random 16 character hashed password, and will lose access
| to this account upon loss of AD connectivity.
|
| This option must be true or false.
|
*/

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

/*
|--------------------------------------------------------------------------
| Login Attribute
|--------------------------------------------------------------------------
|
| The login attribute is the name of the active directory user property
| that you use to log users in. For example, if your company uses
| email, then insert `mail`.
|
| This option must be a string.
|
*/

'login_attribute' => env('ADLDAP_LOGIN_ATTRIBUTE', 'samaccountname'),

/*
|--------------------------------------------------------------------------
| Windows Auth Attribute
|--------------------------------------------------------------------------
|
| This array represents how a user is found when
| utilizing the Adldap Windows Auth Middleware.
|
| The key of the array represents the attribute that the user is located by.
|
|     For example, if 'samaccountname' is the key, then your LDAP server is
|     queried for a user with the 'samaccountname' equal to the
|     $_SERVER['AUTH_USER'] variable.
|
|     If a user is found, they are imported into your
|     local database, then logged in.
|
| The value of the array represents the 'key' of the $_SERVER
| array to pull the users username from.
|
|    For example, $_SERVER['AUTH_USER'].
|
| This must be an array with a key - value pair.
|
*/

'windows_auth_attribute' => ['samaccountname' => 'AUTH_USER'],

/*
|--------------------------------------------------------------------------
| Bind User to Model
|--------------------------------------------------------------------------
|
| The bind user to model option allows you to access the Adldap user model
| instance on your laravel database model to be able run operations
| or retrieve extra attributes on the Adldap user model instance.
|
| If this option is true, you must insert the trait:
|
|   `Adldap\Laravel\Traits\AdldapUserModelTrait`
|
| Onto your User model configured in `config/auth.php`.
|
| Then use `Auth::user()->adldapUser` to access.
|
| This option must be true or false.
|
*/

'bind_user_to_model' => env('ADLDAP_BIND_USER_TO_MODEL', true),

/*
|--------------------------------------------------------------------------
| Sync Attributes
|--------------------------------------------------------------------------
|
| Attributes specified here will be added / replaced on the user model
| upon login, automatically synchronizing and keeping the attributes
| up to date.
|
| The array key represents the Laravel model key, and the value
| represents the Active Directory attribute to set it to.
|
| Your login attribute is already synchronized and does not need to be
| added to this array.
|
*/

'sync_attributes' => [

    'name' => 'cn',

],

/*
|--------------------------------------------------------------------------
| Select Attributes
|--------------------------------------------------------------------------
|
| Attributes to select upon the user on authentication and binding.
|
| If no attributes are given inside the array, all attributes on the
| user are selected.
|
| ** Note ** : Keep in mind you must include attributes that you would
| like to synchronize, as well as your login attribute.
|
*/

'select_attributes' => [

    //

],

]; `

guihig commented 8 years ago

And i did change de base_dn, but has no effects

stevebauman commented 8 years ago

Ok, now I need your login blade view, can you post that?

You're also using a username to login users. Did you change the default laravel migration file that uses email instead of username?

guihig commented 8 years ago

The login.blade.php

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>{{ $page_title or "AdminLTE Dashboard" }}</title>
    <meta content='width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no' name='viewport'>
    <!-- Bootstrap 3.3.2 -->
    <link href="{{ asset("/bower_components/AdminLTE/bootstrap/css/bootstrap.min.css") }}" rel="stylesheet" type="text/css" />
    <!-- Font Awesome Icons -->
    <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.5.0/css/font-awesome.min.css" rel="stylesheet" type="text/css" />
    <!-- Ionicons -->
    <link href="https://cdnjs.cloudflare.com/ajax/libs/ionicons/2.0.1/css/ionicons.min.css" rel="stylesheet" type="text/css" />
    <!-- Theme style -->
    <link href="{{ asset("/bower_components/AdminLTE/dist/css/AdminLTE.min.css")}}" rel="stylesheet" type="text/css" />
    <!-- AdminLTE Skins. We have chosen the skin-blue for this starter
                page. However, you can choose any other skin. Make sure you
                apply the skin class to the body tag so the changes take effect.
    -->
    <link href="{{ asset("/bower_components/AdminLTE/dist/css/skins/skin-blue.min.css")}}" rel="stylesheet" type="text/css" />
    <!-- iCheck -->
    <link href="{{ asset("/bower_components/AdminLTE/plugins/iCheck/square/blue.css")}}" rel="stylesheet" />

    <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[if lt IE 9]>
    <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
    <script src="https://oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script>
    <![endif]-->
</head>
<body class="hold-transition login-page">
    <div class="login-box">
      <div class="login-logo">
        <a href="#">Ayty<b>HD</b>Monitor</a>
      </div>
      <!-- /.login-logo -->
      <div class="login-box-body">
            @if (count($errors) > 0)
                <div class="alert alert-danger">
                    <strong>Whoops!</strong> There were some problems with your input.<br><br>
                    <ul>
                        @foreach ($errors->all() as $error)
                            <li>{{ $error }}</li>
                        @endforeach
                    </ul>
                </div>
            @endif
        <p class="login-box-msg">Sign in to start your session</p>

        <form class="form-horizontal" role="form" method="POST" action="{{ url('/login') }}">
          <div class="form-group has-feedback">
            <input type="text" class="form-control" name="username" value="{{ old('username') }}" placeholder="Usuário">
            <span class="glyphicon glyphicon-envelope form-control-feedback"></span>
          </div>
          <div class="form-group has-feedback">
            <input type="password" class="form-control" name="password" placeholder="Senha">
            <span class="glyphicon glyphicon-lock form-control-feedback"></span>
          </div>
          <div class="row">
            <div class="col-xs-8">
              <div class="checkbox icheck">
                <label>
                  <input type="checkbox" name="remember"> Remember Me
                </label>
              </div>
            </div>
            <!-- /.col -->
            <div class="col-xs-4">
              <button type="submit" class="btn btn-primary btn-block btn-flat">Sign In</button>
            </div>
            <!-- /.col -->
          </div>
        </form>
      </div>
      <!-- /.login-box-body -->
    </div>
    <!-- /.login-box -->

    <!-- REQUIRED JS SCRIPTS -->

    <!-- jQuery 2.1.3 -->
    <script src="{{ asset ("/bower_components/AdminLTE/plugins/jQuery/jQuery-2.2.3.min.js") }}"></script>
    <!-- Bootstrap 3.3.2 JS -->
    <script src="{{ asset ("/bower_components/AdminLTE/bootstrap/js/bootstrap.min.js") }}" type="text/javascript"></script>
    <!-- iCheck -->
    <script src="{{ asset ("/bower_components/AdminLTE/plugins/iCheck/icheck.min.js") }}"></script>
    <script>
      $(function () {
        $('input').iCheck({
          checkboxClass: 'icheckbox_square-blue',
          radioClass: 'iradio_square-blue',
          increaseArea: '20%' // optional
        });
      });
    </script>
    <!-- Resolve conflict in jQuery UI tooltip with Bootstrap tooltip -->
    <script>
      $.widget.bridge('uibutton', $.ui.button);
    </script>

    <!-- Optionally, you can add Slimscroll and FastClick plugins.
          Both of these plugins are recommended to enhance the
          user experience -->
</body>
</html>
guihig commented 8 years ago

I'm using a custom user table that was definated before, and the username colum is nm_user_ad instead of username, is there any local that i need to change?

stevebauman commented 8 years ago

I'm using a custom user table that was definated before, and the username colum is nm_user_ad instead of username, is there any local that i need to change?

Unfortunately yes, try changing the username_attribute configuration option in config/adldap_auth.php to:

'username_attribute' => ['nm_user_ad' => 'samaccountname'],

Then in your view, change your username input field name to nm_user_ad:

 <input type="text" class="form-control" name="nm_user_ad" value="{{ old('username') }}" placeholder="Usuário">
        <span class="glyphicon glyphicon-envelope form-control-feedback"></span>

This should work. However this goes back to the issue: #174

guihig commented 8 years ago

@stevebauman, i've made that change, but it keep not workin it the default Auth::atempt() just work with the Adldap::auth()->atempt(). Here is my LoginController.

<?php

namespace App\Http\Controllers\Auth;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Adldap\Adldap;
use Illuminate\Support\Facades\Auth;
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 = '/home';

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

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

    public function login(Request $request)
    {
        //dd($request->get('username'));

        $credentials = [
          'nm_user_ad' => trim($request->get('nm_user_ad')),
          'password' => trim($request->get('password'))
        ];

        $remember = $request->get('remember');
        //dd(\Adldap::auth()->attempt($request->get('nm_user_ad'), $request->get('password'), $remember));
        if (Auth::attempt($credentials, $remember)) {
            dd("Pass");
            // Authentication passed...
            return redirect()->intended('/');
        }

        return redirect()->back()->withErrors('Login/Password do not match!')->withInput();
    }

}
guihig commented 8 years ago

@stevebauman, i've figured out how to get it works, just addng an account to de ldap admin account, but now it claims another erro, tha seens it's trying to sync id from ldap user model to my user model or searching in my user model for a user id that doesn't exist

clasit commented 7 years ago

I had a similar problem. It is a problem in \Illuminate\Support\Collection class in 'old' versions of this Class, the function 'each' doesn't works like is expected.

The old function 'each' is:

    public function each(callable $callback){
        array_map($callback, $this->items);
        return $this;
    }

This code produces a "Missing argument 2 for..."

But now the code is: (This code works well)

        public function each(callable $callback){
            foreach ($this->items as $key => $item) {
                if ($callback($item, $key) === false) {
                    break;
                }
            }
            return $this;
        }

Update your framework. I hope it helps.

stevebauman commented 7 years ago

Closing due to inactivity.