# TISBackup Authentication Module Pluggable authentication system for Flask routes. ## Features - **Multiple providers**: Basic Auth, Flask-Login, OAuth2 - **Easy integration**: Simple decorator-based protection - **Configurable**: INI-based configuration - **Secure**: bcrypt password hashing, OAuth integration - **Extensible**: Easy to add new providers ## Quick Start ### 1. Choose Authentication Provider ```python from libtisbackup.auth import get_auth_provider # Get provider from config auth = get_auth_provider("basic", { "username": "admin", "password": "$2b$12$...", # bcrypt hash "use_bcrypt": True }) # Initialize with Flask app auth.init_app(app) ``` ### 2. Protect Routes ```python @app.route("/") @auth.require_auth def index(): user = auth.get_current_user() return f"Hello {user['username']}" ``` ## Providers ### Base Provider (No Auth) ```python auth = get_auth_provider("none", {}) ``` - No authentication required - All routes publicly accessible - Useful for development/testing ### Basic Auth ```python auth = get_auth_provider("basic", { "username": "admin", "password": "$2b$12$LQv3c1yqBWVHxkd0LHAkCOYz6TtxMQJqhN8/LewY5GyYWv.5qVQK6", "use_bcrypt": True, "realm": "TISBackup" }) ``` **Features:** - HTTP Basic Authentication - bcrypt password hashing - Custom realm support ### Flask-Login ```python auth = get_auth_provider("flask-login", { "users_file": "/etc/tis/users.txt", "use_bcrypt": True, "login_view": "login" }) ``` **Features:** - Session-based authentication - Multiple users support - Login/logout pages - bcrypt password hashing **User file format** (`users.txt`): ``` username:bcrypt_hash admin:$2b$12$LQv3c1yqBWVHxkd0LHAkCOYz6TtxMQJqhN8/LewY5GyYWv.5qVQK6 ``` ### OAuth2 ```python auth = get_auth_provider("oauth", { "provider": "google", # or "github", "gitlab", "generic" "client_id": "your-client-id", "client_secret": "your-client-secret", "redirect_uri": "http://localhost:8080/oauth/callback", "authorized_domains": ["example.com"], "authorized_users": ["admin@example.com"] }) ``` **Features:** - OAuth2 authentication - Google, GitHub, GitLab support - Custom OAuth providers - Domain/user restrictions ## API Reference ### AuthProvider Base class for all auth providers. #### Methods - `init_app(app)` - Initialize with Flask app - `require_auth(f)` - Decorator to protect routes - `is_authenticated()` - Check if current request is authenticated - `get_current_user()` - Get current user info - `handle_unauthorized()` - Handle unauthorized access - `logout()` - Logout current user ### BasicAuthProvider HTTP Basic Authentication provider. #### Configuration ```python { "username": str, # Required "password": str, # Required (plain or bcrypt hash) "use_bcrypt": bool, # Default: False "realm": str # Default: "TISBackup" } ``` ### FlaskLoginProvider Session-based authentication provider. #### Configuration ```python { "users": dict, # {username: password_hash} or... "users_file": str, # Path to users file "use_bcrypt": bool, # Default: True "login_view": str # Default: "login" } ``` #### Methods - `verify_password(username, password)` - Verify credentials - `login_user(username)` - Login user by username ### OAuthProvider OAuth2 authentication provider. #### Configuration ```python { "provider": str, # "google", "github", "gitlab", "generic" "client_id": str, # Required "client_secret": str, # Required "redirect_uri": str, # Required "scopes": list, # Optional "authorized_domains": list, # Optional "authorized_users": list, # Optional # For generic provider: "authorization_endpoint": str, "token_endpoint": str, "userinfo_endpoint": str } ``` #### Methods - `is_user_authorized(user_info)` - Check if user is authorized ## Integration Example See [example_integration.py](example_integration.py) for a complete example. ### Minimal Example ```python from flask import Flask from libtisbackup.auth import get_auth_provider app = Flask(__name__) app.secret_key = "your-secret-key" # Initialize auth auth = get_auth_provider("basic", { "username": "admin", "password": "changeme", "use_bcrypt": False }) auth.init_app(app) # Protected route @app.route("/") @auth.require_auth def index(): return "Protected content" # Public route @app.route("/health") def health(): return "OK" ``` ### With Flask-Login ```python auth = get_auth_provider("flask-login", { "users": { "admin": "$2b$12$..." }, "use_bcrypt": True }) auth.init_app(app) @app.route("/login", methods=["POST"]) def login(): username = request.form["username"] password = request.form["password"] if auth.verify_password(username, password): auth.login_user(username) return redirect("/") return "Invalid credentials", 401 @app.route("/") @auth.require_auth def index(): user = auth.get_current_user() return f"Hello {user['username']}" ``` ### With OAuth ```python auth = get_auth_provider("oauth", { "provider": "google", "client_id": "...", "client_secret": "...", "redirect_uri": "http://localhost:8080/oauth/callback", "authorized_domains": ["example.com"] }) auth.init_app(app) @app.route("/oauth/login") def oauth_login(): return auth.oauth_client.authorize_redirect( url_for("oauth_callback", _external=True) ) @app.route("/oauth/callback") def oauth_callback(): token = auth.oauth_client.authorize_access_token() user_info = auth.oauth_client.get(auth.userinfo_endpoint).json() if auth.is_user_authorized(user_info): session["oauth_user"] = user_info return redirect("/") return "Unauthorized", 403 ``` ## Security Considerations 1. **Always use HTTPS in production** - Especially for Basic Auth 2. **Use bcrypt for passwords** - Never store plain text passwords 3. **Rotate credentials regularly** - Change passwords and OAuth secrets 4. **Restrict OAuth access** - Use `authorized_domains` or `authorized_users` 5. **Set strong Flask secret_key** - Use `secrets.token_hex(32)` 6. **Protect config files** - `chmod 600` for files with credentials 7. **Use environment variables** - For sensitive configuration values ## Testing ```python import unittest from libtisbackup.auth import get_auth_provider class TestBasicAuth(unittest.TestCase): def test_authentication(self): auth = get_auth_provider("basic", { "username": "admin", "password": "test", "use_bcrypt": False }) # Mock request with credentials # Test authentication logic pass ``` ## License GPL v3.0 - Same as TISBackup