I have run into this scenario a couple of times now but am hoping to get either confirmation that I'm on the right track or a suggestion as to what else should be done.
Situation
I am building a back-end web service that provides access to sensitive data or privileged operations. This web service will not be publicly accessible but will be called by a front-end application that is. There may ultimately be multiple applications that need to access the service but not necessarily with different levels of access.
We want to secure the web service so that any other devices on the network are able to make calls the service, nor sniff traffic to determine how to authenticate.
Solution
Using a large, securely-generated random API key, which is sent via Basic authentication, the username and password are separated, the password hashed with SHA-256, and the result compared against a stored value for the user. This is done over TLS (i.e. with a pinned self-signed certificate or even with a valid CA-signed certificate) to prevent sniffing and to ensure that the client validates the server's authenticity.
Since the password is a large (let's say 128-bit) random value, the purpose of hashing the value is mostly:
- To avoid storing the api key in the web service
- To prevent timing attacks from string comparison against the actual API key, if it was actually stored by the application
Additional Thoughts
I considered doing a more typical password-hashing method (e.g. Argon2) but since the password is not intended to be human readable, it doesn't seem like much would be gained. Even salting the value doesn't seem like it would be very valuable since the space of possible API keys is so large.
There is also a definite need to keep this fast, since it will be sent with every request, so doing too much processing is not desirable.
Also, since this method is very straightforward, I'm not really looking for an alternate method is if this is secure enough. I'm really either looking for improvements that can be made to this schema or reasons that it's absolutely not secure (in which case I'm willing to hear about alternatives).