securitydatabase-designsoftware-designaccess-controlrole-based-access-control

API and Database Access Control Architecture


I am trying to implement access based control for a Survey app but having trouble designing a functional architecture. It seems like DAC would be a good fit for what I am trying to do, but am unsure.

Hierarchy

Survey Series -> Multiple Collection's of Survey's (1 survey that multiple people have to complete) -> Survey.

Examples

I have Survey Managers who need to assign collection creators. Collection creators assign users to a survey belonging to a collection. Each User can have different access controls based on each Series, Collection or Survey.

Summary The access should be hieracle. Every record (Series, Collection, Survey) would have its own set of access controls [Create, Read, View, Update] that users delegate. Could I get some help with designing a model?


Solution

  • Unfortunately, implementing a complex and hierarchical authorization model like this within a database is... not simple. Given the requirements presented (similar roles across multiple resource types), and the need for “inheritance” of those roles, I’ve outlined a possible model to store the roles:

    Name Kind Description
    user_id Foreign Key The user that has this role
    role Enum The role
    survey_id FK or NULL The survey to which the role applies
    collection_id FK or NULL The collection to which the role applies
    series_id FK or NULL The series to which the role applies

    Each row in the table would contain a user, their role, and one of the {survey, collection, series} to which the role applies. This would allow your application to easily lookup the role (which are standardized) for the given resource you are checking. This is a pattern similar to Generic Foreign Key in Django. However, it still leaves one key problem: the heirarchy.

    One option would be define a function in your code that knows which roles to lookup for each level of your heirarchy, so if it is given a survey, it looks up the roles for the user in all levels (survey, collection, series) and returns the role with the greatest access to check against. Otherwise, you'd likely need to make use of a series of joins to select all the roles for the user and the incoming resource, which could become very slow as your tables grow larger. This also only works if your roles remain the same at each level; otherwise, you'll find yourself quickly having to compare different enumerations of roles.

    Hierarchical questions of these sorts appear in permissions checking often, and your unease is a recognition of that fact that its tough to map them in traditional relational databases: permission relationships are, at their core, a graph, and relational databases were not designed for easy traversal of graphs.

    As a result of this complexity, there are services (this one is mine) that abstract away this complexity for you, so you can define your roles and relationships and not have to worry about the traversals. As a demonstration, I took the requirements you listed above and wrote an example in our playground, which might help you visualize and test these relationships.