PHPackages                             csun-metalab/laravel-directory-authentication - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Authentication &amp; Authorization](/categories/authentication)
4. /
5. csun-metalab/laravel-directory-authentication

ActiveLibrary[Authentication &amp; Authorization](/categories/authentication)

csun-metalab/laravel-directory-authentication
=============================================

Composer package for Laravel 5.0 and above to allow for directory-based authentication

v2.0.0(9mo ago)04.5kMITPHPPHP &gt;=7.1

Since Jun 7Pushed 9mo ago1 watchersCompare

[ Source](https://github.com/PioneeringTechLab/laravel-directory-authentication)[ Packagist](https://packagist.org/packages/csun-metalab/laravel-directory-authentication)[ RSS](/packages/csun-metalab-laravel-directory-authentication/feed)WikiDiscussions dev Synced 3w ago

READMEChangelogDependenciesVersions (12)Used By (0)

Laravel Directory Authentication
================================

[](#laravel-directory-authentication)

Composer package for Laravel 5.0 and above to allow for directory-based authentication.

This package adds the ability to perform both local database and LDAP-based authentication.

Once the user has been authenticated via the directory service (such as LDAP) a local database lookup is performed in order to resolve a user model instance that is accessible through `Auth::user()`.

If you wish to use only local database authentication (but still leverage the functionality of the package) instead, please look at the [Laravel Directory Authentication (Database Only)](https://github.com/csun-metalab/laravel-directory-authentication/blob/dev/README_DB.md) Readme.

**NOTE:** authorization was added in Laravel 5.1 and therefore there is a breaking change in the `MetaUser` class. If you need to use this package for Laravel 5.0, please use any version of this package prior to `1.6.0`.

Table of Contents
-----------------

[](#table-of-contents)

- [Installation](#installation)
- [Required Environment Variables](#required-environment-variables)
- [Optional Environment Variables](#optional-environment-variables)
- [The HandlerLDAP class](#the-handlerldap-class)
- [The MetaUser Class](#the-metauser-class)
- [Creating a Custom User Class](#creating-a-custom-user-class)
- [Authenticating](#authenticating)
- [Masquerading](#masquerading)
- [Adding New LDAP Records](#adding-new-ldap-records)
- [Modifying Existing LDAP Records](#modifying-existing-ldap-records)
- [Modifying LDAP User Passwords](#modifying-ldap-user-passwords)

Installation
------------

[](#installation)

**NOTE:** There are different configuration entries to change further down based on the Laravel version you are using.

### Composer, Environment, and Service Provider

[](#composer-environment-and-service-provider)

#### Composer

[](#composer)

To install from Composer, use the following commands in this order:

```
composer require tiesa/ldap:dev-master
composer require csun-metalab/laravel-directory-authentication

```

There are two commands because `tiesa/ldap` cannot be in the `require` clause for this package as that dependency only exposes a `dev-master` release and no versioned releases. Due to this, it evaluates to a `minimum-stability` of `dev` and cannot be included as a dependency of a package going into a project with the `minimum-stability` of `stable`.

#### Environment

[](#environment)

Now, add the following line(s) to your `.env` file:

```
LDAP_HOST=
LDAP_BASE_DN=

```

You may also elect to add the following optional line(s) to your `.env` file to customize the functionality further:

```
LDAP_VERSION=3
LDAP_ALLOW_NO_PASS=false
LDAP_DN=
LDAP_PASSWORD=

LDAP_SEARCH_USER_ID=employeeNumber
LDAP_SEARCH_USERNAME=uid
LDAP_SEARCH_MAIL=mail
LDAP_SEARCH_MAIL_ARRAY=mailLocalAddress
LDAP_SEARCH_USER_QUERY=

LDAP_DB_USER_ID_PREFIX=
LDAP_DB_RETURN_FAKE_USER=false

LDAP_OVERLAY_DN=

LDAP_ADD_BASE_DN=
LDAP_ADD_DN=
LDAP_ADD_PW=

LDAP_MODIFY_METHOD=self
LDAP_MODIFY_BASE_DN=
LDAP_MODIFY_DN=
LDAP_MODIFY_PW=

```

#### Service Provider

[](#service-provider)

Next, add the service provider to your `providers` array in `config/app.php` in Laravel as follows:

```
'providers' => [
   //...

   CSUNMetaLab\Authentication\Providers\AuthServiceProvider::class,

   // You can also use this based on Laravel convention:
   // 'CSUNMetaLab\Authentication\Providers\AuthServiceProvider',

   //...
],

```

### Configuration (Laravel 5.2 and Above)

[](#configuration-laravel-52-and-above)

Next, change the `driver` to `ldap` and add the full classname of the user model to use for database lookups in the `users` array within `config/auth.php` as follows:

```
'providers' => [
    'users' => [
        // LDAP authentication method
        'driver' => 'ldap',

        // this can be any subclass of the CSUNMetaLab\Authentication\MetaUser class
        // or the MetaUser class itself since it works out of the box
        'model' => CSUNMetaLab\Authentication\MetaUser::class,
    ],
],

```

### Configuration (Laravel 5.0 and 5.1)

[](#configuration-laravel-50-and-51)

Next, change the `driver` to `ldap` and change the `model` attribute to be the full classname of the user model to use for database lookups within `config/auth.php` as follows:

```
// LDAP authentication method
'driver' => 'ldap',

// this can be any subclass of the CSUNMetaLab\Authentication\MetaUser class
// or the MetaUser class itself since it works out of the box
'model' => 'CSUNMetaLab\Authentication\MetaUser',

```

### Publish Configuration

[](#publish-configuration)

Finally, run the following Artisan command to publish the configuration:

```
php artisan vendor:publish

```

Required Environment Variables
------------------------------

[](#required-environment-variables)

You added two environment variables to your `.env` file that control the connection to the LDAP server as well as its searching subtree.

### LDAP\_HOST

[](#ldap_host)

This is the hostname or IP address of the LDAP server.

### LDAP\_BASE\_DN

[](#ldap_base_dn)

This is the base DN under which all people to be searched for reside. This may be something like the following:

`ou=People,ou=Auth,o=Organization`

Someone under this base DN may therefore exist with the following record:

`uid=person,ou=People,ou=Auth,o=Organization`

**NOTE:** The environment variables of `LDAP_BASE_DN` and `LDAP_OVERLAY_DN` are incompatible. Please use either one or the other. Ideally, you would use `LDAP_OVERLAY_DN` if your LDAP server makes use of an overlay to create a logical root for multiple subtrees. Otherwise, use `LDAP_BASE_DN` for the search base.

Optional Environment Variables
------------------------------

[](#optional-environment-variables)

There are several optional environment variables that may be added to customize the functionality of the package even further.

### LDAP\_VERSION

[](#ldap_version)

The version of LDAP to use when performing operations. The default is `3`.

### LDAP\_ALLOW\_NO\_PASS

[](#ldap_allow_no_pass)

True to turn off user password validation (and therefore use the admin DN and password for searching for people). When false, binding and searching is done with the username and password passed to `Auth::attempt()`.

Default is `false`.

### LDAP\_DN

[](#ldap_dn)

The admin DN to use when binding and searching for people. This is only used when user password validation is turned off (so searching can still happen).

### LDAP\_PASSWORD

[](#ldap_password)

The admin password to use when binding and searching for people. This is only used when user password validation is turned off (so searching can still happen).

### LDAP\_SEARCH\_USER\_ID

[](#ldap_search_user_id)

The field to use when looking-up a person in LDAP by their user ID; this is typically a numeric field.

Default is `employeeNumber`. This is the field value that will be used when checking for a user in the associated data model and database table/view.

This can also be the same as the `LDAP_SEARCH_USERNAME` value if you want to perform both the LDAP and database lookups with the same value.

### LDAP\_SEARCH\_USERNAME

[](#ldap_search_username)

The field to use when looking-up a person in LDAP by their username; this is typically the POSIX ID.

Default is `uid`. This is the value that will be used to perform the search operation as the username passed to the call to `Auth::attempt()`.

If password validation is turned on, this is also the username that will be used for the bind operation when combined with the base DN.

### LDAP\_SEARCH\_MAIL

[](#ldap_search_mail)

The field to use when looking-up a person in LDAP by their email address.

Default is `mail`.

### LDAP\_SEARCH\_MAIL\_ARRAY

[](#ldap_search_mail_array)

The field to use when looking-up a person in LDAP by all valid email addresses and aliases; this is typically an array attribute.

Default is `mailLocalAddress`.

### LDAP\_SEARCH\_USER\_QUERY

[](#ldap_search_user_query)

Optional search query that will replace the default query executed by the package during user directory searches. If not specified, the query that will be used is the equivalent of `(|(uid=%s)(mail=%s)(mailLocalAddress=%s))` depending on the values of `LDAP_SEARCH_USERNAME`, `LDAP_SEARCH_MAIL`, and `LDAP_SEARCH_MAIL_ARRAY`.

If specified, this query needs to be a `vsprintf()`-compatible string and use `%s` as the placeholder for the search value.

### LDAP\_DB\_USER\_ID\_PREFIX

[](#ldap_db_user_id_prefix)

Optional prefix before the value of the employee ID primary key in the associated database table/view.

Default is blank (no prefix).

For example, LDAP might store the employee ID as numeric (`XXXXXXXXX`) but your database stores it as a textual value prepended with `members:` (ex: `members:XXXXXXXXX`). You would then set this value to `members:` and your database lookups would work.

### LDAP\_DB\_RETURN\_FAKE\_USER

[](#ldap_db_return_fake_user)

Determines whether to return an actual user instance if the user was found in the directory but not in the database.

If `true`, a user instance will be returned with LDAP attributes that can then be used to [create the user in the database](#authentication-with-provisioning).

If `false`, the authentication attempt will fail outright if the user is not in the database because `Auth::attempt()` will return `false`.

Default is `false`.

### LDAP\_OVERLAY\_DN

[](#ldap_overlay_dn)

Overlay DN to give a consistent logical root for the search, add and modify subtrees in the directory.

Default is a blank string.

**NOTE:** The environment variables of `LDAP_BASE_DN` and `LDAP_OVERLAY_DN` are incompatible. Please use either one or the other. Ideally, you would use `LDAP_OVERLAY_DN` if your LDAP server makes use of an overlay to create a logical root for multiple subtrees. Otherwise, use `LDAP_BASE_DN` for the search base.

### LDAP\_ADD\_BASE\_DN

[](#ldap_add_base_dn)

The base DN that will be used for adding objects to a subtree.

If this value is left blank, the value of `LDAP_BASE_DN` will be used instead.

Default is a blank string.

### LDAP\_ADD\_DN

[](#ldap_add_dn)

The admin DN to use when adding objects to the `LDAP_ADD_BASE_DN` subtree.

If this value is left blank, the value of `LDAP_DN` will be used instead.

Default is a blank string.

### LDAP\_ADD\_PW

[](#ldap_add_pw)

The password to use when adding objects to the `LDAP_ADD_BASE_DN` subtree.

If this value is left blank, the value of `LDAP_PASSWORD` will be used instead.

Default is a blank string.

### LDAP\_MODIFY\_METHOD

[](#ldap_modify_method)

The method that will be used for modifying objects in the subtree from the `LDAP_MODIFY_BASE_DN` value. Allowed values are `self` and `admin`.

If the value is `self` then the binding user would be able to modify his own attributes in the directory.

If the value is `admin` then the bind used would be made up of the combination of `LDAP_MODIFY_DN` and `LDAP_MODIFY_PW`.

Default is `self`.

### LDAP\_MODIFY\_BASE\_DN

[](#ldap_modify_base_dn)

The base DN that will be used for modifying objects in a subtree. If this value is left blank, the value of `LDAP_ADD_BASE_DN` will be used instead.

Default is a blank string.

### LDAP\_MODIFY\_DN

[](#ldap_modify_dn)

The admin DN to use when modifying objects in the `LDAP_MODIFY_BASE_DN` subtree.

If this value is left blank, the value of `LDAP_ADD_DN` will be used instead.

Default is a blank string.

### LDAP\_MODIFY\_PW

[](#ldap_modify_pw)

The password to use when modifying objects in the `LDAP_MODIFY_BASE_DN` subtree.

If this value is left blank, the value of `LDAP_ADD_PW` will be used instead.

Default is a blank string.

The `HandlerLDAP` Class
-----------------------

[](#the-handlerldap-class)

The core LDAP functionality is provided by the `CSUNMetaLab\Authentication\Handlers\HandlerLDAP` class. This contains the connect, bind, and searching features used during authentication.

This class can also be used on its own to provide general LDAP searching functionality as well and give you a consistent interface to execute lookup operations.

You can return an instance of `HandlerLDAP` by executing a call to its factory class of `CSUNMetaLab\Authentication\Factories\HandlerLDAPFactory` as follows:

`$ldap = HandlerLDAPFactory::fromDefaults();`

You will now have an instance of the class loaded with the default configuration from `config/ldap.php`. If you wanted to search for someone outside of authentication purposes you could do the following, for example:

```
// this assumes the $ldap variable already holds an instance of HandlerLDAP

// you can optionally set a new base DN to use during the connection and bind
// $ldap->setBaseDN("ou=Administrators,ou=Auth,o=Organization");

// you can now connect and subsequently bind to the directory in one of two ways:
$ldap->connect(); // will use the values of LDAP_DN and LDAP_PASSWORD
//$ldap->connect($username, $password); // will use explicit credentials

// you can also set a new base DN to use prior to a search too
// $ldap->setBaseDN("ou=Managers,ou=Auth,o=Organization");

// now that you have a connection, you can perform any valid search query within
// the base DN specified in the configuration
$result = $ldap->searchByQuery("uid=manager");

// you can then retrieve the relevant attributes that you want
$name = $ldap->getAttributeFromResults($result, "displayName");
$email = $ldap->getAttributeFromResults($result, "mail");
if(!empty($name) && !empty($email)) {
  return "Manager {$name} has the email of {$email}";
}

```

The `MetaUser` Class
--------------------

[](#the-metauser-class)

This package comes with the `CSUNMetaLab\Authentication\MetaUser` class that is configured to work properly with the directory authentication methods. It also supports [masquerading as another user](#masquerading) right out of the box with zero additional configuration.

It provides baseline implementations of the methods to look-up a user by both an identifier in the database as well as the combination of identifier and "Remember Me" token. Only the `findForAuth()` method is invoked automatically upon successful authentication; the other `findForAuthToken()` method is provided for convenience if you are implementing "Remember Me" functionality in your application.

This class expects a local database table called `users` with a primary key of `user_id`. You are free to use this class directly as long as you meet those two requirements.

Creating a Custom User Class
----------------------------

[](#creating-a-custom-user-class)

It is recommended that at the minimum you create a class that extends from `CSUNMetaLab\Authentication\MetaUser` since that will give you greater control over the authentication and database functionality.

### Simple Subclass

[](#simple-subclass)

A simple subclass is the following:

```

```

This class still uses the `users` table but also defines the primary key as non auto-incrementing. In addition, it defines a `fillable` array and allows `User` instances to be created via mass-assignment.

It still, however, relies on the implementations of `findForAuth()` and `findForAuthToken()` that are present in the `MetaUser` class.

### Comprehensive Subclass

[](#comprehensive-subclass)

**IMPORTANT:** If the primary key for your model is anything other than `user_id` you need to implement a comprehensive subclass, specifically the `findForAuth()` and `findForAuthToken()` methods. The `$identifier` parameter will be the value of the primary key for the model instance when authentication checks are performed (such as when the `auth` middleware is used). Otherwise, your initial login will work but the session values will be incorrect so no subsequent login checks on the next request will go through.

A more comprehensive subclass could be the following:

```

```

A couple of additional things are happening in this subclass:

1. Both the table and primary keys have been changed to use custom values
2. The two post-authentication methods have been overridden to perform status checks to ensure only active users are allowed to use the application

Authenticating
--------------

[](#authenticating)

Authenticating with either the `MetaUser` or your custom subclass works just like regular database authentication in Laravel.

This package makes a distinction between whether a user exists only in the directory or in both the directory and the database.

### Authentication Only

[](#authentication-only)

#### Without Returning a Fake User Instance

[](#without-returning-a-fake-user-instance)

If `LDAP_DB_RETURN_FAKE_USER` is set to `false`, you could invoke `Auth::attempt()` in the following way:

```
$creds = ['username' => 'admin', 'password' => '123'];

if(Auth::attempt($creds)) {
  // valid user in the directory and the database, so proceed into the application!
  redirect('home');
}
else
{
  // not a valid user (either in the directory or the database) so return back
  // to the login page with an error
  redirect('login')->withErrors([
    'Invalid username or password'
  ]);
}

```

#### With Returning a Fake User Instance

[](#with-returning-a-fake-user-instance)

If `LDAP_DB_RETURN_FAKE_USER` is set to `true`, you could invoke `Auth::attempt()` in the following way:

```
$creds = ['username' => 'admin', 'password' => '123'];

if(Auth::attempt($creds)) {
  // valid user in the directory, so let's check to see whether the user is
  // valid within the database too
  if(Auth::user()->isValid) {
    // user also exists within the database, so proceed into the application!
    redirect('home');
  }
  else
  {
    // user does not exist within the database, so go ahead and return back
    // to the login screen with an error
    Auth::logout();
    redirect('login')->withErrors([
      'Local user record could not be found'
    ]);
  }
}
else
{
  // not a valid user in the directory, so go ahead and return back to the
  // login screen with an error
  redirect('login')->withErrors([
    'Invalid username or password'
  ]);
}

```

### Authentication with Provisioning

[](#authentication-with-provisioning)

**NOTE:** Authentication with provisioning only functions if `LDAP_DB_RETURN_FAKE_USER` has been set to `true`.

Because a distinction is made between valid directory and valid database users, you have the option of provisioning the user in your local database if he exists within the directory but not yet within the database.

The user instance represented by `Auth::user()` also gets an array of attributes back from LDAP. This array can be accessed as `searchAttributes`. It contains the following key/value pairs:

- `uid` (matches the value of search attribute `LDAP_SEARCH_USERNAME`)
- `user_id` (matches the value of search attribute `LDAP_SEARCH_USER_ID`)
- `first_name` (matches the value of `givenName`)
- `last_name` (matches the value of `sn`)
- `display_name` (matches the value of `display_name`)
- `email` (matches the value of `LDAP_SEARCH_MAIL`)

You can now change your authentication procedure from above to be the following:

```
$creds = ['username' => 'admin', 'password' => '123'];

if(Auth::attempt($creds)) {
  // valid user in the directory, so let's check to see whether the user is
  // valid within the database too
  if(Auth::user()->isValid) {
    // user also exists within the database, so proceed into the application!
    redirect('home');
  }
  else
  {
    // user does not exist within the database, so go ahead and provision the
    // record and perform an automatic login; we are assuming the user instance
    // uses a model called User here
    $attrs = Auth::user()->searchAttributes;
    $user = User::create([
      'user_id' => $attrs['user_id'],
      'first_name' => $attrs['first_name'],
      'last_name' => $attrs['last_name'],
      'display_name' => $attrs['display_name'],
      'email' => $attrs['email'];
    ]);

    // perform the automatic login and the redirect
    Auth::login($user);
    redirect('home');
  }
}
else
{
  // not a valid user in the directory, so go ahead and return back to the
  // login screen with an error
  redirect('login')->withErrors([
    'Invalid username or password'
  ]);
}

```

Masquerading
------------

[](#masquerading)

This package also supports the ability for the logged-in user to become another user out of the box. This is especially useful in situations where an admin-level user may need to enter another user's account in order to triage and solve a problem directly.

### Become Another User

[](#become-another-user)

In order to become another user, it's as simple as finding the other user and then switching the logged-in user. The previous user is maintained in the session so switching back can be seamless.

```
// findOrFail is used here with a custom User instance but you can use any
// subclass of MetaUser that you would like or MetaUser itself
$switchUser = User::findOrFail('employee');

if(Auth::user()->masqueradeAsUser($switchUser)) {
  // successfully masquerading!
}
else
{
  // masquerade attempt failed
}

```

### Am I Masquerading?

[](#am-i-masquerading)

It may be useful to determine whether the user reported by `Auth::user()` is actually a masqueraded user:

```
if(Auth::user()->isMasquerading()) {
  // I am acting as someone else
}
else
{
  // it's the original logged-in user
}

```

You can also retrieve the instance of the masquerading user (the original user that logged-in) in the following way:

```
if(Auth::user()->isMasquerading()) {
  $originalUser = Auth::user()->getMasqueradingUser();
  return "This account is really " . $originalUser->display_name;
}
else
{
  // not masquerading
  return "Not masquerading";
}

```

### Stop Masquerading

[](#stop-masquerading)

Finally, it's simple to stop masquerading and return to your original user account.

```
if(Auth::user()->stopMasquerading()) {
  // I have returned to my original user account
}
else
{
  // this account was not masquerading
}

```

Calls to `Auth::user()` will now once again report the original logged-in user.

Adding New LDAP Records
-----------------------

[](#adding-new-ldap-records)

This package will attempt to use the information configured in the following three `.env` values first when performing add operations:

- `LDAP_ADD_BASE_DN`: the subtree where new entries will be added. If this is left empty, the value of `LDAP_BASE_DN` will be used instead.
- `LDAP_ADD_DN`: the admin DN to use when adding entries. If this is left empty, the value of `LDAP_DN` will be used instead.
- `LDAP_ADD_PW`: the admin password to use when adding entries. If this is left empty, the value of `LDAP_PASSWORD` will be used instead.

You can add new records to an LDAP subtree using the `HandlerLDAP` class:

```
use CSUNMetaLab\Authentication\Factories\HandlerLDAPFactory;
use CSUNMetaLab\Authentication\Factories\LDAPPasswordFactory;

public function addNewObject() {
  $name = "New User";
  $email = "newuser@example.com";
  $pw = "1234";

  $pwhash = LDAPPasswordFactory::SSHA($pw); // SSHA hash
  $uid = 'ex_' . bin2hex(random_bytes(4)); // random UID

  // retrieve a new HandlerLDAP instance and connect to the configured
  // host
  $ldap = HandlerLDAPFactory::fromDefaults();
  $ldap->connect();

  // set up the attributes to be added to the new record
  $nameArr = explode(" ", $name);
  $attrs = [
    'objectClass' => 'inetOrgPerson',
    'uid' => $uid,
    'mail' => $email,
    'displayName' => $name,
    'cn' => $name,
    'sn' => (!empty($nameArr[1]) ? $nameArr[1] : "Example"),
    'givenName' => $nameArr[0],
    'userPassword' => $pwhash,
  ];

  // add the object to the add subtree
  $success = $ldap->addObject($uid, $attrs);
  if($success) {
    return "Successfully registered account {$name}! UID: {$uid}";
  }

  return "Could not register {$name}. UID: {$uid}. Please try again";
}

```

Modifying Existing LDAP Records
-------------------------------

[](#modifying-existing-ldap-records)

This package will attempt to use the information configured in the following four `.env` values first when performing modify operations:

- `LDAP_MODIFY_METHOD`: if `self`, then a user can bind as himself and modify his own attributes. If `admin` then the value of `LDAP_MODIFY_DN` and `LDAP_MODIFY_PW` will be used when performing the modification bind.
- `LDAP_MODIFY_BASE_DN`: the subtree where entries will be modified. If this is left empty, the value of `LDAP_ADD_BASE_DN` will be used instead.
- `LDAP_MODIFY_DN`: the admin DN to use when modifying entries. If this is left empty, the value of `LDAP_ADD_DN` will be used instead.
- `LDAP_MODIFY_PW`: the admin password to use when modifying entries. If this is left empty, the value of `LDAP_ADD_PW` will be used instead.

You can modify existing records in an LDAP subtree using the `HandlerLDAP` class:

```
use CSUNMetaLab\Authentication\Factories\HandlerLDAPFactory;
use CSUNMetaLab\Authentication\Factories\LDAPPasswordFactory;

public function modifyObject() {
  // this lets a logged-in user modify their own attributes due to the bind
  // as "self" as opposed to the LDAP_MODIFY_DN and LDAP_MODIFY_PW values
  // from the .env file
  $cur_pw = "1234";

  $email = "newuser@example.com";
  $newName = "Different Name";
  $newNameArr = explode(" ", $newName);

  // retrieve a new HandlerLDAP instance and connect to the configured
  // host
  $ldap = HandlerLDAPFactory::fromDefaults();
  $ldap->connect();

  // get the matching object for the logged-in user and resolve its DN
  $obj = $ldap->searchByAuth($email);
  $dn = $ldap->getAttributeFromResults($obj, 'dn');

  // modification method of "self": make sure the user has the correct
  // password by performing another bind; this will not be executed if
  // the admin modify DN and password are being used instead
  if(config('ldap.modify_method') == "self") {
    $ldap->connectByDN($dn, $cur_pw);
  }

  // set a new name for the user
  $success = $ldap->modifyObject($dn, [
    'displayName' => $newName,
    'cn' => $newName,
    'givenName' => $newNameArr[0],
    'sn' => $newNameArr[1],
  ]);

  if($success) {
    return "Successfully changed the name for {$email}! DN: {$dn}";
  }

  return "Could not change the name for {$email}. DN: {$dn}";
}

```

Modifying LDAP User Passwords
-----------------------------

[](#modifying-ldap-user-passwords)

While you can perform a `modifyObject()` with the `userPassword` attribute and follow similar steps as those in [Modifying Existing LDAP Records](#modifying-existing-ldap-records), the `HandlerLDAP` class also provides a convenience method for changing user passwords.

The password will be generated as a SSHA hash using a cryptographically-secure salt based on the output of `openssl_random_pseudo_bytes()` using a four-byte string:

```
public function modifyUserPassword() {
  // this lets a logged-in user modify their own attributes due to the bind
  // as "self" as opposed to the LDAP_MODIFY_DN and LDAP_MODIFY_PW values
  // from the .env file
  $cur_pw = "1234";

  $email = "newuser@example.com";
  $new_pw = "2345";

  // retrieve a new HandlerLDAP instance and connect to the configured
  // host
  $ldap = HandlerLDAPFactory::fromDefaults();
  $ldap->connect();

  // get the matching object for the logged-in user and resolve its DN
  $obj = $ldap->searchByAuth($email);
  $dn = $ldap->getAttributeFromResults($obj, 'dn');

  // modification method of "self": make sure the user has the correct
  // password by performing another bind; this will not be executed if
  // the admin modify DN and password are being used instead
  if(config('ldap.modify_method') == "self") {
    $ldap->connectByDN($dn, $cur_pw);
  }

  // set a new password for the user
  $success = $ldap->modifyObjectPassword($dn, $new_pw);

  if($success) {
    return "Successfully changed the password for {$email}! DN: {$dn}";
  }

  return "Could not change the password for {$email}. DN: {$dn}";
}

```

###  Health Score

41

—

FairBetter than 87% of packages

Maintenance57

Moderate activity, may be stable

Popularity18

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity65

Established project with proven stability

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~302 days

Recently: every ~696 days

Total

11

Last Release

283d ago

Major Versions

1.6.0 → v2.0.02025-09-17

PHP version history (2 changes)1.0.0PHP &gt;=5.5.9

v2.0.0PHP &gt;=7.1

### Community

Maintainers

![](https://www.gravatar.com/avatar/ef2f088dbe515e7505204053ba4b89fab631db23d7638297853dc697adf7ddc4?d=identicon)[matthewfritz](/maintainers/matthewfritz)

![](https://www.gravatar.com/avatar/5c86fd91fdf698dd5c9ceffd3dce175a6ae3000d00f4c00bf65b2e97f19072a1?d=identicon)[csun-metalab](/maintainers/csun-metalab)

![](https://www.gravatar.com/avatar/eb2e4b7e97c47122102e9eca3a2707f31d812f27d774197f62f27f130d128e49?d=identicon)[luisjg](/maintainers/luisjg)

---

Top Contributors

[![matthewfritz](https://avatars.githubusercontent.com/u/1715181?v=4)](https://github.com/matthewfritz "matthewfritz (61 commits)")

### Embed Badge

![Health badge](/badges/csun-metalab-laravel-directory-authentication/health.svg)

```
[![Health](https://phpackages.com/badges/csun-metalab-laravel-directory-authentication/health.svg)](https://phpackages.com/packages/csun-metalab-laravel-directory-authentication)
```

###  Alternatives

[kartik-v/yii2-password

Useful password strength validation utilities for Yii Framework 2.0

761.2M17](/packages/kartik-v-yii2-password)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
