2. the UUID by itself doesn't authenicate or authorize anything
3. there is a small chance of collision, and it can be handled on the backend/persistance/DB layer, i.e. return error to the client in case of collision and ask to generate a new UUID
4. many non-trivial and/or CQRS/ES apps work like this
5. if you are really paranoid, you can push down UUID generation logic to BFF (Backend-For-Frontend) layer
6. Lots of DistSys problems can be solved with client-generated IDs. But most people mistakenly think that DistSys applies to backend only, and exclude clients from the picture.
7. Scaling RDBMS (especially Postgres) is hard. UUID generation is slower than serial bigint, so it's best to keep it outside DB layer fo this reason also.
8. Client-generated UUIDs help to make client requests idempotent, and enable error handling with retries (although it's better to add an additional layer of request idempotency with IDEMPOTENCY_KEY HTTP header, or GraphQL Relay's clientMutationID).
the malicious actor will need to somehow get the authorized session first, then get the real UUID which already inserted into the DB.
And now she will be able to do DDoS by replaying create_entity requests with already existing UUID.
But ... the same scheme equally applies to server-generated IDs also when used for updates instead of insert/create (even if there is a translation layer between internal and external IDs) ;)
In my implementations this create_entity will also have an idempotency key, so after first successful request, the replayed/retried requests will hit the cache only, and skip the database.
In case the attacker will also change idempotency_key for each replayed request, then the only remedy is to monitor for this scenarios, or reject requests with the same {sessionID, requestName, enitityUUID} and different idempotencyKey-s over short time intervals.
But again, this equally applies to any type of server-generated ID.
I'm not saying this is a big issue, but saying "P_collision = 1 / 2^122" is misleading and gives a false sense of security. P_collision is 100% if a malicious user can specify any id they want and wants to specify a colliding one.
I don't understand why you're bringing in idempotency keys. The way to fix this is to reject client generated ids that already exist.
This is bad UX and bad design, usually human-readable event slug will be shown in the URL.
But I agreed that since UUIDs are not encrypted, they can be acquired by the attacker (but this equally applies to any other unencrypted data handled by the client).
> Suppose there's also an api where you POST a JSON body to /api/v1/event to create an event. This uses a client generated ID so the body contains the title, location, etc and the supposedly newly generated id. A malicious client could submit an existing uuid instead of generating a new one, and the server would need to reject this.
Again this is bad design, and the attacker will also need to either hijack the session, or to steal JWT token.
> I'm not saying this is a big issue, but saying "P_collision = 1 / 2^122" is misleading and gives a false sense of security. P_collision is 100% if a malicious user can specify any id they want and wants to specify a colliding one.
I agreed with you, but the attacker can copy any ID, including server-generated ones. So I don't understand the problem. Any external data need to be validated be it client-generated or server-generated. Do you claim that somehow validating UUIDs for uniqueness in the DB layer is more expensive than any other validation of the external data?
> I don't understand why you're bringing in idempotency keys. The way to fix this is to reject client generated ids that already exist.
Please read again, yes all external data need to be validated, so it equally applies to server-generated IDs (only they will need to be validated on UPDATE-s and DELETE-s instead of INSERT-s).
Idempotency keys just reduce the load on the hard-to-scale RDBMS database layer, so it will not be hit on every retry or replayed malicious requests.
Sure you are. You're trusting the client to send you valid data.
> 2. the UUID by itself doesn't authenicate or authorize anything
Okay, better hope no one ever considers the UUID to be a unique randomly generated token.
Besides that, users might be tempted to submit "vanity" UUIDs if they get to decide their own identifiers, breaking assumptions about the system.
> 4. many non-trivial and/or CQRS/ES apps work like this
Cool, if your friends jump off a bridge, you gonna follow them?
But client-generated IDs make idempotency easier and remove whole classes of errors. They're typically a huge win.
Reason: I'm not a machine, so I dislike generating UUIDs by myself ;)