Implementing a Secure Web Interface for Active Directory Password Self-Service Updates


7 views

As organizations transition from Windows-centric to web-based application ecosystems, traditional Active Directory password management methods become problematic. The classic CTRL+ALT+DEL password change workflow doesn't serve users who primarily access web apps. We need a secure, web-based solution that integrates with AD without exposing sensitive directory services.

Three main technical approaches exist for web-based AD password changes:

  • LDAPS (LDAP over SSL) direct binding
  • Active Directory Web Services (ADWS)
  • Microsoft Graph API (for Azure AD hybrid environments)

Here's a basic PHP implementation using LDAPS:


<?php
// AD Password Change via LDAPS
function changeADPassword($username, $oldPassword, $newPassword) {
    $ldap_host = "ldaps://yourdomaincontroller:636";
    $ldap_dn = "CN=Users,DC=yourdomain,DC=com";
    
    // First validate current credentials
    $ldap_conn = ldap_connect($ldap_host);
    ldap_set_option($ldap_conn, LDAP_OPT_PROTOCOL_VERSION, 3);
    
    if (@ldap_bind($ldap_conn, "$username@yourdomain.com", $oldPassword)) {
        // Search for user DN
        $search = ldap_search($ldap_conn, $ldap_dn, "(sAMAccountName=$username)");
        $entries = ldap_get_entries($ldap_conn, $search);
        
        if ($entries["count"] > 0) {
            $user_dn = $entries[0]["dn"];
            
            // Prepare password change
            $entry = array();
            $entry["unicodePwd"] = iconv("UTF-8", "UTF-16LE", '"' . $newPassword . '"');
            
            // Modify password
            if (ldap_mod_replace($ldap_conn, $user_dn, $entry)) {
                ldap_unbind($ldap_conn);
                return true;
            }
        }
    }
    
    ldap_unbind($ldap_conn);
    return false;
}
?>
  • Always use SSL/TLS (LDAPS on port 636)
  • Implement strong password complexity validation matching AD policies
  • Add rate limiting to prevent brute force attempts
  • Consider multi-factor authentication for the password change process
  • Log all password change attempts (without storing passwords)

For Windows Server environments, Active Directory Web Services provides a more modern approach:


# PowerShell script for password reset via ADWS
$credential = Get-Credential
$newPassword = Read-Host -AsSecureString "Enter new password"

try {
    $session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri "https://yourdomaincontroller/PowerShell" -Authentication Kerberos -Credential $credential
    
    Invoke-Command -Session $session -ScriptBlock {
        param($username, $newPassword)
        Set-ADAccountPassword -Identity $username -NewPassword $newPassword -Reset
    } -ArgumentList $credential.UserName, $newPassword
    
    Write-Host "Password changed successfully"
} catch {
    Write-Host "Error changing password: $_"
} finally {
    if ($session) { Remove-PSSession $session }
}

When designing the web interface:

  • Clearly indicate password complexity requirements
  • Show password strength meter
  • Include confirmation field for new password
  • Provide immediate feedback on success/failure
  • Offer password recovery options if the old password is forgotten

As organizations migrate toward web-based authentication while maintaining Active Directory (AD) as their identity provider, legacy password change methods (CTRL+ALT+DEL) become impractical. Many modern users access AD-authenticated web apps exclusively through Mac/Linux devices or mobile platforms where native AD password change mechanisms don't exist.

A proper solution must:

  • Authenticate users via LDAP/S before allowing changes
  • Enforce AD password complexity rules programmatically
  • Handle SSL/TLS encryption for all communications
  • Integrate with existing AD infrastructure (2008R2+)

Option 1: IIS with AD DS Service Account

This Windows-native approach uses IIS with ASP.NET Core:


// Configure in Startup.cs
services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
    .AddNegotiate();

// Password change controller
[Authorize]
public class PasswordController : Controller {
    [HttpPost]
    public IActionResult Change([FromBody] PasswordChangeModel model) {
        using (var context = new PrincipalContext(ContextType.Domain)) {
            using (var user = UserPrincipal.FindByIdentity(context, 
                   User.Identity.Name)) {
                user.ChangePassword(model.OldPassword, model.NewPassword);
                user.Save();
            }
        }
        return Ok();
    }
}

Option 2: Cross-Platform PHP/LDAP Solution

For non-Windows environments:


<?php
function changeADPassword($user, $oldPass, $newPass) {
    $ldap = ldap_connect("ldaps://dc.example.com");
    ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
    
    if (@ldap_bind($ldap, "$user@domain.com", $oldPass)) {
        $entry = array();
        $entry["unicodePwd"] = iconv("UTF-8", "UTF-16LE", 
            "\"" . $newPass . "\"");
        
        $dn = "CN=" . ldap_escape($user) . ",OU=Users,DC=domain,DC=com";
        if (ldap_mod_replace($ldap, $dn, $entry)) {
            return true;
        }
    }
    return false;
}
?>

Critical security measures:

  • Implement rate limiting (max 5 attempts/hour)
  • Set HTTP Strict Transport Security headers
  • Validate new passwords against AD complexity requirements client-side
  • Log all change attempts (without storing passwords)

The interface should:

  • Show real-time password strength feedback
  • Include a "password reveal" toggle option
  • Provide clear error messages when AD policies are violated
  • Offer password expiration notifications (query AD's pwdLastSet)

For organizations not wanting custom development:

  • Microsoft's official Self-Service Password Reset (requires Azure AD)
  • Third-party tools like ManageEngine ADSelfService Plus
  • Open-source solutions like LTB Self Service Password