Designing an Authorization System: a Dialogue in Five Scenes

This posting’s setting is a blatant ripoff of perhaps the best technology overview document ever written (on Kerberos):

Designing an Authentication System: a Dialogue in Four Scenes


This dialogue provides a fictitious account of the design of an open-source authorization system called “Haros”. As the dialogue progresses, the characters Athena and Euripides discover the problems inherent in applications using common authorization systems.

When they finish designing the system, Athena changes the system’s name to “Apache Fortress“, the name, coincidentally enough, of the authorization system that was designed and implemented at Apache’s “Directory Project“.


  • Dramatis Personae
  • Scene I
  • Scene II
  • Scene III
  • Scene IV
  • Scene V

Dramatis Personae

Athena a newly promoted director of IT security and a people person.
Euripides a longtime programmer specializing in security and reigning curmudgeon.

Scene I

A cubicle area. Euripides is working on a project rollout, for a new financial system.  Athena’s walking the floor with several other executives.  She finds Euripides in the farthest corner, away from the elevator.  All of the windows are covered and the lighting is muted.

Euripides: [clearing an old pizza box from the stained guest chair] Hey stranger!  Haven’t seen you in a while.  How’s life as a corporate bigwig?

Athena’s in distress but trying to conceal it.  Before the promotion, she and Euripides worked on several projects together, the most successful, a Kerberos authentication system.  Despite his gruff exterior, she’s learned to trust his candid viewpoint, particularly on security.

Athena:    [gingerly sitting down] Not so great Rip.  Our common security authorization system totally sucks.  It’s tightly bound to the application data model and can’t be reused. It’s impossible to separate the security policy data from the business data.  We’re going to have to build yet another authorization system for this new banking project you’re working on.

Euripides: [munching on a donut] Why are you telling me?  I’m just a programmer.

Athena:    [rolling her eyes] If only there was a way to externalize security policy so that it doesn’t taint the business model. That way we could have a common fine-grained authorization system that works across every application, on every system.

Euripides: [licking his fingers] We’ve been asking for one of those for as long as I’ve been here.  It’ll happen when Hades freezes over.  Here, have a donut, you’ll feel better.

Athena:     [cringing] No thanks.  I think it’s time to ask the Gods.  Maybe, this has already been solved and we can save my team the odyssey of creating a new one.

Euripides: [eating another donut] Good luck [muttering under his breath] you’re gonna need it.

Athena:     What’s that?

Euripides: Uh yeah, tell ’em we’re gonna need more donuts down here.

Scene II

Euripides’ cubicle, the next morning where he periodically spaces out while reading email.  Every so often, he’ll respond with a cryptic and/or sarcastic one-liner. A strong proponent of a style of discourse known as ‘cartoon-speak’, points are added for comedic effect.  Athena knocks on the cube wall startlingly him into the present.

Athena:     [excitedly] I found the answer to our entrenched authorization problem!

Euripides: [stifling a yawn] Isn’t that special.  [feigning interest] That sure didn’t take very long.

Euripides moves a brown paper bag oozing some kind of liquid from the guest chair and motions for her to have a seat. The bag has an odd odor.

Athena:    [with a crinkled nose, electing to stand] As it turns out this problem has been studied for a very long time, like for ages. Almost as long as you’ve been a programmer, not quite.

Euripides: [perking up slightly] Really?

Athena:    Right, there’s a research deity called NIST and they have many priests who sit in an ivory tower handing down directives for those of us living in the ‘real world’.

Euripides: I hate it when that happens.

Athena:    I know right? So, the model I found is called Role-Based Access Control, and it’s governed by a specification from another powerful deity, ANSI, called INCITS 359.

Euripides: [sarcastically] That’s a real catchy name.

Athena:    We’ll just call it RBAC for short.

Euripides: Isn’t that what our systems already use for file permissions?

Athena:    Sort of, not exactly. There’s a bit more.

Euripides: Like what?

Athena:     There are Users of course. And Groups, but they’re called Roles.

Euripides: [rubbing his belly] Like for dinner?

Athena:     Very funny.  Roles are how Users are assigned to Permissions. Permissions are a combination of Resources and Operations.

