Instantly share code, notes, and snippets.

Embed
What would you like to do?
Basic authentication on Tornado with a decorator
<div id="main-container">
<div id="main">
<h1>
<img alt="scubabook logo" src="{{ static_url("img/logo.png") }}">
</h1>
<div id="login-form">
<form action="/auth/login/" method="post" id="login_form">
<fieldset>
<label for="username">Username</label>
<input autocapitalize="off" autocorrect="off" class="text-input" id="username" name="username" tabindex="1" type="text" value="">
</fieldset>
<fieldset>
<label for="password">Password</label>
<input class="text-input" id="password" name="password" tabindex="2" type="password" value="">
</fieldset>
<fieldset>
<span class="errormessage">{{errormessage}}</span>
</fieldset>
<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> -->
</div>
</form>
</div>
</div>
</div>
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
logging.basicConfig(level=logging.DEBUG,
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):
@tornado.web.authenticated
def get(self):
username = tornado.escape.xhtml_escape(self.current_user)
self.write("index.html", username = username)
class AuthLoginHandler(BaseHandler):
def get(self):
try:
errormessage = self.get_argument("error")
except:
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.set_current_user(username)
self.redirect(self.get_argument("next", u"/"))
else:
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))
else:
self.clear_cookie("user")
class AuthLogoutHandler(BaseHandler):
def get(self):
self.clear_cookie("user")
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 = {
"template_path":Settings.TEMPLATE_PATH,
"static_path":Settings.STATIC_PATH,
"debug":Settings.DEBUG,
"cookie_secret": Settings.COOKIE_SECRET,
"login_url": "/auth/login/"
}
tornado.web.Application.__init__(self, handlers, **settings)
def main():
tornado.options.parse_command_line()
http_server = tornado.httpserver.HTTPServer(Application())
http_server.listen(options.port)
tornado.ioloop.IOLoop.instance().start()
if __name__ == "__main__":
main()
@IVBakker

This comment has been minimized.

Show comment
Hide comment
@IVBakker

IVBakker Mar 14, 2016

Hi,
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.

Also:

try:
            errormessage = self.get_argument("error")
        except:
            errormessage = ""

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

IVBakker commented Mar 14, 2016

Hi,
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.

Also:

try:
            errormessage = self.get_argument("error")
        except:
            errormessage = ""

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

@EdwardCTaylor

This comment has been minimized.

Show comment
Hide comment
@EdwardCTaylor

EdwardCTaylor 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

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

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