WorkOS Docs Homepage
FGA
API referenceDashboardSign In
Getting StartedOverviewOverviewQuick StartQuick StartPlaygroundPlaygroundKey ConceptsSchemaSchemaWarrantsWarrantsResourcesResourcesPoliciesPoliciesQuery LanguageQuery LanguageWarrant TokensWarrant TokensOperations & UsageOperations & UsageManagementSchema ManagementSchema ManagementLocal DevelopmentLocal DevelopmentIdentity Provider SessionsIdentity Provider SessionsModelingOrg Roles & PermissionsOrg Roles & PermissionsCustom RolesCustom RolesGoogle DocsGoogle DocsEntitlementsEntitlementsUser GroupsUser GroupsManaged Service ProviderManaged Service ProviderAttribute-Based Access ControlAttribute-Based Access ControlConditional RolesConditional RolesPolicy ContextPolicy ContextPublic AccessPublic AccessSuperusersSuperusersBlocklistsBlocklists
API Reference
API Reference
Events
Events
Integrations
Integrations
Migrate to WorkOS
Migrate to WorkOS
SDKs
SDKs

Attribute-Based Access Control (ABAC)

Learn how to use policies to implement a pure attribute-based access control (ABAC) model in Fine-Grained Authorization (FGA).

On this page

  • When to Use Pure ABAC?
  • Schema
  • Example
    • 1. Apply the schema
    • 2. Check access

Explore the example from this guide in the FGA Playground, where you can interact with the schema, warrants, and access checks in real-time!

Attribute-Based Access Control (ABAC) is an authorization model that grants access based on attributes of users, resources, environments, and other contextual factors.

FGA allows you to implement a pure ABAC model, where permissions rely solely on attributes without requiring warrant data. By centralizing authorization policies, FGA eliminates hardcoded access logic, making your system more scalable and maintainable.

Note: Starting with a pure ABAC model can be an effective way to remove hardcoded authorization logic while keeping policies flexible. As your needs evolve, you can seamlessly integrate Relationship-Based Access Control (ReBAC) to support permissions based on user-resource relationships, such as team memberships, delegated roles, or hierarchical access.

When to Use Pure ABAC?

ABAC is ideal when access rules are complex and depend on multiple dynamic factors such as:

  • Entitlements: feature access based on plan level.
  • Feature flags: enabling experimental features for specific groups.
  • Domain-specific data: security constraints based on specific resource data attributes.
  • Role membership: access based on user roles or attributes that are not strictly hierarchical.
  • Temporal data: granting temporary access based on time-based or location-based policies.

Schema

version 0.3
type user
type organization
relation view_financial_records []
inherit view_financial_records if
// Policies can be combined with inheritance rules
all_of
policy user_in_organization
policy is_finance_manager
relation view_research_data []
inherit view_research_data if
all_of
policy user_in_organization
policy is_assigned_researcher
policy is_within_working_hours
type document
relation edit []
inherit edit if
policy edit_document
policy user_in_organization(user_attributes map, organization_id string) {
user_attributes.organization_id == organization_id
}
policy is_finance_manager(user_attributes map) {
user_attributes.department == "finance" &&
"manager" in user_attributes.roles
}
policy is_assigned_researcher(user_attributes map, project_id string) {
user_attributes.role == "manager" &&
project_id in user_attributes.assigned_projects
}
policy is_within_working_hours(access_time_epoch_seconds integer) {
let second_since_midnight = access_time_epoch_seconds % 86400;
// 9 AM (32400s) to 5 PM (61200s)
second_since_midnight >= 32400 && second_since_midnight <= 61200
}
policy edit_document(user_attributes map, document_attributes map) {
let user_is_document_editor = "document_editor" in user_attributes.roles;
let draft_status = document_attributes.status == "draft";
let user_can_access_document = document_attributes.organization_id == user_attributes.organization_id;
user_is_document_editor && draft_status && user_can_access_document
}

Example

1. Apply the schema

Create a file called schema.txt containing the schema definition from above. Then use the CLI to apply this schema to your WorkOS FGA environment.

Note: make sure to select the correct environment with the CLI

workos fga schema apply schema.txt

2. Check access

With our environment setup, we can check the user’s permissions.

Check user permissions
curl "https://api.workos.com/fga/v1/check" \
-X POST \
-H "Authorization: Bearer sk_example_123456789" \
--data-raw \
'{
"op": "all_of",
"checks": [
{
"resource_type": "organization",
"resource_id": "acme",
"relation": "view_financial_records",
"subject": {
"resource_type": "user",
"resource_id": "user_2oDscjroNWtzxzYEnEzT9P7VYEe"
},
"context": {
"user_attributes": {
"id": "user_2oDscjroNWtzxzYEnEzT9P7VYEe",
"department": "finance",
"roles": ["manager"],
"organization_id": "acme",
"assigned_projects": ["project-1", "project-2"],
},
"organization_id": "acme",
"project_id": "project-1",
"access_time_epoch_seconds": 1712653200
}
},
{
"resource_type": "document",
"resource_id": "document-1",
"relation": "edit",
"subject": {
"resource_type": "user",
"resource_id": "user_3kLwpXyzQTuvbNApRmC5X4ZhAmd"
},
"context": {
"user_attributes": {
"id": "user_3kLwpXyzQTuvbNApRmC5X4ZhAmd",
"department": "engineering",
"roles": ["document_editor"],
"organization_id": "acme",
"assigned_projects": ["project-2"],
},
"document_attributes": {
"id": "document-1",
"organization_id": "acme",
"status": "draft",
"project_id": "project-2"
}
}
}
]
}'
© WorkOS, Inc.
FeaturesAuthKitSingle Sign-OnDirectory SyncAdmin PortalFine-Grained Authorization
DevelopersDocumentationChangelogAPI Status
ResourcesBlogPodcastPricingSecuritySupport
CompanyAboutCustomersCareersLegalPrivacy
© WorkOS, Inc.