Euripides: Sounds simple enough. Again, how it’s done in Unix.

Athena:     Not quite. There’s also an entity called a Session. After a User logs in, one or more assigned Roles are then activated into a Session.

Euripides: [skeptical] That’s just great. We’ve added a useless step and state must be maintained. What’s the point?

Athena:     [patiently] It’s keeping with the principle of least privilege. The User’s given the minimum authority to complete her meal, err tasks.  Think about vacations or maternity leave. Do they need to be allowed access then?

Euripides: No, I suppose not.

Athena:    What I’ve described so far is known as RBAC0. The absolute minimum in order to be compliant.

Euripides: [sighing] Wait, there’s more?

Athena:    Still digging. Let’s talk later.

Euripides: [muttering under his breath] Thanks for the warning.

Athena:     Huh?

Euripides: Oh, was just saying, it could be rewarding.

Scene III

The next morning, Athena catches up to Euripides at the Starbucks kiosk inside their campus. He’s awaiting an order, plugged into a headset, seemingly preoccupied, and perhaps doesn’t see her. She has to tap him on the shoulder to get his attention.

The two grab their coffees and head over to the condiment bar, to pour in some creamer, before tucking into a nearby booth.

Euripides: [loudly slurping coffee] Well that sure didn’t take very long.

Athena:    [wincing] Got it all figured out. Do you want to hear the rest of the story?

Euripides: [standing up to go] You mean, I have a choice?

Athena:    Very funny, have a seat Rip. It didn’t take long because it’s simple. Where were we? Oh yeah, going over the RBAC model.

Euripides: I’m captive, err — captivated.

Athena:    [clears throat] RBAC1 is for Hierarchical Roles. That’s where we place inheritance relationships. They can be related.

Euripides: Like some kind of weird family?

Athena:    Sort of. Think about when it comes time to assign the Roles to Users, sometimes referred to as ‘Role engineering’. It’s a pretty tricky task as you might imagine. There are many levels of access to consider. A Role can be a kind of module, and linked to others via inheritance. Perhaps Engineers need to also inherit all of the permissions that a normal User gets, plus everything that is normal for them.

Euripides: [caffeine kicking in] I see. It saves the trouble of having to constantly update all of the Roles anytime the Permissions change for a particular use case. Say we don’t want Users to be able to log into System X, we don’t have to change every Role, we only need to change the one. The others will realize the change automatically via inheritance. Also, the security administrator doesn’t have to understand that an Engineer is also a User. They just assign them the one, and that includes the other.

Athena:    [smiling] Very good Rip! See, you secretly like this stuff — don’t you? But wait, we’re still not done. RBAC2 is Static Separation of Duties. This is where we establish mutual exclusion constraints between assigned Roles.

Euripides: Uh oh. Now we’re getting complex.

Athena:    It’s not all that bad. Basically, we can define sets of Roles and establish a cardinality between them. That is out of particular set of Roles, how many can be assigned to a User.

Euripides: Why would we care about that?

Athena:     Think about how conflicts of interest can arise in everyday scenarios. For example, we don’t want the person who writes the checks to also approve them.

Euripides: I still don’t get it.

Athena:     Someone could write themself a check, approve it, and it’d get deposited into their personal bank account, illegally.

Euripides: Ah, that makes sense.

Athena:    RBAC3 is Dynamic Separation of Duties. It’s basically the same concept only with activated Roles not assigned.

Euripides: Oh, here we’re back to the Session right? One can either write the check or approve it, but never both for the same check. They can both be assigned to a User, but can never activate them together into a Session. There’s a toxic relationship there.

Athena:    Whoa, you’re really getting the hang of this Rip!

Euripides:  [pleased but trying to be gruff] Yeah, maybe.

Athena:     That’s pretty much it. Now, we go in front of the architecture review board and try to convince them to use RBAC inside all of their business apps. Hopefully, we can stop writing throwaway authorization code every time we build new apps.

Euripides: Good luck with that.

Athena:    Why do you keep saying that?

Scene IV

