6 ms·
Better still, don't use passwords in your API at all. Passwords are for humans. APIs use keys. You make great points, but just as a point of clarification (bec
by corresation 14y ago
Better still, don't use passwords in your API at all. Passwords are for humans. APIs use keys.
You make great points, but just as a point of clarification (because I saw numerous people confused by this yesterday), this is merely nomenclature, no? What you are calling a key is really a long, random password (in Amazon's case the secret Access key).
- mechanical_fish 14y agoNomenclature is important. As the joke says, naming things is one of the only two difficult problems in computing. [1] A good password is a long string of random characters, and an API key is a long string of random characters, but they are not the same because the semantics are different. Passwords are typically chosen by customers, changed (let's be honest) very rarely and on a haphazard schedule, often reused across a bunch of different systems no matter how frantically we wave our hands, and (most important of all) have "user" semantics and scope: a password lets a user log in and do logged-in-user stuff. Whereas an API key can be issued by the system, and is thereby guaranteed (assuming a clueful programmer) to be long and random and unique and not shared with the customer's Gmail account and bank account. You can expire it often. You can issue more than one per customer. (With passwords, this is theoretically possible but practically impossible; customers barely understand how to handle one password.) You can issue it to entities that aren't themselves customers, and that don't have "user" semantics. You can scope it to particular uses, issuing a key that is only good for checking balances but not for initiating transactions, for example. --- [1] The other being cache coherency. And avoiding off-by-one errors when enumerating lists.
- poutine 14y agoYou 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.
- tptacek 14y agoExactly what is the point of obfuscating single-purpose API keys at all?
- corresation 14y agoDoesn'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.
- mechanical_fish 14y agoI 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.
- poutine 14y agoIn 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?
- Joeri 14y agoArbitrary distinction. A password can be expired and forced to comply with complexity rules. A key is a server-side generated password, and therefore offers less ability for users to implement their own password policies. Good for users that don't care, bad for users that do care.
- poutine 14y agoThis is not arbitrary at all and has definition by industry standards. Passwords are used by people. Keys by machines. This requires different security policies. Passwords will have complexity rules and shorter expiration policies such as 90 days. Keys should have rollover policies around a year or so.
- corresation 14y agoYou say that it has definition by industry standards, but no such standards exist: There is no standard on the complexity or expiration policy of either passwords or keys. There is no standard on rollover policies.
- poutine 14y agoIncorrect. The PCI-DSS is an industry standard that everyone who touches credit cards must adhere to, which I suspect is a good portion of the audience here. https://www.pcisecuritystandards.org/documents/pci_dss_v2.pdf https://www.pcisecuritystandards.org/documents/pci_dss_v2.pd... See section 8.5.9 for the password change policy. Section 3.6.4 for the key rollover policy (which references NIST 800-57 that basically says 1-3 years for most keys. There's other standards (such as the 1-5 years for an SSL certificate from the issuer) and tons of best practices out there. In short you should be rolling over keys and expiring passwords on some sort of schedule. My point was that because humans use passwords they are conventionally seen as needing quicker expiration than keys.
- corresation 14y agoThe PCI-DSS deals specifically with cryptographic keys used to protect CC details. It is in no way a standard for API keys. Even then it is enormously vague in its rules. There are lots of organizations with notions about passwords and keys and ciphers, etc. However in the context of this discussion I don't believe there is anything that could be considered a standard.
- e12e 14y ago>> Better still, don't use passwords in your API at all. Passwords are for humans. APIs use keys. > this is merely nomenclature, no? What you are calling a key is really a long, random password Both passwords and keys are shared secrets. A password is a secret a human remembers, and can prove he/she remembers. A key is something a machine stores and can prove it has. (Actually, an API key can also be a token, eg: "{ hash: " + hash(key+salt+date(now))+"valid from: " + date(now) + "salt: " + salt + "}" -- that is -- if you know the key, you can verify that that the token is indeed valid from the date claimed (and you could add serial numbers and other stuff as well). Note that the user doesn't need to know the key in this case, the user only needs a copy of the token). So yes, it is nomenclature, but it matters. [edit: formatting, typo]