Portal Community

Groups vs. Roles

Groups are organizational — they represent teams, departments, or functional units. Roles are capability definitions — they define what permissions a user has. The connection: groups are assigned roles, and users are assigned to groups.

// Hierarchy:
User → Group → Role → Permission Set → Permission Strings
User → Role  → Permission Set → Permission Strings  (direct role assignment)

Creating a Group

POST /passport/admin/groups
Authorization: Bearer {admin-token}
Content-Type: application/json

{
  "groupName": "finance-team",
  "displayName": "Finance Team",
  "description": "Accounts, payroll, and financial reporting staff",
  "tenantId": "tenant-abc",
  "roleIds": [
    "role-finance-manager",
    "role-report-viewer"
  ]
}

// Response
{
  "groupId": "group-guid",
  "groupName": "finance-team",
  "memberCount": 0,
  "createdAt": "2026-05-25T10:00:00Z"
}

Group Membership Management

// Add users to a group
POST /passport/admin/groups/{groupId}/members
Authorization: Bearer {admin-token}
Content-Type: application/json

{
  "userIds": ["user-guid-1", "user-guid-2", "user-guid-3"],
  "tenantId": "tenant-abc"
}

// Remove a user from a group
DELETE /passport/admin/groups/{groupId}/members/{userId}
Authorization: Bearer {admin-token}

// List group members
GET /passport/admin/groups/{groupId}/members?page=1&pageSize=50
Authorization: Bearer {admin-token}

// List groups for a user
GET /passport/admin/users/{userId}/groups
Authorization: Bearer {admin-token}

Group-Based Resource Policies

Resource policies can target groups using the group: prefix in subjectIds. All current and future members of the group automatically inherit the policy:

{
  "resourceType": "workflow",
  "resourceId":   "payroll-workflow-guid",
  "effect":       "Allow",
  "permission":   "workflow.initiate",
  "subjectIds":   ["group:group-guid-finance-team"],
  "description":  "All finance team members can initiate payroll"
}

IMembershipProvider and Groups

The IMembershipProvider returns both directly-assigned roles and group-derived roles in a single call. The policy engine does not distinguish the source — all resolved role IDs are evaluated together.

// For a user in group "finance-team" with direct role "viewer":
var groups = await membership.GetUserGroupsAsync("user-guid", "tenant-abc", ct);
// Returns: ["viewer", "finance-manager", "report-viewer"]
// viewer = direct assignment
// finance-manager, report-viewer = from finance-team group

Bulk Import from External Directory

// Sync groups from Azure AD or Okta at tenant onboarding
POST /passport/admin/groups/sync-from-provider
Authorization: Bearer {admin-token}
Content-Type: application/json

{
  "provider": "AzureAD",
  "tenantId": "tenant-abc",
  "groupFilters": ["Finance*", "IT-*", "HR-Managers"],
  "defaultRoleMapping": {
    "Finance*":      ["finance-manager"],
    "IT-*":          ["admin"],
    "HR-Managers":   ["manager"]
  },
  "syncMembership": true
}

// Sync runs asynchronously — returns a job ID
{
  "syncJobId": "sync-job-guid",
  "status": "queued",
  "estimatedMinutes": 2
}
Groups Simplify Offboarding

When a user leaves the organization, removing them from all groups (or disabling their account) immediately revokes all group-derived permissions. No need to audit individual role assignments. For organizations with hundreds of users, group-based access management dramatically reduces administrative overhead.