My REST service currently uses SCRAM authentication to issue tokens for callers and users.
Tokens issued by the SCRAM exchange have an expiry time after which a repeated sign-in is required. We also will be issuing 'infinite' tokens that have no expiry to simplify integration for individuals (who will use our service for personal use) and in preparation for a JSONP endpoint.
We have the ability to revoke caller privileges (the account to which the token is attached) and ban IPs, as well as impose quotas to any type of request across any time period.
One thing that I haven't implemented, however, is MAC for requests. As I've thought about it more, for some requests I think this is needed, because otherwise tokens can be stolen and before we identify this and deactivate the associated caller account, some damage could be done to our user accounts.
In many systems the MAC is generated from the body or query string of the request, however this is difficult to implement as I'm using the ASP.Net Web API and don't want to read the body twice. Equally importantly I want to keep it simple for callers to access the service, and I need to be able to support both desktop/mobile apps as well as web browsers.
So what I'm thinking is to have a MAC key sent to a user on registration, and have them calculate a request MAC on:
- the url, possibly minus query string
- the verb
- utc date and time when the client issues the request.
For the last one I would have the client send that string in a request header, of course - and I can use it to decide whether the request is 'fresh' enough.
My thinking is that whilst this doesn't prevent message body tampering it does prevent using a model request to use as a template for different requests later on by a malicious third party. I believe only the most aggressive man in the middle attack would be able to subvert this, and I don't think our services offer any information or ability that is valuable enough to warrant that.
The services will use SSL as well, for sensitive stuff. And if I do this, then I'll be using HMAC-SHA-256 with the key generated using a PRNG.
Does this sound enough? Have I missed anything?
I don't think I'm a beginner when it comes to security, but when working on it I always. am shrouded in doubt, so I appreciate having this community to call upon!