Hacker News new | past | comments | ask | show | jobs | submit login

You also hash the two differently in your database. With passwords you want to bcrypt (or similar) them to protect against exposure of the DB and an attacker brute forcing the hashes. Since this is virtually impossible for long random strings you're able to just SHA2-256 the keys for DB storage. This becomes important because you're likely checking the key every API request and bcrypt would be a significant API rate limiter.



Exactly what is the point of obfuscating single-purpose API keys at all?


If you store keys plaintext in the DB then if someone gets your DB then they're able to perform API requests on behalf on any of your users.


Doesn't exactly the same concerns arise? A single purpose may be a major purpose, such as "transfer monies between accounts", and aren't exactly the same concerns relevant between passwords and keys?

If someone gets a list of unencrypted (or poorly encrypted) passwords, they have the rights of the user. If someone gets a list of unencrypted (or poorly encrypted) keys, they have the rights of the API caller. The concerns seem identical.


I will state the argument as I understand it:

The difference is that you can, and should, rotate your API keys automatically and fairly frequently (I will leave it to experts to tell us how frequently is prudent.)

Moreover, when you think your DB has been compromised you can flush all the API keys and reissue them. Depending on the application this may be more or less of a pain for the customers, but at least it is possible, because the keys are random and generated by you and not shared across services.

These facts mean that API keys, properly implemented, have a much smaller attack surface. You need not worry, for example, that a three-year-old backup file that someone harvested out of the trash at your ISP has valid API keys on it. The window for attack is, in fact, limited to "someone has stolen a very fresh copy of my live DB, but I have not yet realized it, and there is still something valuable left to compromise other than the data in my app's live DB." And this window often isn't very important. Often, closing it is akin to reinforcing the barn door after the horse has bolted and the barn has burned to the ground.

Passwords, on the other hand, get reused. You are using bcrypt to hash passwords not just to protect your app, but to protect your customer Gmail accounts that share the same password.


In common usage the user will take an server generated API key and embed it within their application that makes API requests. Take a very typical example of a merchant selling snowboards and using Stripe to process the payments as an example.

Since this API key is embedded within their app it'll require a programmer to change (and customers often may be non technical with sites built on contract). These are things you dont want to force customers to change with any frequency as it can cause pain and expense. You dont want to ever be forced to flush all your API keys, it could be a serious disaster.

Now there's protocols that rollover access keys hourly or the like such as OAuth a but that's a complex and often unnecessary use case that's beyond most API implementors. See how Google does OAuth 2.0 with their APIs for an example.

Since it's secure, simple and performant to hash API keys stored in your DB and just compared hashed values for authentication why would you ever not want to do it?


If you lose the database containing either your API keys or hashes of your API keys, you need to revoke the keys. Not doing so is negligent.

The correct next step after discovering that you may have lost custody of API key information is to ensure that the keys are worthless, not to scramble to try to protect the keys.

This is another reason you want to be clear about the difference between a "key" and a "password", because passwords are sticky. A benefit of working with keys is that they are not; you can zorch a key with minimal provocation.


If you lose your DB you're in trouble regardless. We're talking about the level of trouble here. I'd rather be faced with a 30 day key rollover of all my users than a forced immediate change.

I dont see any reason to continue the argument. It's clear to me that you should hash your API keys in your DB.


You do not need to obfuscate your API keys if you're generating them properly.


Would you mind enlightening us? If you're using API keys over TLS+HTTP Basic Auth, storing the plain API key in your database means that anyone with readonly access to the API key table can now use those accounts. (Ignoring IP filtering or something.)

What am I missing?


If an attacker gets access to the key table, you are boned. Revoke all your keys. Make the keys worthless; don't take half-measures to try to protect them.


... I agree if you know an attacker has access then you should revoke. Just like if you know an employee has been compromised. But why wouldn't you store them hashed, anyways? So that if an employee has to debug something and selects more than they should, your system is not compromised?

Also, I'd say that a SHA256 hash of a 256-bit key is hardly a "half-measure". Nothing short of compromising your RNG or SHA2 will make those hashes useful to authenticate.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: