Basic auth stopped working starting at 1.4.3
auth-test.py
import datetime
import tornado
from tornado.web import RequestHandler
# could define get_user_async instead
def get_user(request_handler):
return request_handler.get_cookie("user")
# could also define get_login_url function (but must give up LoginHandler)
login_url = "/login"
class LoginHandler(RequestHandler):
def get(self):
try:
errormessage = self.get_argument("error")
except Exception:
errormessage = ""
self.render("login.html", errormessage=errormessage)
def check_permission(self, username, password):
if username == "testuser" and password == "password":
return True
return False
def post(self):
username = self.get_argument("username", "")
password = self.get_argument("password", "")
auth = self.check_permission(username, password)
if auth:
self.set_current_user(username)
self.redirect("/")
login_status = "successful"
else:
error_msg = "?error=" + \
tornado.escape.url_escape("Login incorrect")
login_status = "failed"
self.redirect(login_url + error_msg)
def set_current_user(self, user):
if user:
self.set_cookie(
"user",
tornado.escape.json_encode(user),
expires_days=0.3
)
else:
self.clear_cookie("user")
# optional logout_url, available as curdoc().session_context.logout_url
logout_url = "/logout"
# optional logout handler for logout_url
class LogoutHandler(RequestHandler):
def get(self):
self.clear_cookie("user")
self.redirect("/")
login.html
<!doctype html>
<html>
<head>
<title>Test Login</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html {
height: 100%;
}
body {
font-family: "Segoe UI", sans-serif;
font-size: 1rem;
line-height: 1.6;
height: 100%;
}
.wrap {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
background: #fafafa;
}
.login-form {
width: 350px;
margin: 0 auto;
border: 1px solid #ddd;
padding: 2rem;
background: #ffffff;
}
.form-input {
background: #fafafa;
border: 1px solid #eeeeee;
padding: 12px;
width: 100%;
}
.form-group {
margin-bottom: 1rem;
}
.form-button {
background: #69d2e7;
border: 1px solid #ddd;
color: #ffffff;
padding: 10px;
width: 100%;
text-transform: uppercase;
}
.form-button:hover {
background: #69c8e7;
}
.form-header {
text-align: center;
margin-bottom: 2rem;
}
.form-footer {
text-align: center;
}
</style>
</head>
<body>
<div class="wrap">
<form class="login-form" action="/login" method="post">
{% module xsrf_form_html() %}
<div class="form-header">
<p>Login to access dashboard</p>
</div>
<!--Email Input-->
<div class="form-group">
<input
name="username"
type="text"
class="form-input"
autocapitalize="off"
autocorrect="off"
placeholder="username"
/>
</div>
<!--Password Input-->
<div class="form-group">
<input
name="password"
type="password"
class="form-input"
placeholder="password"
/>
</div>
<!--Login Button-->
<div class="form-group">
<button class="form-button" type="submit">Login</button>
</div>
<span class="errormessage">{{errormessage}}</span>
</form>
</div>
</body>
</html>
test_login.py
import panel as pn
pn.extension()
pn.panel("Hello World").servable()
panel serve test_login.py --auth-module=auth-test.py
Works up until panel 1.4.2
For panel 1.4.3 and 1.4.4: