TISbackup/AUTHENTICATION.md
k3nny 38a0d788d4
Some checks are pending
lint / docker (push) Waiting to run
feat(auth): install all authentication providers by default
All authentication methods (Basic Auth, Flask-Login, OAuth) are now
installed as core dependencies instead of optional extras. This
simplifies setup and eliminates the need to run `uv sync --extra auth-*`
when switching between authentication methods.

Changes:
- Move authlib, bcrypt, and flask-login to core dependencies
- Remove auth-* optional dependency groups from pyproject.toml
- Update documentation to remove installation instructions
- Simplify troubleshooting and migration guides

Benefits:
- No import errors when switching auth methods
- Simpler user experience
- All providers available out of the box

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-05 21:17:30 +02:00

9.1 KiB

TISBackup Authentication System

TISBackup provides a pluggable authentication system for securing the Flask web interface. You can choose between multiple authentication methods based on your security requirements.

Supported Authentication Methods

  1. None - No authentication (default, NOT recommended for production)
  2. Basic Auth - HTTP Basic Authentication with username/password
  3. Flask-Login - Session-based authentication with username/password
  4. OAuth2 - OAuth authentication (Google, GitHub, GitLab, or generic provider)

Quick Start

1. Choose Authentication Method

Add an [authentication] section to /etc/tis/tisbackup_gui.ini:

[authentication]
type = basic
username = admin
password = $2b$12$LQv3c1yqBWVHxkd0LHAkCOYz6TtxMQJqhN8/LewY5GyYWv.5qVQK6
use_bcrypt = True

2. Restart TISBackup

docker compose restart tisbackup_gui

Configuration Guide

Basic Authentication

Simple HTTP Basic Auth with username and password.

Pros:

  • Easy to set up
  • Works with all HTTP clients
  • No session management needed

Cons:

  • Credentials sent with every request
  • No logout functionality
  • Browser password prompt can be confusing

Configuration:

[authentication]
type = basic
username = admin
# Use bcrypt hash (recommended)
password = $2b$12$LQv3c1yqBWVHxkd0LHAkCOYz6TtxMQJqhN8/LewY5GyYWv.5qVQK6
use_bcrypt = True
realm = TISBackup Admin

Generate bcrypt hash:

python3 -c "import bcrypt; print(bcrypt.hashpw(b'yourpassword', bcrypt.gensalt()).decode())"

Docker environment:

services:
  tisbackup_gui:
    environment:
      - TISBACKUP_SECRET_KEY=your-secret-key
    # Optional: Pass credentials via env vars
    # Then reference in config with ${AUTH_PASSWORD}

Flask-Login Authentication

Session-based authentication with login page and user management.

Pros:

  • Clean login/logout workflow
  • Session-based (no credentials in each request)
  • Multiple users supported
  • Password hashing with bcrypt

Cons:

  • Requires custom login page
  • Session management overhead
  • Cookies must be enabled

Configuration:

[authentication]
type = flask-login
users_file = /etc/tis/users.txt
use_bcrypt = True
login_view = login

Create users file (/etc/tis/users.txt):

admin:$2b$12$LQv3c1yqBWVHxkd0LHAkCOYz6TtxMQJqhN8/LewY5GyYWv.5qVQK6
operator:$2b$12$abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNO
viewer:$2b$12$ANOTHERBCRYPTHASHHERE1234567890ABCDEFGHIJKLMNOPQRS

Generate user entry:

USERNAME="admin"
PASSWORD="yourpassword"
HASH=$(python3 -c "import bcrypt; print(bcrypt.hashpw(b'$PASSWORD', bcrypt.gensalt()).decode())")
echo "$USERNAME:$HASH" >> /etc/tis/users.txt

Permissions:

chmod 600 /etc/tis/users.txt
chown root:root /etc/tis/users.txt

OAuth2 Authentication

Delegate authentication to external OAuth providers (Google, GitHub, GitLab, etc.)

Pros:

  • No password management
  • Leverage existing identity providers
  • Support for SSO
  • Can restrict by domain or specific users

Cons:

  • Requires OAuth app registration
  • Internet connectivity required
  • More complex setup
  • External dependency

Google OAuth

Setup:

  1. Go to Google Cloud Console
  2. Create OAuth 2.0 Client ID
  3. Add authorized redirect URI: http://your-server:8080/oauth/callback
  4. Note the Client ID and Client Secret

Configuration:

[authentication]
type = oauth
provider = google
client_id = 123456789-abcdefghijklmnop.apps.googleusercontent.com
client_secret = GOCSPX-your-client-secret-here
redirect_uri = http://your-server:8080/oauth/callback

# Restrict to specific domain(s)
authorized_domains = example.com,mycompany.com

# Or restrict to specific users
authorized_users = admin@example.com,backup-admin@example.com

GitHub OAuth

