Edit: This scheme has since been standardised as WebAuthn - go use that instead!
I have a userbase which really isn't all that inclined to create a secure password for a website. They're also almost entirely on mobile devices, so I would like to try something a little different rather than them type 'password1' and just wait for it to get guessed. So, firstly, some assumptions:
- Web browsers almost always remember the password for you anyway.
- Mobile devices are increasingly gaining features which identify a particular user more securely (touch ID, for example).
- This uses HTTPS; Malicious clients (intercepting) are largely a non-issue.
The resulting implication:
- The website authenticates the device and the device authenticates the user. Therefore, we might as well use something better than a poorly chosen password for website <-> device.
Given this, the intention is to use a client generated key pair. The most similar thing asked before is Using RSA for Web Application Authentication, however this approach appears to be a little different.
So, the protocol itself. Firstly, the join process:
- The client generates an RSA key pair.
- The public key is sent to the server (over HTTPS). This only ever happens once per device.
- The server stores the public key as a device.
- The server creates an account and relates the device to the account. [A]
- The first session token along with the new device ID is encrypted using the public key, and the result is sent back to the client. The device ID is both a number and a randomly generated string.
- The client decrypts it, stores the device ID and the private key, and sets the IP locked session token as its cookie.
- All further requests are authenticated using the session token.
Login (typically due to changed IP)
- The client tells the server which device it is by sending the device ID.
- The server asks the client to prove it by encrypting the new session token with its stored public key of that device, and sending it.
- The client decrypts the data and sets the session as it's cookie.
- Provided it really is who it said it was, the session is now valid.
Adding a device to an account (e.g. a new phone to replace the one you just washed):
- The device gets a device ID for itself by doing a join similar to above but does not create an account; [A] does not occur. The device is currently able to authenticate but is not associated with any account. (And this association is purely at the server end).
- Enter your email address (or some other account related information such as a username) on the new device.
- The server identifies the requested account and sends it an email or SMS containing a link.
- The user loads the link (on any device). This causes the server to relate the new device to the original account, provided it's within e.g. 24 hours.
Known vulnerabilities:
The following vulnerabilities all also relate to your typical password system.
- It's as strong as the email account/ SMS receiver etc.
- SSLStrip and XSS being used to grab the stored private key, in the same way they could grab document.cookie or the autofilled user/password fields. Although the whole site is HTTPS only, there may be some unknown exploit with the surrounding infrastructure.
- Someone else could grab the physical device and use the site.
Benefits over a password system:
The 'password' is private, even from the server, helping against data leaks and MITM.
The 'password' text is considerably stronger as it's essentially equivalent to one in the region of 300-500 characters long.
The server only contains a list of public keys. Someone gaining this list via a data leak would still have to break RSA.
It's unphishable as the user never directly enters a password.
If an intruder breaks HTTPS, i.e. by going around it with something like SSLStrip, they'd still have to break the password as it's not then on the wire as clear text.
Actually simpler to use; the user simply enters, at a minimum, an email address.
Given this, my assumption is that such a system may provide more security and simplicity than a password one can. However, why is this not being done, and, should it be done; am I missing something? Or should I stick to the mainstream password setup and just live with it - any responses would be greatly appreciated!
Side notes
I'm aware of client certificates which this has parallels to, but they seem to use complicated terminology and UX for a user to understand, thus they doesn't get used all that much. On a similar thread then, it may make a user feel odd not using a password; it may be perceived to be less secure. (?)
Provided the technique is sound and the 'perception issue' isn't a concern, I intend to opensource the implemented solution for both greater security/ simplicity on the web with a corresponding full audit of the implementation.