2
\$\begingroup\$

I recently started a project using python-tornado, and needed to implement google OAuth to manage user logins. I struggled getting this working in the context of the project, and decided to abstract it out to a simple working demo. Since it was such a bear to get up and running in the first place, I wanted to seek feedback regarding my specific implementation, to have the best fleshed-out boilerplate I can to quickly get a new project up and running. Any advice regarding performance/security/maintainability are greatly appreciated.

Below is the code, which a working demo can be found on Github.

import os
import tornado.auth
import tornado.autoreload
import tornado.ioloop
import tornado.web
import json

class BaseHandler(tornado.web.RequestHandler):
    def get_current_user(self):
        return self.get_secure_cookie("user")

class TestHandler(BaseHandler):
    def get(self):
        name = tornado.escape.xhtml_escape(self.current_user)
        print self.get_current_user()
        self.write("Hello, " + name)

class MainHandler(BaseHandler):
    def get(self):
        if not self.current_user:
            self.redirect("/")
            return

class GoogleOAuth2LoginHandler(BaseHandler, tornado.auth.GoogleOAuth2Mixin):
    @tornado.gen.coroutine
    def get(self):
        if self.get_argument('code', False):
            access = yield self.get_authenticated_user(
                redirect_uri=os.environ['REDIRECT_URI'],
                code=self.get_argument('code'))
            user = yield self.oauth2_request("https://www.googleapis.com/oauth2/v1/userinfo", access_token=access["access_token"])
            self.set_secure_cookie("user", json.dumps(user))
            self.current_user = user
            self.redirect('/test')
        else:
            yield self.authorize_redirect(
            redirect_uri=os.environ['REDIRECT_URI'],
            client_id=os.environ['CLIENT_ID'],
            client_secret=os.environ['CLIENT_SECRET'],
            scope=['profile', 'email'],
            response_type='code',
            extra_params={'approval_prompt': 'auto'}
        )

def make_app():
    settings = {
    'google_oauth' : {
            'key': os.environ['CLIENT_ID'],
            'secret': os.environ['CLIENT_SECRET'],
    },
    'redirect_uri': os.environ['REDIRECT_URI'],
    'login_url': '/',
    'cookie_secret': os.environ['COOKIE_SECRET']
    }
    return tornado.web.Application([
        (r"/", GoogleOAuth2LoginHandler),
        (r"/test", TestHandler)], **settings)

if __name__ == "__main__":
    app = make_app()
    app.listen(8888)
    print "Listening on port 8888"
    tornado.autoreload.start()
    for dir, _, files in os.walk('./'):
        [tornado.autoreload.watch(dir + '/' + f) for f in files if not f.startswith('.')]

    tornado.ioloop.IOLoop.current().start()
\$\endgroup\$
2
  • \$\begingroup\$ Your indentation seems off at several places. Can you check that the code is displayed exactly like in your editor and edit in the differences, please. \$\endgroup\$ Commented Dec 10, 2017 at 13:59
  • \$\begingroup\$ Thank you, it was just the one method from a bad copy and paste. I updated it to reflect the correct spacing. \$\endgroup\$ Commented Dec 11, 2017 at 19:46

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.