login page polishing
frdel committed
Sep 23, 2025 at 09:49 UTC
68147778690483dd1b0b9f80436a1f77dbe58084
3 files changed
+17
-8
run_ui.py
+14
-7
@@ -1,6 +1,7 @@
1
from datetime import timedelta
2
import os
3
import secrets
4
+import hashlib
5
import time
6
import socket
7
import struct
@@ -38,7 +39,6 @@ webapp.config.update(
39
PERMANENT_SESSION_LIFETIME=timedelta(days=1)
40
)
41
41
-
42
lock = threading.Lock()
43
44
# Set up basic authentication for UI and API but not MCP
@@ -114,16 +114,23 @@ def requires_loopback(f):
114
return decorated
115
116
117
+def _get_credentials_hash():
118
+ user = dotenv.get_dotenv_value("AUTH_LOGIN")
119
+ password = dotenv.get_dotenv_value("AUTH_PASSWORD")
120
+ if not user:
121
+ return None
122
+ return hashlib.sha256(f"{user}:{password}".encode()).hexdigest()
123
+
124
# require authentication for handlers
125
def requires_auth(f):
126
@wraps(f)
127
async def decorated(*args, **kwargs):
121
- user = dotenv.get_dotenv_value("AUTH_LOGIN")
128
+ user_pass_hash = _get_credentials_hash()
129
# If no auth is configured, just proceed
123
- if not user:
130
+ if not user_pass_hash:
131
return await f(*args, **kwargs)
125
-
126
- if not session.get('authenticated'):
132
+
133
+ if session.get('authentication') != user_pass_hash:
134
return redirect(url_for('login'))
135
136
return await f(*args, **kwargs)
@@ -151,7 +158,7 @@ async def login():
158
password = dotenv.get_dotenv_value("AUTH_PASSWORD")
159
160
if request.form['username'] == user and request.form['password'] == password:
154
- session['authenticated'] = True
161
+ session['authentication'] = _get_credentials_hash()
162
return redirect(url_for('serve_index'))
163
else:
164
error = 'Invalid Credentials. Please try again.'
@@ -161,7 +168,7 @@ async def login():
168
169
@webapp.route("/logout")
170
async def logout():
164
- session.pop('authenticated', None)
171
+ session.pop('authentication', None)
172
return redirect(url_for('login'))
173
174
# handle default address, load index
webui/index.html
-1
@@ -130,7 +130,6 @@
130
<script type="text/javascript" src="js/settings.js"></script>
131
<script type="text/javascript" src="js/file_browser.js"></script>
132
<script type="text/javascript" src="js/modal.js"></script>
133
- <script type="module" src="js/tunnel.js"></script>
133
</head>
134
135
<body class="dark-mode device-pointer">
webui/js/api.js
+3
@@ -52,6 +52,9 @@ export async function fetchApi(url, request) {
52
// retry the request with new token
53
csrfToken = null;
54
return await _wrap(false);
55
+ }else if(response.redirected && response.url.endsWith("/login")){
56
+ // redirect to login
57
+ window.location.href = response.url;
58
}
59
60
// return the response