Why you should add UUIDs to your database entities

UUIDs (Universally unique identifier) can be used to uniquely identify a record along with the entity’s identifier, but without exposing the auto-incremented ID of the record.

António Pereira
KinetIT
6 min readJun 28, 2022

--

Photo by Tim Evans on Unsplash

In OutSystems, by default, when creating an entity, the platform creates an auto-incremented number (of type Long Integer) attribute as the primary key of an entity. This auto-incremented number starts from 1 for the first record of the entity, 2 for the second…, and so on.

Often, after the entity is created, it is common to create a screen to edit the data of that entity’s records. In that screen, there exists an input parameter of the type of the entity’s identifier to be able to fetch that record and access the data to show on the screen.

Usual screen signature to read/write an entity’s record

For this example, the resulting URL would be

https://<domain>/<Module name>/Employee_Detail?Employee_Id=1

(For the first created record).

Up until here, nothing new, and everything works as expected. Everyone is happy!

Photo by Tim Mossholder on Unsplash

Wait…maybe you shouldn’t be so happy!

This approach brings some hidden caveats. One of the major issues of this approach is the exposure of the record ID. Since it is a sequential number, anyone can change the URL query parameter and replace it with another number to check what happens. In some cases, when data from other records shouldn’t be seen, and there is no validation, we are making it easier to access and see that data. This is worse when that data is sensitive (e.g., banking account balance). As you can imagine, it’s a major security flaw.

In some cases, when data from other records shouldn’t be seen, and there is no validation, we are making it easier to access and see that data.

Another caveat that you shouldn’t neglect is the fact that you are exposing the number of records of an entity. This can have an impact on the business side. Can you imagine another competitor checking how many records you have in a specific table (e.g., number of clients). The business department wouldn’t be happy.

The safest development to avoid this would be to avoid data from being fetched when the user has no read permissions. Even when validating the user’s permission to read the data, it would continue to show the identifier number of the record, not good.

How does using UUIDs fix this?

First of all, what is a UUID? A universally unique identifier (UUID) is a 128-bit label used for information in computer systems. The term globally unique identifier (GUID) is also used.

When generated by standard methods, UUIDs are (virtually) unique. Any system can create a new UUID, there is no need to communicate to a central registration or authority responsible for generating or managing them. So, two UUIDs can be the same, but their probability is close to zero to be considered an issue.

Thus, anyone can create a UUID and use it to identify something with the near certainty that the identifier does not duplicate one that has already been, or will be, created to identify something else.

Regarding format, it is represented by five groups separated by hyphens, in the form 8–4–4–4–12 for a total of 36 characters (32 hexadecimal characters and 4 hyphens). For example:

123e4567-e89b-12d3-a456–426614174000

The suggestion here is to add a Text attribute to the entities which will contain the generated random string (UUID) for the record. Each time a new record is created, a UUID is generated and assigned.

The entity with the UUID attribute
Properties of the UUID attribute

In OutSystems, you can generate a UUID by using the ‘GenerateGuid’ from the (System) module.

Where to consume the GenerateGuid action

Before setting the values to the record that will be stored, call the action to generate the UUID. The output of this action will be the UUID that you will assign to the UUID attribute of the record.

Flow’s node sequence to generate a UUID
Assign the record to save in the DB

If we replace the URL above from using the record ID to a UUID (from a sequential number to a random string) the URL will look like

https://<domain>/<Modulename>/Employee_Detail?UUID=843cd48b-d871–4264–9f92-fff6529c0dff

Signature of the Detail screen using the UUID to filter the record

There isn’t a number or letter that comes after (or before), since it’s a random and non-sequential string. In case the development teams forget to validate user permissions to read data of a record, it’s “almost” impossible for someone to exploit this vulnerability.

What happens to the old entity identifier?

In my opinion, the usual entity identifier continues to be important. Using the sequential entity identifier as the primary key is important since, like a long integer, it is more performant in queries that use the UUID attribute (text). To reduce the performance impact, the UUID attribute can be indexed.

When to use the UUID or the entity ID?

The UUID should be used to identify a record when there is a “public” exposure. This is an example of a screen where the identifier attribute is an input parameter or an exposed service (REST/Soap or even Service Actions).

After the code flow passes the exposed part, the entity ID should be fetched and used after on. An easy example is a Detail screen (”Employee Detail”). To access the screen, the UUID is provided, but once the code flow is inside a server action, the ID should be used to identify the record.

Fetch of the record to use in an action using the UUID
The filter used in the aggregate

P.S.1: In case you need to generate a UUID in a client action (Reactive or Mobile) you can use the following components:

P.S.2: Another alternative to UUID is to use Nano ID which claims to be safer, more compact, and faster than UUID. In OutSystems Forge you can find an implementation of Nano ID.

P.S.3: You can check the implementation of an entity and its CRUD actions while using the UUID in the How to CRUD component in OutSystems Forge.

P.S.4: Shoutout to Justin James, since after I wrote this article, I found another article for the same subject in OutSystems written by him. I hope this article can complement the info written there.

Thank you for reading!

If you enjoyed this article, share your feedback and comments. Follow me for more articles about OutSystems, technology and random stuff I decide to write about.

--

--

António Pereira
KinetIT

Father, husband and professionally focused on delivering value to clients by solving their challenges using the amazing OutSystems Platform.