After not hearing from Athena for a week, and no sign of her on slack, Euripides gets worried, and tracks her GPS location on Google to a courtyard inside their business campus, overlooking a large pond.  He finds her slumped over a park bench by the shoreline, in obvious despair.  A flotilla of turtles nearby, observing the scene somberly.

Euripides: Whoa!  Look alive there sailor!

The turtles scatter.

Athena:    [Lifting her head up] I was eaten alive by the board.

Euripides: How so?

Athena:    They hated my idea.  Told me they already understood RBAC, and it’s stupid.

Euripides: Why do they say that?

Athena:     They called it quaint and said it hasn’t worked in the ‘real world’ for a long time.

Euripides: Did you tell them the NIST control the real world?

Athena:     [tearfully] They said it’s nearly impossible to externalize because security is tightly bound to the application’s business rules.  For an RBAC system to compensate, its Roles would explode, making a huge mess.

Euripides: What in hades are you talking about?

Athena:     It happens when context is introduced into an RBAC policy.

Euripides: Context… like attributes and such?

Athena:     Yeah, like in our baking scenario, I mean banking, we have an attribute associated with the location of the financial institution, or branch. There are over 1,000 separate locations today and our business plan calls for 10X that over the next few years. How do we specify that someone can be a Teller in one location and not in another?

Euripides: That’s easy. Just create Roles with the location as part of the name. Say Teller-North123 and Washer-South456.

Athena:    That’s what I told them too. But they said the number of Roles gets multiplied by the number of locations. So if we have two Roles: Teller and Money Washer, and 1,000 locations, we end up with over 2,000 Roles to manage!

Euripides: Ay yi yi I see the problem.

Athena:    The architects say the only way to fix it is to join the policy entities, i.e. User, Role, and Perm, with the Bank’s data, that includes its locations. It’s hopeless because every application must have its own policy engine, one that understands its particular data model.

Euripides: Sounds like we’re back to square one. Now what?

Athena:     Well, they’re talking about this new kind of authorization system called Attribute-Based Access Control, or ABAC. It downplays the Role. Everything is just an attribute, that can then get linked with a User at runtime.

Euripides: I mean, isn’t that just an Access Control List?

Athena:     Well yeah, but there’s more, like dynamic policies. In ABAC, policies are expressions in which the various linked attributes are combined with the traditional security entities like Roles and Resources.  Let’s say that I have a policy where the ‘Teller’ Role is still required to gain access to a cash drawer at a financial institution. We can also link additional attributes, like location. These attributes can come from anywhere.  Something from the runtime environment, like location, time, IP address, platform, temperature of processors. Attributes also come from the the application domain. Things like hair color, favorite type of beer, how many donuts eaten yearly, literally anything under the helios.

Euripides: [stepping onto a soapbox] Ah, the old loosey-goosey. No common data schema. Makes it almost impossible to audit or even validate input. No thanks. Been there, done that. Let me tell you about back when …

Athena:    [cutting him off] You haven’t even heard the worst of it yet. The most popular ABAC systems use XML to transmit the data between their intermediaries.

Euripides: [retracting in horror] That’s bloody awful.

Athena:    [despondently] If only there was a way to combine RBAC and ABAC. We could keep our common security data model and policy engine and combine a few attributes, like location, as needed.

Euripides: And you think the NIST high priests allow it?

Athena:    I don’t know but I’m going to find out.

Euripides: Good luck.

Athena:     Stop saying that.

Scene V

The following week at Euripides cubicle.  Athena knocks, startling Euripides from a mid-afternoon siesta.

Euripides: [groggy after a 3 IPA lunch] There you are. How’s it going … have you found a solution to your exploding Roles?

Athena:    [grinning] I sure did, and the architecture board has approved my plan for externalizing authorization.

Euripides: Wuff.  How’d you manage to pull that off?

Athena:     It was surprisingly easy.  First, there’s nothing in RBAC that says that attributes aren’t allowed. So from a standards perspective we’re in the clear and the NIST priests say the Gods won’t hex our offspring.

Euripides: [nervously looking at a framed portrait of a dog on the cubicle wall] Oh, yeah, that’s good.  Did they tell you how?

Athena:    Yes. There’s the user-role activation phase… back to our Banking example… remember the two Roles and 1,000 locations?

