I am making a web application in python and I would like to have a secure login system.
I have done login systems many times before by having the user login and then a random string is saved in a cookie which is also saved next to that user in a database which worked fine but it was not very secure.
I believe understand the principles of an advanced system like this but not the specifics:
- Use HTTPS for the login page and important pages
- Hash the password saved in the database(bcrypt, sha256? use salt?)
- Use nonces(encrypted with the page url and ip?)
But apart from those I have no idea how to reliably check if the person logged in is really the user, or how to keep sessions between page requests and multiple open pages securely, etc.
Can I have some directions (preferably specific ones since I am new to this advanced security programming.
I am just trying to accomplish a basic user login-logout to one domain with security, nothing too complicated.
This answer mainly addresses password hashing, and not your other subquestions. For those, my main advice would be don't reinvent the wheel: use existing frameworks that work well with GAE. It offers builtin deployments of Django, but also has a builtin install of WebOb, so various WebOb-based frameworks (Pyramid, Turbogears, etc) should also be considered. All of these will have premade libraries to handle a lot of this for you (eg: many of the WebOb frameworks use Beaker for their cookie-based session handling)
Regarding password hashing... since you indicated in some other comments that you're using Google App Engine, you want to use the SHA512-Crypt password hash.
The other main choices for storing password hashes as securely as possible are BCrypt, PBKDF2, and SCrypt. However, GAE doesn't offer C-accelerated support for these algorithms, so the only way to deploy them is via a pure-python implementation. Unfortunately, their algorithms do way too much bit-fiddling for a pure-python implementation to do a fast enough job to be both secure and responsive. Whereas GAE's implementation of the Python crypt
module offers C-accelerated SHA512-Crypt support (at least, every time I've tested it), so it could be run at sufficient strength.
As far as writing actual code goes, you can use the crypt
module directly. You'll need to take care of generating your own salt strings when passing them into crypt, and when encrypting new passwords, call crypt.crypt(passwd, "$6$" + salt)
. The $6$
tells it to use SHA512-Crypt.
Alternately, you can use the Passlib library to handle most of this for you (disclaimer: I'm the author of that library). For quick GAE deployment:
from passlib.context import CryptContext
pwd_context = CryptContext(schemes=["sha512_crypt"],
default="sha512_crypt",
sha512_crypt__default_rounds=45000)
# encrypt password
hash = pwd_context.encrypt("toomanysecrets")
# verify password
ok = pwd_context.verify("wrongpass", hash)
Note: if care about password security, whatever you do, don't use a single HASH(salt+password) algorithm (eg Django, PHPass, etc), as these can be trivially brute-forced.
It's hard to be specific without knowing your setup. However, the one thing you should not do is reinventing the wheel. Security is tricky, if your wheel is lacking something you may not know until it's too late.
I wouldn't be surprised if your web framework came with a module/library/plugin for handling users, logins and sessions. Read its documentation and use it: it was hopefully written by people who know a bit about security.
If you want to know how it's done, study the documentation and source of said module.