EnterprisePatternsRole-based access

Role-based access

Role-aware patterns for safe self-service UIs that show only what a user is authorized to do.

SecurityAuthorizationUX

Overview

Role-based access reduces confusion by removing unactionable controls at the source.

It also strengthens security posture by limiting accidental execution paths in complex applications.

Preview workspace capabilities by role

Live preview

Switch roles to compare allowed, disabled, and replaced capability surfaces, inspect the read-only grant matrix, and request escalation.

POLICY SANDBOX

Workspace capabilities

UI checks mirror API policy decisions
Export billing reportInvoices, tax identifiers, and payment status
Finance Admin access requiredBilling exports contain sensitive invoice and tax data.
Workspace management restrictedOperations Managers and Finance Admins can manage workspace members.
Viewer capability matrix
ResourceViewExportManage
Analytics—
Billing—
Workspace——

This preview changes presentation only. The API must authorize every data read and action again.

Anatomy

Use each piece in this order to keep interpretation and automation consistent.

Identity: ViewerWorkspace policy
AnalyticsView
Billing exportRestricted
Finance Admin access required
12345
  1. 1
    Identity claim

    Holds authenticated user roles and entitlements.

  2. 2
    Policy map

    Matches routes and controls to allowed capabilities.

  3. 3
    Capability surface

    Displays controls with permissions-aware states.

  4. 4
    Justification messaging

    Explains why items are hidden or disabled.

  5. 5
    Fallback action

    Escalation options for users needing elevated rights.

The ordering here is not visual-only; it reflects interaction priority and expected user cognition. Keep this order unless policy demands a specific domain exception.

When to use

Use this pattern when the user needs guided consistency, state, and reuse at scale.

Recommended

  • Multi-tenant systems

    Different customers or teams need different visibility.

  • Sensitive operations

    Only authorized staff can execute critical actions.

  • Shared workspaces

    Different roles collaborate in same surface with distinct boundaries.

When not to use

Avoid forcing this pattern where simpler, direct interactions are sufficient.

Avoid

  • Public info screens

    Do not overfit RBAC where all data is intentionally public.

  • Experimental demos

    Use placeholder flags, not hard-coded role checks.

  • Tiny admin tools

    Keep custom role checks simple for very small apps.

Variants

A small number of variants helps teams choose correctly without adding complexity.

Hide controls

Complete suppression of unavailable actions for reduced noise.

Disable controls

Keep discoverability with explicit access hint.

Escalation

Action request path for temporary permission needs.

States

States communicate readiness, risk, and expected user behavior.

StateTriggerVisual responseInteraction
PermittedRole grants capabilityActive action control appearsAction can be executed.
RestrictedCapability blockedDisabled control with tooltipUser can request access.
ConditionalContext-based checks failWarning label and alternative pathSupport path routes to authorization owner.
DelegatedTemporary role overrideStatus chip and expiryRestricted actions become available briefly.

Behavior

Behavior should remain predictable across devices, permissions, and async edges.

Fail-safe defaults

Always deny by default, then grant explicitly.

Live policy refresh

Reflect role changes without full reload where possible.

Action rationale

Keep rationale visible for governance review.

Accessibility

Keep interaction clarity high and ensure assistive technologies get the same meaning.

KeyAction
TabNavigate only enabled controls in disabled-state contexts where possible.
?Open permission help for inaccessible sections if available.
  • Do not rely on color or cursor to signal permission state.
  • Explain unavailable actions in text and provide next steps.
  • Ensure error and warning messages are assertive enough for screen readers.

Content guidelines

Consistency is achieved by language standards, not by design only.

Permission language

Use "You can request access" instead of "No permission".

ExampleRequest approval to access billing details.

Clear ownership

Show who can grant rights.

ExampleRequest access from Workspace Admin.

Role naming

Use familiar role names already known by users.

ExampleFinance Admin

Examples

Reference implementation style, payloads, and practical behavior.

Resolve capabilities before rendering

  • Role checks happen at both UI and API layers.
  • Display disabled state rather than hard removal for frequently requested features.
  • Pair each restricted control with a request escalation action.
BillingCapability.tsx
tsx
const decision = await policy.can({
actor: session.user,
action: 'billing.export',
resource: workspace,
})
 
<AccessGate
allowed={decision.allowed}
deniedMode={decision.discoverable ? 'disable' : 'hide'}
title="Finance Admin access required"
reason={decision.reason}
action={<Button onClick={requestAccess}>Request access</Button>}
>
<Button onClick={exportBilling}>Export billing report</Button>
</AccessGate>
 
// UI state is not authorization.
await authorize(session.user, 'billing.export', workspace)
Open linked component reference for implementation patterns

Props / API

Use these API entries as a baseline contract and validate them against your domain layer.

These names are implementation-oriented and should map to your local contracts.

Props

PropTypeDefaultDescription
sessionRolesreadonly string[][]Roles available in current authentication context.
permissionsreadonly PermissionCheck[][]Granular capability matrix for resource-level checks.
onRequest(permission: string) => Promise<void>undefinedRequest path for elevated access.
onRetry() => voidundefinedRefresh policy after role change.