Euripides: [groaning] Like it was yesterday.

Athena:    As we learned earlier, in RBAC, assigned Roles must be activated into the Session before a particular User can perform operations on the Role’s corresponding resources.

Euripides realizing he’s famished, snatches a cookie wedged against a burger from a day-old takeout box on his desk, almost takes a bite, thinks better of it, (trying to be nice) offers it to Athena, who vigorously shakes her head and frowns. He then shrugs and begins eating it, a bit of ketchup hanging from one side dropping onto his shirt.

Euripides: [with his mouth full] How could I forget?

Athena:     [disgusted] Anyway, we can add a constraint during activation to detect whether the Role being activated matches location. For example, only activate the Teller Role for Curly when he’s at the North branch.

Euripides: [drinks from a room temperature two-liter bottle of mountain dew burping with gusto] ‘scuse me. That’s the policy but how is it enforced?

Athena:     Could … you …

Euripides: Wha?

Athena:     [waving her hands] ew! Just … never mind. We’re making the constrained Roles special to the system. The policy engine has to know when activating any Role, that it might have a dynamic constraint placed upon it. Here, a property associated with the Role’s name will do quite well.

[clears a tiny space on the cluttered whiteboard and begins drawing]:

Role: Teller:locale

Role: Washer:locale

Euripides: This covers how the authorization system knows when to check for a dynamic constraint, but where will the actual attribute values be stored?

Athena:    On the User’s entity of course. With RBAC, there is already a User-Role assignment that is bound to the User entity. We simply need to place a couple of delineated properties on that assignment. For example the Role assignment looks like this:

[draws on whiteboard]:

User: Curly

Role Assignment: Teller:locale:North123

Role Assignment: Washer:locale:South456

Euripides: We’re still missing a piece here. How does the authorization system get the current valid values of a dynamic constraint? For our scenario, which locale they’re in?

Athena:    It just pushes that into the runtime context…

[draws on whiteboard]:

Session session = createSession("Curly", "locale:North123");

Euripides: Ah!  Now, when the runtime activates Curly’s Roles, it knows that they’re special and will compare the value of the constraint pushed into the API with that stored on the User-Role assignment. Here, Curly will be a Teller because we’re in the North, right?

Athena:     That’s right. There really is more to you than your curmudgeonly demeanor suggests.

Euripides: [with a bit of ketchup still on his shirt] It’s hard to be humble. What’d the review board have to say?

Athena:    [handing him a napkin] What could they? We’re pushing into the financial system as we speak. The Bank’s pleased because we’re not spending money on a new ABAC system. We just tweaked our RBAC system and we’re good to go!

Euripides: [rising up] The Gods must be pleased! Maybe they’ll hand out raises this year!

Athena:    Good luck.

Who put ABAC in my RBAC?

Readers know that Attribute-based Access Control (ABAC) is a bit of an obsession with me.  It stems from the want to have something like an ABAC system in my little bag of tricks.  An authorization engine that scales to everyday usage, without proprietary, bloated or cumbersome baggage to weigh it down.

So I comment, lament and nothing seems to come of it.

Until I leaned that ABAC can be combined with RBAC.

We like RBAC, use it in our everyday applications, but it has some serious shortcomings, and we don’t know what to do about them.

ABAC also good.  It’s adaptable, but lacks meaningful standards, we struggle during implementations, and are left wanting more.

Now, let’s somehow combine the two.  Hopefully allowing the strengths of each to be preserved while eliminating their shortcomings.

What would such a system look like?

  1. Simple apis that are easy to understand and use.
  2. Standard data and api formats, something that can be shared between all of my apps and systems.
  3. Flexible decision expressions allowing unlimited instance data types and values to be considered.

How would this system work?

Standards-based RBAC adheres to the NIST model, later becoming an ANSI standard — INCITS 359.  Long story short, RBAC allows attributes to be applied during two separate phases of the access control decision:

1. User-Role Activation – instance data used to constrain whether an assigned role is eligible to be considered in the access control decision, i.e. permission check, that happens later.  For example, user may only activate the cashier role at store 314.

2. Role-Permission Activation – these constraints apply during the permission check itself.  An example is the action may only be performed if account #456789.