Setup:

  1. Go to GitHub Settings > Developer settings > OAuth Apps
  2. Register a new application
  3. Set Authorization callback URL: http://your-server:8080/oauth/callback
  4. Note the Client ID and Client Secret

Configuration:

[authentication]
type = oauth
provider = github
client_id = your-github-client-id
client_secret = your-github-client-secret
redirect_uri = http://your-server:8080/oauth/callback
authorized_users = admin@example.com,devops@example.com

GitLab OAuth

Setup:

  1. Go to GitLab User Settings > Applications
  2. Create application with scopes: read_user, email
  3. Set Redirect URI: http://your-server:8080/oauth/callback
  4. Note the Application ID and Secret

Configuration:

[authentication]
type = oauth
provider = gitlab
client_id = your-gitlab-application-id
client_secret = your-gitlab-secret
redirect_uri = http://your-server:8080/oauth/callback
authorized_domains = example.com

Generic OAuth Provider

For custom OAuth providers:

[authentication]
type = oauth
provider = generic
client_id = your-client-id
client_secret = your-client-secret
redirect_uri = http://your-server:8080/oauth/callback

# Custom endpoints
authorization_endpoint = https://auth.example.com/oauth/authorize
token_endpoint = https://auth.example.com/oauth/token
userinfo_endpoint = https://auth.example.com/oauth/userinfo
scopes = openid,email,profile

# Authorization rules
authorized_domains = example.com

Security Best Practices

1. Use HTTPS in Production

Always use a reverse proxy with TLS:

server {
  listen 443 ssl http2;
  server_name tisbackup.example.com;

  ssl_certificate /etc/letsencrypt/live/tisbackup.example.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/tisbackup.example.com/privkey.pem;

  location / {
    proxy_pass http://localhost:8080/;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto https;
  }
}

2. Set Strong Flask Secret Key

# Generate secret
python3 -c "import secrets; print(secrets.token_hex(32))"

# Set in environment
export TISBACKUP_SECRET_KEY=your-generated-secret-key

3. Protect Configuration Files

chmod 600 /etc/tis/tisbackup_gui.ini
chmod 600 /etc/tis/users.txt  # if using Flask-Login
chown root:root /etc/tis/*.ini

4. Use Environment Variables for Secrets

Instead of hardcoding secrets in config files:

[authentication]
type = oauth
client_id = ${OAUTH_CLIENT_ID}
client_secret = ${OAUTH_CLIENT_SECRET}

Then set in Docker Compose:

services:
  tisbackup_gui:
    environment:
      - OAUTH_CLIENT_ID=your-client-id
      - OAUTH_CLIENT_SECRET=your-client-secret
      - TISBACKUP_SECRET_KEY=your-secret-key

5. Regularly Rotate Credentials

  • Change passwords/secrets every 90 days
  • Rotate OAuth client secrets annually
  • Review authorized users/domains regularly

6. Monitor Authentication Logs

Check logs for failed authentication attempts:

docker logs tisbackup_gui | grep -i "auth"

Troubleshooting

Basic Auth Not Working

  1. Verify password hash:

    python3 -c "import bcrypt; print(bcrypt.checkpw(b'yourpassword', b'$2b$12$your-hash'))"
    
  2. Check browser credentials:

    • Clear browser cache
    • Try incognito/private mode

Flask-Login Issues

  1. Users file not found:

    ls -la /etc/tis/users.txt
    chmod 600 /etc/tis/users.txt
    
  2. Session problems:

    • Check TISBACKUP_SECRET_KEY is set
    • Ensure cookies are enabled

OAuth Problems

  1. Redirect URI mismatch:

    • Ensure redirect URI in config matches OAuth app settings exactly
    • Check for http vs https mismatch
  2. Unauthorized domain/user:

    • Verify email matches authorized_users or domain matches authorized_domains
    • Check OAuth provider returns email in user info
  3. Token errors:

    • Verify client ID and secret are correct
    • Check OAuth app is enabled
    • Ensure scopes are correct

API Access with Authentication

Basic Auth

curl -u admin:password http://localhost:8080/api/backups

OAuth (with access token)

# Not recommended for API access - use service account or API keys instead

Recommendation for API Access

For programmatic API access, use Basic Auth with a dedicated API user:

[authentication]
type = basic
username = api-user
password = $2b$12$...

Or implement API key authentication separately for API endpoints.

Migration Guide

From No Auth to Basic Auth

  1. Add authentication section to config
  2. Restart service
  3. Update client scripts with credentials

From Basic Auth to OAuth

  1. Register OAuth application
  2. Update configuration
  3. Test OAuth login flow
  4. Update redirect URI if needed

From Flask-Login to OAuth

  1. Register OAuth application
  2. Map user emails to OAuth provider
  3. Update configuration
  4. Test migration with test users first

Support

For issues or questions:

  • Check logs: docker logs tisbackup_gui
  • Review configuration syntax
  • Verify dependencies are installed
  • See SECURITY_IMPROVEMENTS.md for security context