Auto login with Authelia

This commit is contained in:
2026-01-23 13:41:39 +01:00
parent 877ecf32b4
commit 3d11470f81
3 changed files with 53 additions and 45 deletions

View File

@@ -61,6 +61,9 @@ environment:
- SSL/TLS termination at proxy - SSL/TLS termination at proxy
- Production deployments with HTTPS - Production deployments with HTTPS
**Special Feature - Authelia Auto-Login:**
When `ENABLE_PROXY=true` and you're using Authelia, the app automatically logs you in using Authelia's authentication headers. **No app password needed!** Simply authenticate through Authelia, and you'll be logged into the Mailcow Alias Manager automatically.
--- ---
### **Switching Between Modes** ### **Switching Between Modes**

View File

@@ -76,12 +76,14 @@ The application supports two access modes:
- Set `ENABLE_PROXY=false` in `docker-compose.yml` (default) - Set `ENABLE_PROXY=false` in `docker-compose.yml` (default)
- Access at: `http://your-server-ip:5172` - Access at: `http://your-server-ip:5172`
- Works over HTTP (no HTTPS required) - Works over HTTP (no HTTPS required)
- **Login:** Enter app password
- Perfect for internal/LAN access - Perfect for internal/LAN access
**Proxy Access** - Access via reverse proxy (Authelia, Nginx, Traefik, etc.) **Proxy Access** - Access via reverse proxy (Authelia, Nginx, Traefik, etc.)
- Set `ENABLE_PROXY=true` in `docker-compose.yml` - Set `ENABLE_PROXY=true` in `docker-compose.yml`
- Access at: `https://alias.yourdomain.com` (through your proxy) - Access at: `https://alias.yourdomain.com` (through your proxy)
- Requires HTTPS - Requires HTTPS
- **Login:** Automatic when using Authelia (no password needed!)
- See [PROXY_SETUP.md](PROXY_SETUP.md) for detailed configuration - See [PROXY_SETUP.md](PROXY_SETUP.md) for detailed configuration
**To switch modes:** **To switch modes:**

93
app.py
View File

@@ -171,40 +171,35 @@ def login_required(f):
@app.route('/login', methods=['GET', 'POST']) @app.route('/login', methods=['GET', 'POST'])
def login(): def login():
"""Login page""" """Login page or JSON login endpoint"""
# First, try Authelia authentication
authelia_user = get_authelia_user()
# Debug logging for all requests # Auto-login when ENABLE_PROXY=true and Authelia headers are present
if app.debug: if ENABLE_PROXY:
logger.info(f"Login route: method={request.method}, headers={dict(request.headers)}") authelia_user = get_authelia_user()
# If Authelia authenticated, login and redirect to index
if authelia_user:
logger.info(f"Login via Authelia for user: {authelia_user}")
session.clear()
session.permanent = True
session['logged_in'] = True
session['authelia_user'] = authelia_user
session['user_token'] = secrets.token_urlsafe(32)
session['auth_method'] = 'authelia'
session.modified = True
# Set a cookie manually to ensure it's properly formatted for Zoraxy if authelia_user:
response = redirect(url_for('index')) # User authenticated by Authelia - auto-login
# Set cookie parameters to work with Zoraxy/Authelia if not session.get('logged_in'):
response.set_cookie( logger.info(f"🔐 Auto-login: User '{authelia_user}' authenticated by Authelia")
key=app.config['SESSION_COOKIE_NAME'], session.clear()
value=secrets.token_urlsafe(32), # Generate a new token instead of using session.sid session.permanent = True
max_age=int(app.config['PERMANENT_SESSION_LIFETIME'].total_seconds()), session['logged_in'] = True
path=app.config['SESSION_COOKIE_PATH'], session['user_token'] = secrets.token_urlsafe(32)
secure=app.config['SESSION_COOKIE_SECURE'], session['auth_method'] = 'authelia'
httponly=app.config['SESSION_COOKIE_HTTPONLY'], session['authelia_user'] = authelia_user
samesite='None' session.modified = True
)
return response # Get additional Authelia info if available
session['remote_email'] = request.headers.get('Remote-Email', '')
session['remote_name'] = request.headers.get('Remote-Name', '')
session['remote_groups'] = request.headers.get('Remote-Groups', '')
logger.info(f"✅ Auto-login successful: {authelia_user} ({session.get('remote_email', 'no email')})")
# Already logged in via Authelia - redirect to main page
return redirect(url_for('index'))
# Handle form submission for local authentication # Handle form submission for local authentication (only when ENABLE_PROXY=false)
if request.method == 'POST': if request.method == 'POST':
password = request.json.get('password', '') password = request.json.get('password', '')
logger.info("Login attempt with password (redacted)") logger.info("Login attempt with password (redacted)")
@@ -286,20 +281,28 @@ def logout():
@app.route('/') @app.route('/')
def index(): def index():
"""Main page - requires login""" """Main page - requires login"""
# Try to auto-login with Authelia # Auto-login with Authelia (only when ENABLE_PROXY=true)
authelia_user = get_authelia_user() if ENABLE_PROXY:
authelia_user = get_authelia_user()
if authelia_user and not session.get('logged_in'):
# Auto-login for users authenticated by Authelia if authelia_user and not session.get('logged_in'):
logger.info(f"Auto-login via Authelia for user: {authelia_user}") # Auto-login for users authenticated by Authelia
session.clear() logger.info(f"🔐 Auto-login via Authelia for user: {authelia_user}")
session.permanent = True session.clear()
session['logged_in'] = True session.permanent = True
session['authelia_user'] = authelia_user session['logged_in'] = True
session['user_token'] = secrets.token_urlsafe(32) session['authelia_user'] = authelia_user
session['auth_method'] = 'authelia' session['user_token'] = secrets.token_urlsafe(32)
session.modified = True session['auth_method'] = 'authelia'
return render_template('index.html') session.modified = True
# Store additional Authelia info
session['remote_email'] = request.headers.get('Remote-Email', '')
session['remote_name'] = request.headers.get('Remote-Name', '')
session['remote_groups'] = request.headers.get('Remote-Groups', '')
logger.info(f"✅ Auto-login successful: {authelia_user} ({session.get('remote_email', 'no email')})")
return render_template('index.html')
# Check if logged in # Check if logged in
if not session.get('logged_in'): if not session.get('logged_in'):