Apache Fortress 2.0.2 now supports type 1.  For a test drive, there’s this rbac-abac-sample in Github.  Have a look under-the-hood section of the README.


Towards an Attribute-Based Role-Based Access Control System

[Link to the Apache Fortress RBAC-ABAC-SAMPLE project on Github]

[Link to towards-an-attribute-based-rbac-ldapcon-2019-v1 from LDAPCon]

We’ve all heard the complaint, RBAC doesn’t work.  It leads to Role Explosion, defined as an inordinate number of roles in a production environment.  Nobody knows who must be assigned to what because there are hundreds if not thousands of them.

What’s a system implementor to do?  We could give Attribute-Based Access Control a try, but that has its own problems and we need not go there again.

There’s another way.  RBAC allows the usage of dynamic attributes.

  • Recent standards include dynamic policies, most notably, ANSI INCITS 494 RBAC Policy-Enhanced
  • The existence of entities to conveniently apply dynamic policies, e.g. User-Role and Role-Permission.
  • No language discouraging the usage of dynamic attributes alongside RBAC in the standard.

Indeed, dynamic attributes are encouraged if not prescribed.  Here’s where I should be pointing to evidence substantiating my arguments.

This brings us to Apache Fortress and a new enhancement to use dynamic attributes.

What is Apache Fortress?

Both followers of this blog (wife and boss) know about Apache Fortress.  Especially my wife.  It’s the itch that leads me to three years of work in a garage, alongside two of my brothers, who got dragged in also.

It’s also an implementation of the classic RBAC specification – ANSI INCITS 359.  If anything’s prone to exploding roles, it’s Apache Fortress.

How are we going to stop the dang exploding?

Described in a JIRA ticket  yesterday, and checked into the Apache Fortress Core Repo last night.  The idea is best explained with a story.

The Tale of Three Stooges and Three Branches

Once upon a time there were three branches, North, South and East managed by The Three Stooges that worked there, Curly, Moe and Larry.

They were nice blokes, but a tad unruly, and so we try to keep them separated.  Curly works in the East, Moe the North and Larry runs amok in the South.  All three are Tellers, but each may also substitute as coin Washers at the other two.

All is well because each Branch has only one Teller.  It’s never good when two Stooges combine without one being in charge.

Here are the Users and their Role assignments:

Curly: Teller, Washer

Moe: Teller, Washer

Larry: Teller, Washer

By now we know where this storyline’s headed.  How do we prevent one going off-script, wandering into another branch, activating Teller, and running slipshod?

The classic Role explosion theory goes like…

Create Roles by Location with User-Role assignments:

Curly: TellerEast, WasherNorth, WasherSouth

Moe: TellerNorth, WasherEast, WasherSouth

Larry: TellerSouth, WasherNorth, WasherEast

This works pretty good with three branches and two roles but what about the real-world?  How many branches will the medium-sized bank have, a thousand?  How many types of roles, at least ten?  If we follow the same Role-by-Location pattern there’d be over 10,000 Roles to manage!  We may be keeping our Stooges in check, but at the IT team’s expense.  Our roles have indeed exploded.  What now?

Time for something different, back to the earlier discussion over using attributes.  Let’s try controlling role activation by location, but store the required attributes on the user object itself.

User-Properties to store Role-Locale constraints:

Curly: Teller:East, Washer:North, Washer:South

Moe: Teller:North, Washer:East, Washer:South

Larry: Teller:South, Washer:North, Washer:East

What just happened here?  It kind of looks the same but it’s not.  We go back to only needing two Roles, but have added dynamic policies, Role-Locale, to properties stored on the User.  Our medium-sized bank only needs 10 roles not 10,000.

Now, when the security system logs in a User (createSession), it pushes its physical location attribute into the runtime context, e.g. North, South or East, along with the already present Userid attribute.  The security system compares that physical location, along with its corresponding properties stored on the User, to determine access rights, specifically which Roles may be activated into their Session.

Sprinkle in a policy that defines the role to constraint relationships.

Global Config Properties store Role-Constraint mappings:



That way when the security system activates roles it knows to perform the extra check on a particular role, and which attribute to verify.

