Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Basic authentication on Tornado with a decorator
<div id="main-container">
<div id="main">
<img alt="scubabook logo" src="{{ static_url("img/logo.png") }}">
<div id="login-form">
<form action="/auth/login/" method="post" id="login_form">
<label for="username">Username</label>
<input autocapitalize="off" autocorrect="off" class="text-input" id="username" name="username" tabindex="1" type="text" value="">
<label for="password">Password</label>
<input class="text-input" id="password" name="password" tabindex="2" type="password" value="">
<span class="errormessage">{{errormessage}}</span>
<div id="form_btn">
<input id="signin-btn" class="btn btn-blue" type="submit" value="Sign In" tabindex="3">
<!-- <a href="/sb/"><input id="inscription-btn" class="btn btn-red" value="Inscription" tabindex="3"></a> -->
import os
DEBUG = True
DIRNAME = os.path.dirname(__file__)
STATIC_PATH = os.path.join(DIRNAME, 'static')
TEMPLATE_PATH = os.path.join(DIRNAME, 'template')
import logging
import sys
#log linked to the standard error stream
format='%(asctime)s - %(levelname)-8s - %(message)s',
datefmt='%d/%m/%Y %Hh%Mm%Ss')
console = logging.StreamHandler(sys.stderr)
#import base64
#import uuid
#base64.b64encode(uuid.uuid4().bytes + uuid.uuid4().bytes)
COOKIE_SECRET = 'L8LwECiNRxq2N0N2eGxx9MZlrpmuMEimlydNX/vt1LM='
import tornado.auth
import tornado.escape
import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web
import Settings
from tornado.options import define, options
define("port", default=8888, help="run on the given port", type=int)
class BaseHandler(tornado.web.RequestHandler):
def get_current_user(self):
return self.get_secure_cookie("user")
class MainHandler(BaseHandler):
def get(self):
username = tornado.escape.xhtml_escape(self.current_user)
self.write("index.html", username = username)
class AuthLoginHandler(BaseHandler):
def get(self):
errormessage = self.get_argument("error")
errormessage = ""
self.render("login.html", errormessage = errormessage)
def check_permission(self, password, username):
if username == "admin" and password == "admin":
return True
return False
def post(self):
username = self.get_argument("username", "")
password = self.get_argument("password", "")
auth = self.check_permission(password, username)
if auth:
self.redirect(self.get_argument("next", u"/"))
error_msg = u"?error=" + tornado.escape.url_escape("Login incorrect")
self.redirect(u"/auth/login/" + error_msg)
def set_current_user(self, user):
if user:
self.set_secure_cookie("user", tornado.escape.json_encode(user))
class AuthLogoutHandler(BaseHandler):
def get(self):
self.redirect(self.get_argument("next", "/"))
class Application(tornado.web.Application):
def __init__(self):
handlers = [
(r"/", MainHandler),
(r"/auth/login/", AuthLoginHandler),
(r"/auth/logout/", AuthLogoutHandler),
settings = {
"cookie_secret": Settings.COOKIE_SECRET,
"login_url": "/auth/login/"
tornado.web.Application.__init__(self, handlers, **settings)
def main():
http_server = tornado.httpserver.HTTPServer(Application())
if __name__ == "__main__":

This comment has been minimized.

Copy link

@Fran-Rg Fran-Rg commented Mar 14, 2016

Good gist but the next parameter isn't carried from the GET login to the POST. Thus then login you simply get redirected to home page.


            errormessage = self.get_argument("error")
            errormessage = ""

can be simply replace by errormessage = self.get_argument("error",'')


This comment has been minimized.

Copy link

@EdwardCTaylor EdwardCTaylor commented Jul 5, 2017

Cheers for gist. to corrected above as follows:

  1. set params in the AuthLoginHandler GET call to include nextpage ('/' fallback). passed to template
def get(self):
        params = {
            "errormessage": self.get_argument("error",''),
            "nextpage": self.get_argument("next", "/")
        self.render('login.html', **params)
  1. Updated the template to pass on "next" param

<form action="/auth/login?next={{nextpage}}" method="post" id="login_form">

Seems a relatively clean way of fixing


This comment has been minimized.

Copy link

@hclivess hclivess commented Nov 7, 2019

What's the Settings you are importing?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment