IoT Device Management Example

This example demonstrates how to implement Relationship-Based Access Control (ReBAC) for an Internet of Things (IoT) device management system.

The schema models hierarchical access control where devices are organized into groups, and users have different permission levels based on their relationships with both device groups and individual devices.

Schema

model AuthZ 1.0
 
type user
 
type user_group
  relation member: user
 
type device_group
  relation owner: user | user_group#member
  relation operator: user | user_group#member
  relation guest: user | user_group#member
 
  permission can_add_device: owner
  permission can_add_operator: owner
  permission can_add_guest: owner
 
type device
  relation parent: device_group
  relation owner: user | user_group#member
  relation operator: user | user_group#member
  relation guest: user | user_group#member
 
  permission can_change_code: owner | parent.owner
  permission can_view: can_change_code | operator | parent.operator
  permission can_open: can_view | guest | parent.guest
  permission can_add_operator: owner | parent.owner
  permission can_add_guest: can_add_operator | operator | parent.operator

Schema Components

Types

  • user: Individual users in the system
  • user_group: Groups of users that can be assigned permissions collectively
  • device_group: Collections of IoT devices (e.g., "Smart Home - Living Room", "Office Building - Floor 3")
  • device: Individual IoT devices (e.g., smart locks, thermostats, cameras)

Device Group Relations

Device groups support three relationship types:

  • owner: Full administrative control over the device group
  • operator: Can manage devices within the group but cannot modify group settings
  • guest: Limited access for temporary or restricted users

Device Relations

Individual devices inherit from their parent device group but can also have direct relationships:

  • parent: Links the device to its device group
  • owner: Direct owner of the device (can override group permissions)
  • operator: Can operate the device
  • guest: Limited access to the device

Permission Hierarchy

The schema implements a hierarchical permission model:

  1. Device Group Permissions:

    • can_add_device: Only owners can add new devices to the group
    • can_add_operator: Only owners can grant operator access
    • can_add_guest: Only owners can grant guest access
  2. Device Permissions (with inheritance):

    • can_change_code: Device owners or device group owners can change access codes
    • can_view: Owners, operators, or those with view access from the parent group
    • can_open: Anyone with view access, guests, or guests from the parent group
    • can_add_operator: Device owners or device group owners can add operators
    • can_add_guest: Operators or owners can add guests

Use Cases

Smart Home Management

Scenario: A family manages their smart home with multiple device groups (Living Room, Bedroom, Garage) and various devices (smart locks, thermostats, cameras).

  • Family Members (Owners): Have full control over all device groups and can add devices, change codes, and manage access
  • House Sitter (Operator): Assigned as operator to the "Living Room" device group, can view and operate devices but cannot change codes or add new devices
  • Guest (Guest): Temporary access to open the front door lock but cannot view other devices or change settings

Example Relations:

// Family member owns the "Living Room" device group
{ resource: "living-room", resourceType: "device_group", relation: "owner", target: "alice", targetType: "user" }
 
// House sitter is operator of the device group
{ resource: "living-room", resourceType: "device_group", relation: "operator", target: "sitter-123", targetType: "user" }
 
// Front door lock inherits from parent group
{ resource: "front-door-lock", resourceType: "device", relation: "parent", target: "living-room", targetType: "device_group" }
 
// Guest has temporary access to front door
{ resource: "front-door-lock", resourceType: "device", relation: "guest", target: "guest-456", targetType: "user" }

Commercial Building Management

Scenario: An office building with multiple floors, each floor is a device group containing various IoT devices (access control, HVAC, lighting).

  • Building Manager (Owner): Full control over all floors and devices
  • Floor Manager (Operator): Can manage devices on their specific floor but cannot modify floor-level settings
  • Maintenance Staff (Operator): Can operate devices across multiple floors for maintenance purposes
  • Temporary Contractor (Guest): Limited access to specific devices for a project

Example Relations:

// Building manager owns "Floor 3" device group
{ resource: "floor-3", resourceType: "device_group", relation: "owner", target: "manager-789", targetType: "user" }
 
// Floor manager is operator of their floor
{ resource: "floor-3", resourceType: "device_group", relation: "operator", target: "floor-mgr-3", targetType: "user" }
 
// HVAC system on floor 3
{ resource: "hvac-floor-3", resourceType: "device", relation: "parent", target: "floor-3", targetType: "device_group" }
 
// Maintenance staff can operate HVAC (inherits from parent operator)
// Contractor has guest access to specific access control device
{ resource: "access-door-3a", resourceType: "device", relation: "guest", target: "contractor-xyz", targetType: "user" }

Multi-Tenant IoT Platform

Scenario: An IoT platform serving multiple organizations, where each organization has device groups and devices.

  • Organization Admin (Owner): Full control over their organization's device groups
  • Department Head (Operator): Manages devices within their department's device group
  • Team Member (Operator): Can operate devices in their team's device group
  • External Partner (Guest): Temporary, limited access to specific devices for collaboration

Example Relations:

// Organization owns their device group
{ resource: "org-acme-devices", resourceType: "device_group", relation: "owner", target: "org-acme", targetType: "user_group" }
 
// Department is a device group within organization
{ resource: "dept-engineering", resourceType: "device_group", relation: "parent", target: "org-acme-devices", targetType: "device_group" }
 
// Department head is operator of their department
{ resource: "dept-engineering", resourceType: "device_group", relation: "operator", target: "dept-head-eng", targetType: "user" }
 
// Test device in engineering department
{ resource: "test-device-001", resourceType: "device", relation: "parent", target: "dept-engineering", targetType: "device_group" }

How It Works

Permission Inheritance

The schema uses hierarchical permission inheritance:

  1. Device Group → Device: Permissions from the device group flow down to devices through the parent relation

    • If a user is an owner of a device group, they can can_change_code on all devices in that group
    • If a user is an operator of a device group, they can can_view all devices in that group
  2. Direct Device Relations: Devices can have direct relations that override or complement group permissions

    • A device can have its own owner who has full control regardless of group permissions
    • A device can have its own guest who has access even if not a guest of the parent group

Access Control Flow

When checking if a user can perform an action on a device:

  1. Check Direct Relations: First, check if the user has a direct relation to the device
  2. Check Parent Group: If no direct relation, check if the user has a relation to the parent device group
  3. Check Permissions: Evaluate permission expressions that may combine multiple relations
  4. Inherit from Group: Group-level permissions apply to all devices in the group

Example: Checking Access

To check if user alice can open device front-door-lock, you use the Descope SDK to check the can_open permission. The permission is defined as can_open: can_view | guest | parent.guest, which means alice can open if she has can_view permission, is a direct guest of the device, or is a guest of the parent device group.

// Check if alice can open the front-door-lock device
const relations = await descopeClient.management.fga.check([
  {
    resource: 'front-door-lock',
    resourceType: 'device',
    relation: 'can_open',
    target: 'alice',
    targetType: 'user',
  },
]);
 
// relations[0] will have an 'allowed' property indicating if access is granted
if (relations[0].allowed) {
  console.log('Alice can open the front door');
  // Proceed with opening the device
} else {
  console.log('Access denied');
}

Complete Implementation Example

Here's a complete example showing how to set up relations and check access for an IoT device:

// 1. Create device group and device relations
await descopeClient.management.fga.createRelations([
  // Alice owns the living room device group
  {
    resource: 'living-room',
    resourceType: 'device_group',
    relation: 'owner',
    target: 'alice',
    targetType: 'user',
  },
  // Front door lock belongs to living room group
  {
    resource: 'front-door-lock',
    resourceType: 'device',
    relation: 'parent',
    target: 'living-room',
    targetType: 'device_group',
  },
  // Bob is a guest of the device
  {
    resource: 'front-door-lock',
    resourceType: 'device',
    relation: 'guest',
    target: 'bob',
    targetType: 'user',
  },
]);
 
// 2. Check if alice can open (she can because she's owner of parent group)
const aliceAccess = await descopeClient.management.fga.check([
  {
    resource: 'front-door-lock',
    resourceType: 'device',
    relation: 'can_open',
    target: 'alice',
    targetType: 'user',
  },
]);
console.log('Alice can open:', aliceAccess[0].allowed); // true
 
// 3. Check if bob can open (he can because he's a direct guest)
const bobAccess = await descopeClient.management.fga.check([
  {
    resource: 'front-door-lock',
    resourceType: 'device',
    relation: 'can_open',
    target: 'bob',
    targetType: 'user',
  },
]);
console.log('Bob can open:', bobAccess[0].allowed); // true
 
// 4. Check if charlie can open (he cannot - no relation)
const charlieAccess = await descopeClient.management.fga.check([
  {
    resource: 'front-door-lock',
    resourceType: 'device',
    relation: 'can_open',
    target: 'charlie',
    targetType: 'user',
  },
]);
console.log('Charlie can open:', charlieAccess[0].allowed); // false

Implementation Considerations

  • Device Registration: When a new device is added, it must be linked to a device group via the parent relation
  • Permission Propagation: Changes to device group permissions automatically affect all devices in the group
  • User Groups: Use user groups for role-based assignments (e.g., all "Maintenance Staff" users)

This schema provides a robust foundation for managing IoT device access in scenarios ranging from smart homes to enterprise building management systems.

Was this helpful?