Over the last several months I have been working on a project with two somewhat conflicting goals:
- Create an authentication service which is secure.
- Create an authentication service which is easy to use.
I believe I have achieved that goal, and I call it AuthHub, and I want to say a little bit about it. I also want to start soliciting people who are interested in trying it out to participate in an alpha test starting later this month.
What is AuthHub?
AuthHub is web-based authentication service based on several ideas I have had as I have worked to secure mobile and web applications. I have noticed that programmers are often under pressure to develop application features and leave secure authentication as either an afterthought, or something relegated to the framework they happen to use. In many cases the framework may offer a fairly secure password storage mechanism, but often two-factor authentication is not available or available as a poorly integrated add-on. This can lead to a piecemeal approach to user authentication which is hard to audit and difficult to secure.
I decided to create an authentication service which can be integrated with any development framework, is easy to use, enforces integrated 2-factor authentication, and incorporates clear encryption and hashing standards. I also decided to address a weak link in the chain of most authentication systems, the use of email for password resets.
Authentication and the User Problem
In theory password based authentication works because a user picks a complex random password and remembers that password. In practice we have a couple of problems. The first is that users do not pick great passwords as is evident from the number of times word "password" has been found on cracked password lists. The introduction of a second factor, which incorporates a cryptographically random number chosen not by the user, but by a computational algorithm, creates additional security. Currently AuthHub uses the Time-based One-time Password Algorithm (TOTP) specified in RFC 6238 and popularized by Google Authenticator. I am also working on including U2F support. These second factors can help mitigate the weakness of user generated passwords.
The second issue is that users often forget their passwords. As a result most authentications systems provide a reset mechanism, and this reset mechanism often relies on a separate system such as email, text message, or verification by phone call. Most common among these is email, which I think is a bad route through which to conduct password resets. Email was written for a less secure internet and email messages containing reset codes or links are often sent unencrypted through the internet. In addition to that, there are still many email providers that accept unencrypted POP connections, through which an email user may send their email password unencrypted. I have decided to eliminate these reset mechanisms that rely on third party communication mechanisms and instead generate a 16 character reset code when a user creates his or her login credentials.
The reset code is chosen using a cryptographic random-number generation scheme. The user is advised to store this code in a safe location. This still has the possibility of being exploited as some users will probably copy the code and save it as an unencrypted file on their laptop, but some users may go as far as to save this code in a safety deposit box. The point of this scheme is that it places the responsibility and faith fully in the user, leaving the user and AuthHub itself as the only possible points of failure. Any other scheme creates an additional point of failure in the network used to communicate the reset instructions back to the user.
Nuts and Bolts
So, how does AuthHub work? AuthHub is based on established and tested cryptography and hashing schemes. I also have used standard libraries.
- AuthHub is written in Python using the Bottle microframework and Gunicorn web application server behind an Nginx proxy.
- AuthHub stores user names, per user salt, password hashes, and encrypted TOTP keys in a PostgreSQL database backed by an encrypted drive. Passwords and encryption keys are never placed in the database.
- AuthHub stores temporary tokens in a Redis memory store. Keys automatically time-out and are removed within one hour of creation, unless they are revoked sooner. Passwords and encryption keys are never placed in the memory store.
- Database backups are stored in encrypted AWS S3 buckets. Both the Amazon API key and S3 bucket keys are regularly rotated (I am still considering the optimal key rotation frequency).
- Random numbers are generated using the
os.urandom
random number generator in python. This is used to generate a 32 byte salt for every user, a 10 byte TOTP key, 32 byte random tokens, and the 16 character reset code. - We use PBKDF2, a standard under PKCS #5 v2.0, to create a 32 byte password hash using the user password and user's random salt. We do 10,000 SHA-256 iterations to make the process relatively slow. The first 16 bytes of this hash are stored and used for password verification. The last 16 bytes are never stored and used as a user encryption key. PBKDF2 is also used to store the hash of the 16 character reset code. The reset code is treated like a password and therefore is never stored in the database or memory store. The PBKDF2 implemtation used by AuthHub is included with the python standard library.
- The user encryption key is used to encrypt and decrypt the TOTP key using AES. The cryptography library's AES implementation is used for encryption. Encryption is done according to the Fernet specification. As a result the TOTP code cannot be verified without the user providing his or her password as well.
- In the event that a database is compromised the user accounts can be set to force the user to use the reset code to reset his or her account. This requires the user to generate a new password, a new TOTP key is generated, and a new reset code is generated thus rendering any stolen hashed or encrypted information useless. We store no additional user information.
- Communication between AuthHub service and the web or mobile client application uses a simple protocol based on HTTP redirection, TLS encrypted HTTP calls to preapproved hosts, and employs cross-site request forgery mitigation codes.
- Communication between the AuthHub service and the client application server uses TLS encrypted HTTP calls with client and server certificates signed by the AuthHub certificate authority.
- Short-term randomly generated tokens are passed between the client application, application server, and the AuthHub service. These are revoked by the application server when authentication is complete.
- The only assertion made by the AuthHub service to the application server is the user name of the user on successful authentication.
You Seem Interested
If you have read to this point, you are probably pretty interested in trying this out. If you would like to be included in the alpha send me an email or tweet and I'll contact you with information about the alpha. In the coming weeks I'll be putting up documentation and working on the user management interface.
If you have any comments, feel I have left anything out, or feel I am overlooking some aspect of security please let me know. In subsequent posts I will dive deeper into the API and integrating AuthHub into a web application.