EDITOR’S NOTE: Welcome to the EMEA Blog Takeover, where our EMEA employees take over the Auth0 blog to share success stories from the region. This week, you’ll meet our thought leaders across the pond, discover some of our most compelling use cases, and read about the trends that influence how we do business.

The Scene

Online media includes a vast world of mostly free and some exclusive paid content, consumed through a plethora of devices. We read the news and listen to music on our phones or smart assistants, skim articles and books on our tablets, and watch movies on our laptops or TVs. More and more, the shape of our devices is changing — from hand-held and large-screen TVs to standalone speakers and connected cars.

In the highly-competitive world of media, understanding the consumer can make the difference between going under or keeping your head above the water. Users need to be able to find media on their devices and consume it at the time they prefer. Keeping the user engaged by offering additional media choices builds loyalty and increases consumption, making room for additional revenue streams.

"The shape of our devices is changing — from hand-held and large-screen TVs to standalone speakers and connected cars."

Understanding the consumer’s social graph can provide a competitive edge, as it allows media providers to differentiate between different consumers sharing a subscription. This is critical to avoid mixing up personalization efforts, while correctly tailoring media access and subscription usage according to a user’s location, role, and age (e.g. restricting content for younger audiences). Knowing how the consumer relates to others in their network also helps to provide more relevant media recommendations.

Many established media providers are still grappling with digital transformation. While there are innovative ways to design a paywall strategy, paywalls can be challenging as content has increasingly become abundant and often free. A frictionless consumer onboarding process with a low barrier to entry is key, as well as an outstanding initial, and continued, digital customer experience. For this you need a minimal amount of effort needed to setup an account as well as a low commercial threshold, such as a 1-month free or low-entry monthly subscription.

Lots of providers today merely focus on a subscriber account, and perhaps attach some profiles, missing out on truly understanding their consumers. We all know how subscriptions are shared — even with attached profiles it doesn’t provide good separation — and consumers get annoyed when personalisation engines get confused. Furthermore, children grow up, employees move companies, users can become full-blown subscribers themselves, people move across countries … starting with a blank digital profile is painful for all parties involved.

"A frictionless consumer onboarding process with a low barrier to entry is key."

Authorization Models

As we’ve discussed, it’s important for every user to have his or her own account, or data gets mixed and becomes useless very quickly. Let’s imagine a simple traditional family setup: mom and dad manage the subscription (1234), also used by two children, an adult (child_adult), and a minor (child_minor). We also have a partner of the oldest child using the subscription (partner_child_adult). All of them have seperate accounts and we assume they can be recognized seamlessly by all the devices. We’re going to focus on how users are mapped to permissions, i.e. the authorization model used.

Note: The examples below are simplified for illustrative purposes. Please reference the linked documentation for more information about the specific features can be used to implement these models.

Discretionary Access Control (DAC)

In a DAC model, all permissions are assigned directly to users, so the model is basically a direct mapping between users and permissions. It holds little information as to why permissions are assigned they way they are, and hence makes it extremely inflexible and hard to manage. In our family example we have five permissions, administration of the subscription (sub_admin), access to minor-approved content (content_minor), access to High Definition streaming any content (content_hd), access to content for 18 years of age or older (content_adult), and access to admin-only content (content_admin).

Discretionary Access Control

Our example using DAC:

// RULES: DAC
// set subscription
context.accessToken[`subscription`] = user.subscription;

// collect permissions
for (permission in user.permissions) context.accessToken.scope.push(permission);

// USER: MOM
“subscription”: 1234,
“permissions”: [“sub_admin”, “content_minor”, “content_hd”, “content_adult”, “content_admin”]

// USER: DAD
“subscription”: 1234,
“permissions”: [“content_minor”, “content_hd”, “content_adult”]

// USER: CHILD (ADULT)
“subscription”: 1234,
“permissions”: [“content_minor”, “content_hd”, “content_adult”]

// USER: CHILD (MINOR)
“subscription”: 1234,
“permissions”: [“content_minor”, “content_hd”]

// USER: PARTNER (CHILD ADULT)
“subscription”: 1234,
“permissions”: [“content_minor”, “content_adult”]

