Limiting results to a given type

This is heavily related to modelling types (e.g. How to model entity type? - #5 by tatut), but with focus on security and performance.

So how would you design the data and queries to make sure that nobody can access documents of wrong type? For example when some kinds of documents are public, and thus don’t need authorization while others do, and are “top level” so that the queries don’t flow from the graph (like public resources linked to the current user).

After a bit of thinking I see three ways to go about this:

  1. Just count on UUIDs being so hard to guess, that nobody could manage to abuse the API to fetch documents of any other type.
  2. Use xt/entity to fetch the document, and then check in code that the type matches
  3. Put the type in the :xt/id, e.g. [:type-a uuid] or {:type-a/id uuid}
  4. Put a type field ({:type :type-a}), or a type-namespaced id in the document ({:type-a/id uuid}), and always use queries with :where clauses to get the documents.

I’m assuming that option 1 would be fastest for looking up a single document, but it doesn’t actually enforce thinking about the type.

Option 2 might be a bit slower (since the ID is now somewhat larger), but you simply cannot retrieve the document (with xt/entity) without being explicit about the type (unless you leak the :xt/id structure outside the db implementation. This explicitness is both a benefit and a downside. Separating an db internal id (that you would use when linking documents) and an external id seems tricky and I can foresee bugs where the id leaks and the incoming ids are sometimes in the external format (like plain UUIDs) and sometimes in the internal structure.

Option 3 would seem slowest (haven’t tested) and doesn’t enforce thinking about the type, but is the only way I can see if any kind of “fetch all” functionality is needed.

2 Likes

I know the implementation is based on C# Entity Framework, but there’s still some good ideas here that can be applied to data authorization in general: Part 4: Building a robust and secure data authorization with EF Core – The Reformed Programmer

1 Like

One limitation of making the type part of the document id [:type-a uuid] or {:type-a/id uuid} is that you are limiting a document to be only one type of thing. For the app I’m working on I went with namespaced fields, so an entity/document can actually consist of multiple types if needed.

2 Likes