Every organization using LDAP authentication eventually faces the same challenge: users forgetting passwords and overwhelming IT support. The standard workflow we've all implemented (or suffered through) follows this pattern:
1. User submits username (e.g., jdoe)
2. System sends reset link to jdoe@company.com
3. User clicks link and sets new password
After extensive research, here are the most viable FOSS options currently maintained:
- LAM (LDAP Account Manager) - Includes password self-service module
- Self Service Password - PHP-based solution supporting multiple backends
- LLDAP - Lightweight LDAP server with web interface including password reset
Here's a basic Docker deployment example for the most popular option:
version: '3'
services:
self-service-password:
image: ltbproject/self-service-password
ports:
- "8080:80"
environment:
- LDAP_URI=ldap://ldap.example.com
- LDAP_BASE_DN=dc=example,dc=com
- LDAP_ADMIN_DN=cn=admin,dc=example,dc=com
- LDAP_ADMIN_PASSWORD=secret
- MAIL_FROM=no-reply@example.com
When implementing any password reset solution, these security measures are essential:
// Token generation example (PHP)
$token = bin2hex(random_bytes(32));
$expires = time() + 3600; // 1 hour expiration
// Store in database with:
// - username
// - hashed token (use password_hash())
// - expiration timestamp
For organizations needing a tailored solution, here's a Python Flask blueprint:
from flask import Flask, request
import ldap3
app = Flask(__name__)
@app.route('/reset', methods=['POST'])
def request_reset():
username = request.form['username']
# Validate user exists in LDAP
# Generate and store token
# Send email
return "Reset link sent"
@app.route('/reset/', methods=['GET', 'POST'])
def perform_reset(token):
if request.method == 'POST':
new_password = request.form['password']
# Verify token validity
# Update LDAP password
return "Password updated"
return "<form>...</form>"
Every organization using LDAP directories eventually hits the same pain point - how to enable secure password resets without creating helpdesk tickets. The manual process becomes unsustainable once you exceed about 50 users.
While many teams build custom solutions (usually PHP/Python scripts), these often lack:
- Proper security audits
- Multi-LDAP backend support
- Configurable password policies
- Modern web UI components
After testing multiple solutions, these stand out:
1. Self Service Password (PHP)
Feature-rich solution supporting:
// Sample config snippet
$ldap_url = "ldaps://ldap.example.com";
$ldap_binddn = "cn=admin,dc=example,dc=com";
$ldap_bindpw = "secret";
$ldap_base = "ou=people,dc=example,dc=com";
2. LTSP Password Reset (Python/Flask)
Modern alternative with REST API:
@app.route('/api/v1/reset', methods=['POST'])
def initiate_reset():
username = request.json.get('username')
if not ldap_user_exists(username):
return jsonify({"error": "Invalid user"}), 404
When implementing any solution, ensure:
- Rate limiting on reset attempts
- Secure token generation (use secrets module)
- LDAPS/TLS mandatory
- Password complexity enforcement
For teams needing custom solutions, here's the core workflow:
def generate_reset_token(username):
token = secrets.token_urlsafe(32)
redis.setex(f"reset:{token}", 3600, username)
send_email(
to=get_ldap_email(username),
subject="Password Reset",
body=f"Click here: {BASE_URL}/reset?token={token}"
)