The amount of static decisions to make in this DAC model would be:

complexity_dac = users * (subscriptions + permissions)
[users: 10.000, subscriptions: 5.000 & permissions: 5 => 50.050.000]

When faced with an extremely small number of users, subscriptions, and permissions, it might still be manageable. At Auth0, we provide support for DAC by allowing permissions to be stored directly in the user’s account in the metadata fields, which can store generic JSON information.

Role-Based Access Control (RBAC)

In an RBAC model, an abstraction layer is introduced using the concept of roles or groups. Each role or group can be attached to multiple users on one side and multiple permissions on the other side. In other words, instead of having permissions directly assigned to users, they’re now assigned to roles, which in turn get assigned to users.

Role-Based Access Control

Our example using RBAC:

// RULES: RBAC
// set subscription
context.accessToken[`subscription`] = user.subscription;

// collect roles and permissions
for (role in user.roles)
    for (permission in role.permissions) context.accessToken.scope.push(permission);

// ROLE: ADMIN
“permissions”: [“sub_admin”, “content_admin”]

// ROLE: FAMILY (MINOR)
“permissions”: [“content”, “content_hd”]

// ROLE: FAMILY (ADULT)
“permissions”: [“content”, “content_hd”, “content_adult”]

// ROLE: FAMILY (EXTERNAL)
“permissions”: [“content”, “content_adult”]

// USER: MOM
“subscription”: 1234,
“roles”: [“admin”, “family_adult”]

// USER: DAD
“subscription”: 1234,
“roles”: [“family_adult”]

// USER: CHILD (ADULT)
“subscription”: 1234,
“roles”: [“family_adult”]

// USER: CHILD (MINOR)
“subscription”: 1234,
“roles”: [“family_minor”]

// USER: PARTNER (CHILD ADULT)
“subscription”: 1234,
“roles”: [“family_external”]

The amount of static decisions to make in this RBAC model would be:

complexity_rbac = users * (subscriptions + roles) + roles * permissions
[users: 10.000, subscriptions: 5.000, roles: 4 & permissions: 5 => 50.040.020]

When there are significantly fewer roles than permissions, it can vastly reduce the complexity. With Auth0, RBAC can be implemented through the use of roles — permissions can be assigned to roles and roles to users in a static way, either using the Administrator UI or the Management API.

Attribute-Based Access Control (ABAC)

In an ABAC model, policies are introduced that can dynamically determine how permissions are assigned to users based on attributes of the user, but also whatever information is available to the policy engine (like request or context information).

Attribute-Based Access Control

Our example using ABAC:

// RULES: ABAC
// set subscription
context.accessToken[`subscription`] = user.subscription;

// check if admin and add permissions
if (user.admin) context.accessToken.scope.push(["sub_admin", "content_admin"]);

// check if family and add permissions
if (user.external) context.accessToken.scope.push("content");

// check if adult and add permissions
if (user.age >= 18) context.accessToken.scope.push("content_adult");

// check if not external and add permissions
if (!user.external) context.accessToken.scope.push("content_hd");

// USER: MOM
"subscription": 1234,
"admin": true, "external": false, "age" : 45

// USER: DAD
"subscription": 1234,
"admin": false, "external": false, "age" : 47

// USER: CHILD (ADULT)
"subscription": 1234,
"admin": false, "external": false, "age" : 20

// USER: CHILD (MINOR)
"subscription": 1234,
"admin": false, "external": false, "age" : 16

// USER: PARTNER (CHILD ADULT)
"subscription": 1234,
"admin": false, "external": true, "age" : 21

The amount of static decisions to make in this ABAC model would be:

complexity_abac = users * (subscriptions + attributes)
[users: 10.000, subscriptions: 5.000, attributes: 3 => 50.030.000]

When the number of attributes is significantly lower than the number of roles or permissions, it can vastly reduce the complexity. Of course, now a dynamic component of policies is introduced. At Auth0, we provide support for ABAC through rules, which are JavaScript snippets that run after login and allow customizing the permissions returned to the applications.

Relationship-Based Access Control (ReBAC)