In addition to location, we can constrain role activation by project, organization, customer, account balance, hair color, favorite ice cream, and any other form of instance data imaginable.  There may be multiple types of constraints applied to any or all roles in the system.  It truly is a dynamic policy mechanism placed on top of a traditional Role-Based Access Control System.

With this minor change to the security system, our IT guys return to the good life without worrying about exploding roles or what the Stooges are up to.  🙂

The End




Frequently debated within info sec circles.  Which one of them is better?

Use the right tool for the job as they say. RBAC, like any access control model, has its weaknesses. Many are well understood, even discussed by the original NIST team who framed the model.

Comments on “A Critique of the ANSI Standard on Role-Based Access Control”

However, there are a number of common fallacies wrt how RBAC works.  For example…

1. RBAC is static. It cannot use contextual information e.g. time, user location, device type.

Constraints are commonly applied during user, role and permission activation in RBAC. For example, placing temporal constraints on a role activation. Indeed INCITS 494 prescribes their use:

5.4 RBAC Policy Enhanced Constraints

Enhanced constraints go beyond the INCITS 359 RBAC Standard by including additional types of constraints. Constraints on roles may be static or dynamic. Static constraints are applied off- line before the role is activated by the user. Dynamic constraints are applied on-line after the role(s) are activated. These enhanced dynamic constraints can introduce attributes into the RBAC environment.
INCITS 494-2012, p. 8

2. RBAC cannot perform dynamic segregation-of-duty.

RBAC supports dynamic SoD constraints. From the spec:

5.3.2 Dynamic Separation of Duty Relations

Dynamic Separation of Duty Relations Static separation of duty relations reduce the number of potential permissions that can be made available to a user by placing constraints on the users that can be assigned to a set of roles. Dynamic Separation of duty (DSD) relations, like SSD relations, are intended to limit the permissions that are available to a user. However, DSD relations differ from SSD relations by the context in which these limitations are imposed. SSD relations define and place constraints on a user’s total permission space. This model component defines DSD properties that limit the availability of the permissions over a user’s permission space by placing constraints on the roles that can be activated within or across a user’s sessions.
ANSI INCITS 359-2004, p. 10

3. It relies on custom code within application layers (API, apps, DB…) to implement finer-grained controls.

Presumably what is meant here is that custom code must be written because RBAC controls don’t adequately satisfy security requirements for authorization.

Where are ABAC’s published functional specifications? Where are the standard object (data) and functional (api) model for computing (and storing) its decisions?

Perhaps it is better to use a proven, non-standard ABAC implementation than a custom app widget? If that is what is being said then I agree, but neither are ideal.

ABAC has its place as does RBAC. Knowing when to use one, the other, or both, is important. Understanding the limitations and strengths of each is crucial before adequately addressing the challenges we face as security practitioners.

ABAC – Where are the Functional Specs?

As a security architect I have long-awaited the means to express authorization policies using dynamic constraints – in a standard way. Over the years there have not been many models to choose from.

First came A Resource Access Decision Service, which had promise, but departed with CORBA.

Next came eXtensible Access Control Markup Language (XACML).  Some believe it dead, and there are those who continue to promote.  The jury is out.

What do you think about XACML?

Now the buzz is Attribute-Based Access Control (ABAC).

Blurring the lines, supposedly XACML implements ABAC, because attributes combine with decisions.

There are commonalities across the three models:

  1. Grammar to express very fine-grained access control policies.
  2. Rules containing variables captured from subjects and resources.  Facts such as location, time and date included.
  3. Adjudication when rules combine or clash.
  4. Separation into multiple components, e.g. Policy Enforcement Point (PEP), Policy Decision Point (PDP), Policy Information Point (PIP).

The promise is reuse.

So where are the functional specs?  I must understand and share.

“Despite the clear guidance to implement contextual (risk adaptive) role or attribute based access control ABAC, to date there has not been a comprehensive effort to formally define or guide the implementation of ABAC”

Ruh roh.

Until formal specifications are drafted, ABAC is useless because it’s non-standard and/or proprietary.

Back to square one – awaiting an industry standard dynamic authorization model.