I'm currently in the process of building a JavaScript SPA and have been researching how to secure it. There is currently as RESTful API that is being completely interacted with through AJAX. We also have mobile clients that interact with this API, and currently it only supports HTTP BASIC Authentication over SSL. The JavaScript app will also communicate exclusively over SSL, but BASIC Auth won't cut it as that would involve storing the password (or a derivative of it) on the client. Lastly, the SPA app will be pure JavaScript and HTML, served on the same server as the RESTful API, but without any server-side framework.
Goals:
- No server-side framework for the javascript client (it's just another client).
- Maintain statelessness of the RESTful API, for the typical reasons (scalability, fault tolerance, simplified deployment, etc)
- Any state should be maintained by the client. For the purposes of this question, this means the login credentials.
- Login state maintained by the client must be secure and be resistant to session hijacking and similar attacks.
What I've come up with is based on my research of OAuth and similar schemes (Amazon, etc).
- The user will login using and HTTP POST over SSL.
The server will compute a hash as follows:
HMAC(key, userId + ":" + ipAddress + ":" + userAgent + ":" + todaysDateInMilliseconds)
This token will be returned to the client and supplied with every subsequent request in place of the userName and password. It will most likely be stored in localStorage or a cookie.
Is this secure? My motivation for choosing the userId,ipAddress,todaysDateInMilleseconds is to create a token that is valid for only today, but does not require database lookup for every request AND is safe to be stored on the client. I cannot trust that the key will not be comprimised, thus the inclusion of IP Address in an attempt to prevent session hijacking.
Let me include the following link from a related post on StackExchange because I think it addresses a lot of the issues I'm trying to solve: REST and Stateless Session Ids
After the initial feedback here I've decided to use only the first two octects of the IP address to handle clients behind proxies and mobile clients better. It's still not perfect, but its a tradeoff for some additional security.