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

The article appears to say that you must sign your requests with a symmetric key. To verify the request, the server needs the same key, right? So the server needs a copy of every single user's encryption key.

The server _could_ just store the keys plaintext in a database but I'm assuming we can agree that's a horrible idea. The best it can do is encrypt them symmetrically before storing them, using an extra-special secret key that needs to be protected very carefully.

With username/password authentication, we don't store symmetrically encrypted passwords, do we? We store a one-way hash of the passwords instead, because symmetric is deemed not-good-enough.




The server is trying to validate that the thing it gets back is the thing it previously sent out, so that's a different model. What concretely are you suggesting we store as if it was a password? The serialized JSON object?


I'm beginning to think you're trolling, but... I'll make one last attempt to explain: How does the server verify the signature? Does it just wave a magic wand? Doesn't it need the same key the user used to sign the request?


As I mentioned in that comment: the thing sending is also the thing receiving, just at a later point. So "the same key the user used to sign the request" doesn't seem to apply.


It seems like you're describing a specific use case that is different from what most readers think of when they see a post about cryptographic signatures.

If the server generates the token, and all it's effectively doing is verifying that the client has the correct token, then what is gained by making that token be a signature of any sort?


You no longer have O(n) server-side storage proportional to your number of clients, the way you would if you put each token in a database. You also no longer need to worry about consistency + availability of that database if you have multiple web servers. If one web server in your cluster generates a signed token, and another one verifies it, they have the same key (they have exactly one key, among all of them) and it works without any communication or storage between the web servers.


That's fair, although it doesn't allow tokens to be revoked or to expire. For that you'd need to store at least some unique part of the payload you're signing, and then you have O(n) storage requirements again, right?


> or to expire

Add an expiry time to your signed payload. Tokens can have metadata.

> If the server generates the token, and all it's effectively doing is verifying that the client has the correct token

I think you might be understanding "token" as the API tokens that are just a random bunch of bytes that are later matched to authenticate like they were a password (let's call them "passtokens", I don't know if they have a name).

Tokens can be far broader than that. For example, JWTs contain arbitrary data. Verifying that the token is valid is just verifying its signature. You wouldn't check that the passtoken matches (in fact, you wouldn't have a passtoken at all). The payload is where the sauce is at.

A payload can include anything, from an user id (which is similar to the passtoken use case, authentication) to a list of grants (so you wouldn't even have to hit the "users" table to check for permissions... or even have access to it! As long as you can verify the signature.)

> to be revoked

That's true though. This is usually handled with short-lived tokens that must be renewed periodically.

Alternatively you could have a Token Revocation List of some sort (which isn't O(n) storage since 1. not all tokens will be revoked and 2. you can purge expired tokens). But then you get the problem of synchronizing the TRL across services (or centralize the token verification in a service which IMHO kinda defeats the purpose).


The way I'd approach this is to treat "revocation" as meaning "after this user's current tokens expire, they can't refresh them," and make the token lifetime short enough that you're comfortable with it. Document that any API call can also include a "new_token": {...} field, and the client should update. On the server side, only try to refresh the token when it's close to expiring, and don't fail the API call if you can't reach the revocation server (just skip refreshing).

You still have a central server to track account status, but now it can be more like "a text file with a list of usernames on a single box running Apache, if it crashes we reboot it" and less like "a distributed, high performance, highly-available in-memory K/V store that's in the critical path for every request," which is going to make you a lot happier operationally.

Or you can push the list of usernames to revoke to each server, or something.


the user isn't signing anything. the server is signing something it sends to the user. when the user sends it back to the server, the server checks the sig to make sure the user didn't alter/forge it.


> The article appears to say that you must sign your requests with a symmetric key. To verify the request, the server needs the same key, right? So the server needs a copy of every single user's encryption key.

Correct. Usually if this was in a app and they use a symmetric key and they wanted to sign requests from a first-party app, in the real world this key is heavily obfuscated to ward off reverse-engineers from lifting the secret. The server will then decrypt this request with the same symmetric key to determine if it is indeed from the client and not a third-party.

As the author has outlined in the article, some of these API services use standard algorithms to do this such as HMAC while other services go to the extreme to use whitebox crypto + obfuscation. This is just security by obscurity, but it is for the purpose to slow down the attacker.

For example, when a app developer release a new app that uses a new API version, they can rotate the keys to slow the attacker down and can keep compatibility with the v1/v2/v3 versions with different keys and can choose to deprecate a endpoint without breaking the app.




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

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

Search: