I have been interested in implementing authentication method for a web app that is run in modern browsers, without having to send the password over the wire.
Can anyone suggest improvements or even tell me whether or not I am going wrong.
The authentication is done over an unsecured HTTP connection using AJAX.
My current understanding of an authentication protocol implementation
Server has a users password that was hashed using bcrypt and stored during registration.
User enters id
and password
. A XMLHttpRequest
is sent to the server to begin authentication, X-R1
is a random integer created on client.
GET /auth/{id} HTTP/1.1
X-R1: 123412341234
Server gets values.
ServerPassword
- users bycrpt hashed password from password databaseX-Salt
- extracts the salt from theServerPassword
X-R1
- from client in the request headerX-R2
- randomly generated integer on server.
Server creates values
X-Session
- session key, concatenatingX-R1 + X-R2 + id
it then one way hashes this stringVerifier
- shared secret, concatenatingX-R1 + X-R2 + ServerPassword
and then one way hashing this string.Saves these values to a session store.
Server response.
HTTP/1.1 202 ACCEPTED
X-R2: 432143214321
X-Salt: $2a$10$rBV2JDeWW3.vKyeQcM8fFO
X-Session: 92429d82a41e930486c6de5ebda9602d55c39986
Client gets values
X-R1
- same value from before sending the request.ClientPassword
- plain text, what user entered.X-R2
- from server sent headerX-Salt
- from server sent header.
Client creates values
HashedPassword
- created using a JavaScript implementation of bcrypt by using theClientPassword
andX-Salt
Verifier
- ConcatenatingX-R1 + X-R2 + HashedPassword
and then one way hashing this value. Client uses a JavaScript implementation of bcrypt to hash the password that the user entered withX-Salt
's string.
Now the client and the server both think they have the same verifier so to confirm this client sends a further request but this time hashing the request headers and body with the verifier and then adding 'X-Auth' to the headers with the resulting hash.
POST /auth/{id} HTTP/1.1
X-Session: 92429d82a41e930486c6de5ebda9602d55c39986
X-Auth: ad801198a9fab4e4ef79eb97624a4bf9c78b450a
Server now looks up the X-Sessions
's in it's session store. Does the same hashing of the request headers and body and then checks to see if the hash matches X-Auth
's value, if so the server assumes the client is authorised and responds accordingly.
HTTP/1.1 200 OK
Client knows server has the same Verifier
and stores it in localStorage
using X-Session
's value for the key, for further requests.
Concerns
I am an average developer and no crypto expert and from my understanding I can not see any issues that might occur with this method.
I can see the great advantages, such as:
The password is never sent over the wire. Prevent MITM from getting your password.
MITM can't modify request as it is hashed with the verifier and then sent.
The server doesn't need to use bcrypt every time a user wants to authenticate.