Files
TISbackup/libtisbackup/auth/basic_auth.py
T

79 lines
2.5 KiB
Python
Raw Normal View History

#!/usr/bin/python3
# -*- coding: utf-8 -*-
"""
HTTP Basic Authentication provider
"""
import base64
import logging
from functools import wraps
from flask import request
from .base import AuthProvider
class BasicAuthProvider(AuthProvider):
"""HTTP Basic Authentication provider.
Configuration:
username: Required username
password: Required password (plain text, or hashed with bcrypt)
realm: Authentication realm (default: 'TISBackup')
use_bcrypt: If True, password is bcrypt hash (default: False)
"""
def __init__(self, config):
super().__init__(config)
self.logger = logging.getLogger("tisbackup.auth")
self.username = config.get("username")
self.password = config.get("password")
self.realm = config.get("realm", "TISBackup")
self.use_bcrypt = config.get("use_bcrypt", False)
if not self.username or not self.password:
raise ValueError("BasicAuth requires 'username' and 'password' in config")
if self.use_bcrypt:
try:
import bcrypt
self.bcrypt = bcrypt
except ImportError:
raise ImportError("bcrypt library required for password hashing. Install with: pip install bcrypt")
def is_authenticated(self):
"""Check if request has valid Basic Auth credentials."""
auth = request.authorization
if not auth:
return False
if auth.username != self.username:
self.logger.warning(f"Failed authentication attempt for user: {auth.username}")
return False
if self.use_bcrypt:
# Compare bcrypt hash
password_bytes = auth.password.encode('utf-8')
hash_bytes = self.password.encode('utf-8') if isinstance(self.password, str) else self.password
return self.bcrypt.checkpw(password_bytes, hash_bytes)
else:
# Plain text comparison (not recommended for production)
return auth.password == self.password
def handle_unauthorized(self):
"""Return 401 with WWW-Authenticate header."""
from flask import Response
return Response(
'Authentication required',
401,
{'WWW-Authenticate': f'Basic realm="{self.realm}"'}
)
def get_current_user(self):
"""Get current authenticated user."""
auth = request.authorization
if auth and self.is_authenticated():
return {"username": auth.username, "auth_type": "basic"}
return None