Hybrid C2C / B2C Marketplace

This article explains how to design a graph-based authorization model for a B2B2C marketplace. The article assumes you are familiar with our Key Concepts and Attribute Scopes.

There are four steps to design a model:

  • (a) list the design requirements for the permissions system
  • (b) define the types of objects that the authorization logic will consider
  • (c) define the types of relationships between those types of objects. Since relationships are reflected by edges in the graph, we call this “defining the edge types”
  • (d) attach these permissions to these relationships using attributes

In general, model design is an iterative process. While this article is presented linearly, you might expect to loop through these steps until you’ve hit on the cleanest model structure.

A. List Design Requirements

Suppose you are an ecommerce marketplace company. Buyers and sellers transact via Orders, which are associated with a shipping address at checkout time. You might want to define permissions such that:

  1. Sellers can be (a) shops (groups of users) or (b) individual users
  2. Buyers can only be individual users
  3. Users can be a "shop owner" or a "shop member"
  4. Buyers can view and edit their own orders
  5. Individual sellers can view, edit and refund orders that they sell
  6. Shop owners can edit their shop's settings (e.g. name and payout details) and manage their shop's members
  7. Both shop owners and shop members can view, edit and refund their shop's orders

With GBAC, this system becomes simple to implement. GBAC can natively reflect the relationships between the users, shops and orders. This extra level of native abstraction saves you from creating shop-specific roles.

B. Define the types of objects to consider

First, we define our object types. Every object in the system must have exactly one object type. This means we should not define separate object types for shop owners, shop members and buyers.

Together, the following types make an effective, mutually exclusive representation of the core elements of our real-world system:

  • Users
  • Shops
  • Orders (transactions)

C. Define the edge types

Next, we define the edge types. We will reference design requirements that are satisfied solely by the existence of each edge type. Each edge type represents a possible one-way relationship between two object types. Every edge must have a type, so our list of edge types should be comprehensive: any type of relationship that we use in our authorization logic should be reflected here.

Here is a good set of edge types for our use case:

Source/Target RelationshipEdge Type NameDescriptionDesign Requirements
User → Shopowner-of-shopUser (source) can be an owner of a Shop (target)DR3, DR5, DR6, DR7
User → Shopmember-of-shopUser (source) can be a member of a Shop (target)DR3, DR5, DR7
Shop → Ordershop-seller-of-orderShop (source) can sell an Order (target)DR1(a), DR5
User → Orderuser-seller-of-orderUser (source) can sell an Order (target)DR1(b), DR5
User → Orderbuyer-of-orderUser (source) can buy an Order (target)DR2, DR4

Note that, since edges are strongly typed, we require different edge types to represent a shop selling an order and a user selling an order.

D. Add permissions to each of our relationships.

To add attributes, we'll go through our design requirements, one-by-one. DR1-DR3 define relationships and roles, so are already established by our edge types. DR4-DR6 are all satisfied by direct attributes, which give an edge's source object the permission on the edge's target object. For example:

DR4: Buyers can view and edit their own orders

We add two attributes, view-order:direct and edit-order:direct, to the buyer-of-order edge type.

DR5: Individual sellers can view, edit and refund orders that they sell

We add three attributes, view-order:direct, edit-order:direct andrefund-order:direct to the user-seller-of-order edge type.

DR6: Shop owners can edit their shop's settings (e.g. name and payout details) and manage their shop's members

We add two attributes, edit-shop-settings:direct and manage-shop-members:direct, to the owner-of-shop edge type.

DR7: Both shop owners and shop members can view, edit and refund their Shop's Orders

Firstly, we add an attribute, view-order:inherit, to the edge types member-of-shop and owner-of-shop. The inherit attribute here means that, if a shop has a view-order permission on an order, owners and members of that shop will inherit that permission too.

Next, we add an attribute view-order:direct, to the shop-seller-of-order edge type. This gives the shop the view-order permission on its orders.

We repeat this approach for editing and refunding orders.

Wrap

Our graph's structure now reflects the real-world relationships that determine our permissions. Once we populate the graph with instances of objects and edges, we have all the data we need to run our permission system. When a user tries to view a shipping address associated with a transaction, our client can call CheckAttribute to ask: does User X have Permission Y on Resource Z?