In a ReBAC model, a graph-based model is introduced between users and subscriptions, and policies dynamically determine how permissions are assigned to users based on relationships of the user. This allows for a lot more expressive and powerful policies, enabling the business to truly understand the user’s environment and act accordingly.

Relationship-Based Access Control

Our example using ReBAC:

// RULES: REBAC
// if subscription is managed by user …
if (sub:subscription--managed_by-->user:user)
    context.accessToken[`subscription`] = sub:subscription.number;
    context.accessToken.scope.push([“sub_admin”, “content_admin”]);

// if user is related to admin of sub with max 2 hops …
if (sub:subscription--managed_by-->--related_with(2)--user:user)
    context.accessToken[`subscription`] = sub:subscription.number;
    context.accessToken.scope.push(“content”);

// check if adult and add permissions
if (user:user.age >= 18) context.accessToken.scope.push(“content_adult”);

// if user is related to admin of sub with max 1 hop ...
for (sub:subscription--managed_by-->--related_with(1)-->user:user)
context.accessToken.scope.push(“content_hd”);

//RELATIONSHIPS
sub:1234--managed_by-->user:mom
user:mom--related_with-->user:dad
user:mom--related_with-->user:child_adult
user:mom--related_with-->user:minor_adult
user:child_adult--related_with-->user:partner_child_adult

// USER: MOM
“age” : 45

// USER: DAD
“age” : 47

// USER: CHILD (ADULT)
“age” : 20

// USER: CHILD (MINOR)
“age” : 16

// USER: PARTNER (CHILD ADULT)
“age” : 21

Notice that we’ve now stated that everyone who’s related to the admin of the subscription within one hop is considered “close family” and is able to stream content in HD, and everyone who’s related to the admin of the subscription within two hops can access content, allowing all “in-law family” to access content as well, not only child_adult_partner.

The amount of static decisions to make in this ReBAC model would be:

complexity_rebac = users * attributes + subscriptions + users * (users - 1) / 2
[users: 10.000, subscriptions: 5.000, attributes: 1 => 50.010.000]

When the number of attributes is significantly reduced through a small number of possible relationships, it can vastly reduce the complexity. Although harder to quantify, it’s clear it provides more power to define generalized policies. As with ABAC, Auth0 supports ReBAC through the use of rules, which can call out to external sources such as a graph database, where the model can be stored and queried efficiently.

The same model could also be used to enrich the information provided back to the application for improved personalization. This allows for a smoother migration of accounts, as social graphs don’t need to change, and can handle more complex setups. For example, an admin on one subscription could also have non-admin access to another subscription.

Conclusion

We looked at four different authorization models to map users to the correct permissions:

  1. Discretionary Access Control (DAC) where permissions are statically assigned to users directly and only proven manageable with extremely small amounts of users, subscriptions and permissions. Supported by Auth0 using metadata on accounts.

  2. Role-Based Access Control (RBAC) where permissions are statically assigned to roles/groups which in turn are assigned to users, vastly reducing complexity when less roles than permissions. Supported by Auth0 using integrated roles.

  3. Attribute-Based Access Control (ABAC) where permissions are dynamically assigned in policies to users based on the attributes or roles/groups of the users, vastly reducing complexity when less attributes than roles/groups and permissions. Supported by Auth0 using rules.

  4. Relationship-Based Access Control (ReBAC) where permissions are dynamically assigned in policies to users based on the relationships or attributes of the users, vastly reducing complexity when attributes are significantly reduced through a small number of possible relationships. Not only does it provide some complexity gains it also allows for far more complex scenarios to be modeled. Supported by Auth0 using rules, calling out to an external graph database.

About Auth0

Auth0, a global leader in Identity-as-a-Service (IDaaS), provides thousands of customers in every market sector with the only identity solution they need for their web, mobile, IoT, and internal applications. Its extensible platform seamlessly authenticates and secures more than 2.5 billion logins per month, making it loved by developers and trusted by global enterprises. The company's U.S. headquarters in Bellevue, WA, and additional offices in Buenos Aires, London, Tokyo, and Sydney, support its global customers that are located in 70+ countries.

For more information, visit https://auth0.com or follow @auth0 on Twitter.