336 lines
7.5 KiB
Markdown
336 lines
7.5 KiB
Markdown
# LDAP Docker Examples
|
|
|
|
This directory contains example scripts and applications demonstrating how to use the LDAP server for authentication and user management.
|
|
|
|
## Available Examples
|
|
|
|
### 1. Simple Authentication (`simple_auth.py`)
|
|
|
|
A Python script demonstrating basic LDAP authentication and user information retrieval.
|
|
|
|
**Features:**
|
|
- Authenticate users with username/password
|
|
- Retrieve detailed user information
|
|
- Get user group memberships
|
|
- List all users in the directory
|
|
|
|
**Usage:**
|
|
|
|
```bash
|
|
# Authenticate a user (default: jdoe)
|
|
python examples/simple_auth.py
|
|
|
|
# Authenticate with custom credentials
|
|
python examples/simple_auth.py --username jsmith --password password123
|
|
|
|
# List all users
|
|
python examples/simple_auth.py --list-users
|
|
|
|
# Use a different LDAP server
|
|
python examples/simple_auth.py --server ldaps://localhost:636
|
|
```
|
|
|
|
**Example Output:**
|
|
|
|
```
|
|
🔐 LDAP Authentication Example
|
|
Server: ldap://localhost:389
|
|
|
|
Attempting to authenticate user: jdoe
|
|
✅ Authentication successful for user: jdoe
|
|
✅ Authentication successful!
|
|
|
|
Fetching user information...
|
|
|
|
==================================================
|
|
USER INFORMATION
|
|
==================================================
|
|
Username: jdoe
|
|
Full Name: John Doe
|
|
First Name: John
|
|
Last Name: Doe
|
|
Email: jdoe@testing.local
|
|
UID Number: 10001
|
|
GID Number: 10001
|
|
DN: uid=jdoe,ou=people,dc=testing,dc=local
|
|
==================================================
|
|
|
|
Fetching user groups...
|
|
User belongs to 2 group(s):
|
|
• developers
|
|
• users
|
|
```
|
|
|
|
## Using in Your Application
|
|
|
|
### Python with ldap3
|
|
|
|
```python
|
|
from ldap3 import Server, Connection
|
|
|
|
# Connect and authenticate
|
|
server = Server('ldap://localhost:389')
|
|
conn = Connection(
|
|
server,
|
|
user='uid=jdoe,ou=people,dc=testing,dc=local',
|
|
password='password123',
|
|
auto_bind=True
|
|
)
|
|
|
|
# Search for users
|
|
conn.search(
|
|
'dc=testing,dc=local',
|
|
'(objectClass=inetOrgPerson)',
|
|
attributes=['uid', 'cn', 'mail']
|
|
)
|
|
|
|
for entry in conn.entries:
|
|
print(f"{entry.cn}: {entry.mail}")
|
|
|
|
conn.unbind()
|
|
```
|
|
|
|
### Using ldapsearch (Command Line)
|
|
|
|
```bash
|
|
# Search for a user
|
|
ldapsearch -H ldap://localhost:389 \
|
|
-D "cn=admin,dc=testing,dc=local" \
|
|
-w admin_password \
|
|
-b "dc=testing,dc=local" \
|
|
"(uid=jdoe)"
|
|
|
|
# List all users
|
|
ldapsearch -H ldap://localhost:389 \
|
|
-D "cn=admin,dc=testing,dc=local" \
|
|
-w admin_password \
|
|
-b "ou=people,dc=testing,dc=local" \
|
|
"(objectClass=inetOrgPerson)" \
|
|
uid cn mail
|
|
```
|
|
|
|
### Web Application Integration
|
|
|
|
#### Flask Example
|
|
|
|
```python
|
|
from flask import Flask, request, jsonify
|
|
from ldap3 import Server, Connection
|
|
|
|
app = Flask(__name__)
|
|
|
|
@app.route('/login', methods=['POST'])
|
|
def login():
|
|
username = request.json.get('username')
|
|
password = request.json.get('password')
|
|
|
|
server = Server('ldap://localhost:389')
|
|
user_dn = f'uid={username},ou=people,dc=testing,dc=local'
|
|
|
|
try:
|
|
conn = Connection(server, user=user_dn, password=password)
|
|
if conn.bind():
|
|
return jsonify({'status': 'success', 'message': 'Authenticated'})
|
|
else:
|
|
return jsonify({'status': 'error', 'message': 'Invalid credentials'}), 401
|
|
except:
|
|
return jsonify({'status': 'error', 'message': 'Authentication failed'}), 401
|
|
```
|
|
|
|
#### Django Example
|
|
|
|
```python
|
|
# settings.py
|
|
import ldap
|
|
from django_auth_ldap.config import LDAPSearch
|
|
|
|
AUTH_LDAP_SERVER_URI = "ldap://localhost:389"
|
|
AUTH_LDAP_BIND_DN = "cn=admin,dc=testing,dc=local"
|
|
AUTH_LDAP_BIND_PASSWORD = "admin_password"
|
|
AUTH_LDAP_USER_SEARCH = LDAPSearch(
|
|
"ou=people,dc=testing,dc=local",
|
|
ldap.SCOPE_SUBTREE,
|
|
"(uid=%(user)s)"
|
|
)
|
|
|
|
AUTHENTICATION_BACKENDS = [
|
|
'django_auth_ldap.backend.LDAPBackend',
|
|
'django.contrib.auth.backends.ModelBackend',
|
|
]
|
|
```
|
|
|
|
## Common Integration Patterns
|
|
|
|
### 1. Simple Bind Authentication
|
|
|
|
The most straightforward approach - try to bind with user credentials:
|
|
|
|
```python
|
|
def authenticate_user(username, password):
|
|
server = Server('ldap://localhost:389')
|
|
user_dn = f'uid={username},ou=people,dc=testing,dc=local'
|
|
conn = Connection(server, user=user_dn, password=password)
|
|
return conn.bind()
|
|
```
|
|
|
|
### 2. Search and Bind
|
|
|
|
Search for the user first, then authenticate:
|
|
|
|
```python
|
|
def authenticate_user(username, password):
|
|
# First, search for the user with admin credentials
|
|
server = Server('ldap://localhost:389')
|
|
admin_conn = Connection(
|
|
server,
|
|
user='cn=admin,dc=testing,dc=local',
|
|
password='admin_password',
|
|
auto_bind=True
|
|
)
|
|
|
|
admin_conn.search(
|
|
'ou=people,dc=testing,dc=local',
|
|
f'(uid={username})',
|
|
attributes=['dn']
|
|
)
|
|
|
|
if not admin_conn.entries:
|
|
return False
|
|
|
|
user_dn = admin_conn.entries[0].entry_dn
|
|
admin_conn.unbind()
|
|
|
|
# Now authenticate as the user
|
|
user_conn = Connection(server, user=user_dn, password=password)
|
|
return user_conn.bind()
|
|
```
|
|
|
|
### 3. Group-Based Authorization
|
|
|
|
Check if user belongs to specific groups:
|
|
|
|
```python
|
|
def user_has_role(username, required_group):
|
|
server = Server('ldap://localhost:389')
|
|
conn = Connection(
|
|
server,
|
|
user='cn=admin,dc=testing,dc=local',
|
|
password='admin_password',
|
|
auto_bind=True
|
|
)
|
|
|
|
user_dn = f'uid={username},ou=people,dc=testing,dc=local'
|
|
|
|
conn.search(
|
|
'ou=groups,dc=testing,dc=local',
|
|
f'(&(objectClass=groupOfNames)(member={user_dn})(cn={required_group}))',
|
|
attributes=['cn']
|
|
)
|
|
|
|
return len(conn.entries) > 0
|
|
```
|
|
|
|
## Testing Your Integration
|
|
|
|
### 1. Start the LDAP Server
|
|
|
|
```bash
|
|
make start
|
|
```
|
|
|
|
### 2. Test Connection
|
|
|
|
```bash
|
|
python examples/simple_auth.py --list-users
|
|
```
|
|
|
|
### 3. Test Authentication
|
|
|
|
```bash
|
|
python examples/simple_auth.py --username jdoe --password password123
|
|
```
|
|
|
|
### 4. Test with Your Application
|
|
|
|
Point your application to:
|
|
- LDAP URL: `ldap://localhost:389`
|
|
- LDAPS URL: `ldaps://localhost:636` (with SSL)
|
|
- Base DN: `dc=testing,dc=local`
|
|
|
|
## Available Test Accounts
|
|
|
|
| Username | Password | Groups | Purpose |
|
|
|----------|----------|--------|---------|
|
|
| admin | password123 | admins | Administrative testing |
|
|
| jdoe | password123 | developers, users | Regular user testing |
|
|
| jsmith | password123 | developers, users | Regular user testing |
|
|
| testuser | password123 | users | Basic user testing |
|
|
|
|
## SSL/TLS Configuration
|
|
|
|
For production-like testing with LDAPS:
|
|
|
|
```python
|
|
import ssl
|
|
from ldap3 import Server, Connection, Tls
|
|
|
|
tls = Tls(
|
|
ca_certs_file='certs/ca.crt',
|
|
validate=ssl.CERT_REQUIRED
|
|
)
|
|
|
|
server = Server('ldaps://localhost:636', use_ssl=True, tls=tls)
|
|
conn = Connection(server, user=user_dn, password=password, auto_bind=True)
|
|
```
|
|
|
|
## Troubleshooting
|
|
|
|
### Connection Refused
|
|
|
|
```bash
|
|
# Check if LDAP server is running
|
|
make status
|
|
|
|
# Start if not running
|
|
make start
|
|
```
|
|
|
|
### Authentication Fails
|
|
|
|
```bash
|
|
# Verify user exists
|
|
make test-users
|
|
|
|
# Check LDAP logs
|
|
make logs
|
|
```
|
|
|
|
### Python ImportError
|
|
|
|
```bash
|
|
# Install ldap3 library
|
|
uv pip install ldap3
|
|
# or
|
|
pip install ldap3
|
|
```
|
|
|
|
## Additional Resources
|
|
|
|
- [ldap3 Documentation](https://ldap3.readthedocs.io/)
|
|
- [LDAP Protocol Overview](https://ldap.com/ldap-protocol/)
|
|
- [Django LDAP Authentication](https://django-auth-ldap.readthedocs.io/)
|
|
- [Flask-LDAP3-Login](https://flask-ldap3-login.readthedocs.io/)
|
|
|
|
## Contributing Examples
|
|
|
|
Have an example for a specific framework or use case? Contributions are welcome!
|
|
|
|
Examples we'd love to see:
|
|
- Express.js / Node.js authentication
|
|
- Ruby on Rails integration
|
|
- Go LDAP client
|
|
- Java Spring Security LDAP
|
|
- PHP authentication
|
|
- Docker Compose with application stack
|
|
|
|
Submit a pull request with your example! |