52 lines
1.5 KiB
Python
52 lines
1.5 KiB
Python
|
|
"""Authentication provider.
|
||
|
|
|
||
|
|
Replaces authprovider.js:
|
||
|
|
- check_password: plaintext and apr1 MD5 hash verification
|
||
|
|
- find_botuser: bot user lookup from config
|
||
|
|
- find_ldapuser: LDAP authentication via ldap3
|
||
|
|
- authorize: full auth pipeline entry point
|
||
|
|
"""
|
||
|
|
|
||
|
|
import logging
|
||
|
|
|
||
|
|
logger = logging.getLogger(__name__)
|
||
|
|
|
||
|
|
# Placeholder imports — implemented in Phase 4
|
||
|
|
# from . import database
|
||
|
|
# from . import memberdata
|
||
|
|
|
||
|
|
|
||
|
|
def check_password(password, hash_value):
|
||
|
|
"""Verify *password* against *hash_value*.
|
||
|
|
|
||
|
|
Supports plaintext and apr1 (MD5 crypt) formats.
|
||
|
|
Replaces Node.js apache-md5 module.
|
||
|
|
"""
|
||
|
|
# Plaintext
|
||
|
|
if not hash_value.startswith('$'):
|
||
|
|
return password == hash_value
|
||
|
|
|
||
|
|
# Parse algorithm tag: $apr1$...
|
||
|
|
try:
|
||
|
|
_, algo, _ = hash_value.split('$', 2)
|
||
|
|
except ValueError:
|
||
|
|
raise ValueError("Password hashing algorithm not selected")
|
||
|
|
|
||
|
|
if algo == 'apr1':
|
||
|
|
# TODO Phase 4: use passlib to verify apr1 hash
|
||
|
|
raise NotImplementedError("apr1 verification not yet implemented")
|
||
|
|
|
||
|
|
raise ValueError(f"Unsupported password hashing algorithm: {algo}")
|
||
|
|
|
||
|
|
|
||
|
|
def authorize(ctx):
|
||
|
|
"""Run the full authorization pipeline.
|
||
|
|
|
||
|
|
ctx is a dict with keys: config, request, response, permissions
|
||
|
|
Returns ctx augmented with: username, flags, data, query, filter, permission
|
||
|
|
"""
|
||
|
|
# TODO Phase 4: pipeline
|
||
|
|
# find_botuser -> find_ldapuser -> find_config_flags ->
|
||
|
|
# find_database_flags -> impersonate -> effective_permissions
|
||
|
|
raise NotImplementedError("Authorization pipeline not yet implemented")
|