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.
Suppose we're talking about an app where users can post events. Each public event has a page at /event/<uuid>. So any malicious user can trivially find the id of an existing event. 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.
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.
> Suppose we're talking about an app where users can post events. Each public event has a page at /event/<uuid>. So any malicious user can trivially find the id of an existing event.
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.
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.