I'm working up an API for a REST service that I'm going to both be producing and consuming. I've spent the past few days trying to figure out how to handle authentication nicely, and think I've finally come up with something.
I'm coming up with this based on the following facts about the application stack:
- Client & Server are in .NET4 (Client part in Client Profile)
- Server exposes using WCF REST
- I really don't want to keep the user name and password in memory in the app
From 3, I wanted to use a form of token authentication, so that after the credentials are verified by the server, the client gets a token back to use throughout the rest of the app (this will allow me to do other things, such as timing out users, being able to move users seamlessly between the web and desktop versions, etc). After figuring out how to make the calls replay and tamper resistant, I've come up with the following:
- Before the client attempts to authenticate, it generates a Diffie-Hellman key pair using the
- It sends the public part of the key pair over the wire along with the user name and password (Over HTTPS of course).
- Server authenticates the username/password combination, if successful, it then does the following:
- Creates a unique session token
- Generates its own DH key pair, and calculate the shared secret from the public key provided by the client
- Makes note of the session token, the shared secret, the user, and the "last action" time (used for a rolling expiration window) in its database
- Returns the session token, its public DH key, and an authentication success message
- Client takes the DH key from the response, calculates the shared secret, and store both token and secret in memory.
From this point on, the session token/secret combination works like most other REST APIs, with the request being fingerprinted and timestamped, and then have some sort of HMAC generated. Whenever a client performs an action against the server, it checks the token/secret pair, and allows the action if it is valid and not expired, and updates the last action record in the session.
I don't see any obvious flaws, and is probably over-engineered for this, but I need to learn how to do this at some point. The HMAC prevents replay attacks, the DH negotiation helps prevent MITM attacks (I can't think of a workable attack off the top of my head between HMAC/DH).
Any holes anyone can poke in this?