BitsDevelopmentTeam / bits-server

Presence and logging daemon for BITS system.
GNU General Public License v3.0
5 stars 2 forks source link

Implementing in-house authentication #11

Closed esseks closed 11 years ago

esseks commented 11 years ago

I have written all models, DB actions (delete) and views that fully implement the authentication system. Since this is a major change in security (we expose a write access to our DB on the Internet), I ask you to review the changes thoroughly.

How does it work

Each user is identified by a unique username and a password. Passwords are stored as salted SHA512 hashes. We use the passlib Python library to handle that transparently.

Here is a query on my test DB:

sqlite> select * from Users;
test|$6$rounds=60000$mkstDqSFFT4rtk8R$awvaSa2yU0s/546kWiewri1SUklIh.HJtZT69LKOaDSkjIWbPWUGkdX/Ih.v.4.WHN0kMCSZkRZVZd0SuKgmE.

The username is base64 encoded and stored in a cookie with a timestamp and a HMAC (with SHA1, Python stdlib implementation, documentation here) signature for integrity, like:

usertoken="dGVzdA==|1382384756|a21d79cdae3270df508e7c085696c44692666a97"

which is, obviously, fictitious. The cookie max age can be configured and defaults to one day. The signature is calculated starting from cookie name, value, timestamp and a server secret, according to the standard procedure implemented by Tornado in create_signed_value, source code here

How to protect a page

Authenticated path handlers must inherit from bitsd.server.handlers.BaseHandler and their get/post methods must be decorated with tornado.web.authenticated:

class AwesomenessHandler(BaseHandler):
    @tornado.web.authenticated
    def get(self):
        # Something very exciting here...

That's it. Authentication and redirection to/from login page is handled behind the scenes for you :)

How to add/remove users

Users can be added, removed or modified using usermanage.py utilty. It works more or less like adduser in interactive mode. It allows you to add:

$ ./usermanage.py add test
Password for `test`:

remove:

$ ./usermanage.py delete test

and modify:

$ ./usermanage.py modify test
New password for `test`:

users in the database. This tool is still experimental: you don't risk compromising DB in any way or anything, but expect errors in non-ordinary cases (adding already existing users...). I will fix it asap, but it's not critical.

Important notice about security

The authentication data is sent in clear text. It is IMPERATIVE to force SSL, at least on login page.

esseks commented 11 years ago

Consider that this will break DB schema. Drop Users and Message tables if some weird DB error appears.

esseks commented 11 years ago

I am adding a numeric user ID for privacy and byte saving in a subsequent pull request.