Access Control
FLXBL provides built-in role-based access control (RBAC) to secure your data. Define roles with specific permissions, then assign users and API keys to those roles.
How It Works
Every API request is authorized based on the caller's role and permissions. FLXBL checks permissions automatically before executing any operation.
Two Levels of Access Control
FLXBL provides access control for your tenant operations. For your application's end-users, you implement your own authorization logic.
| Level | Who | Controlled By |
|---|---|---|
| Tenant RBAC | Your team, API keys, service accounts | FLXBL roles and permissions |
| Application RBAC | Your app's end-users | Your code using role field on identity entity |
For end-users, add a role field to your identity entity and enforce
permissions in your application code. Learn more in
Integration Patterns.
Permissions
Permissions are automatically generated based on your schema. When you publish a schema with entities and relationships, FLXBL creates corresponding permissions.
Permission Format
// Permission format
entity:{EntityName}:{operation}
relationship:{RelationshipName}:{operation}
// Operations
create = create new records
read = read/query records
update = modify existing records
delete = remove records
* = all operationsFor example, with a schema containing Product and Category entities:
| Permission | Allows |
|---|---|
entity:Product:create | Create products |
entity:Product:read | Read products |
entity:Product:update | Update products |
entity:Product:delete | Delete products |
entity:Product:* | All operations on products |
relationship:BELONGS_TO:* | Create/read/update/delete relationships |
Roles
Roles are named collections of permissions. Create roles that match your organization's access patterns, then assign users to roles.
Built-in Roles
FLXBL provides default roles to get you started:
| Role | Permissions | Use Case |
|---|---|---|
| Admin | All operations on all entities | Tenant administrators, system managers |
| Editor | Create, read, update (no delete) | Content creators, data entry |
| Viewer | Read-only access | Reporting, dashboards, public APIs |
Creating Custom Roles
Create roles tailored to your application's needs:
// Example: Creating a "Content Manager" role
// Via API
POST /api/v1/roles
{
"name": "Content Manager",
"permissions": [
"entity:Article:*", // Full access to Articles
"entity:Category:read", // Read-only Categories
"relationship:AUTHORED_BY:*" // Manage authorship
]
}
// Via CLI
flxbl role create "Content Manager" \
--permissions entity:Article:*,entity:Category:read,relationship:AUTHORED_BY:* \
--jsonAssigning Roles to Users
// Assign role to a user
PATCH /api/v1/users/:userId/role
{
"roleId": "role_content_manager_abc123"
}Permission Checks
FLXBL automatically enforces permissions on every API call. You can also explicitly check permissions in your application:
// Check if current user has permission
GET /api/v1/auth/check-permission?permission=entity:Article:create
// Response
{
"hasPermission": true,
"role": "Content Manager"
}API Key Scopes
API keys can be scoped to a subset of the creating user's permissions. This follows the principle of least privilege - give each integration only the access it needs.
// API keys inherit role permissions
// But can be further restricted with scopes
POST /api/v1/api-keys
{
"name": "blog-frontend",
"scopes": [
"entity:Article:read", // Only read Articles
"entity:Author:read" // Only read Authors
]
}
// This key cannot create/update/delete even if
// the creating user has those permissionsLearn more about creating and managing API keys in the API Keys documentation.
Sensitive Fields And Field-Level Security
FLXBL tenant RBAC authorizes operations with permission strings such as
entity:User:read, entity:User:update, and
relationship:WROTE:read. API key scopes further restrict the
owning user's permissions. This is not a general per-field ACL system.
PASSWORD fields are special: they are accepted as input on create, update, registration, and login flows, hashed before storage, removed from REST and SDK response properties, omitted from generated GraphQL output fields and query response types, and omitted from generated identity profile response schemas. GraphQL mutation input types can still include password fields when a write path requires a password value.
{
"name": "User",
"isIdentity": true,
"identifierField": "email",
"fields": [
{ "name": "email", "type": "STRING", "required": true, "unique": true },
{ "name": "displayName", "type": "STRING", "required": true },
{ "name": "password", "type": "PASSWORD", "required": true }
]
}# Create or register with a password value
POST /api/v1/dynamic/User
{
"email": "ada@example.com",
"displayName": "Ada",
"password": "correct-horse-battery-staple"
}
# Responses omit the password field
{
"id": "user_123",
"email": "ada@example.com",
"displayName": "Ada"
}For other sensitive values, model the sensitive data as a separate entity, protect that entity with entity-level permissions and scoped API keys, and expose only trusted server-side routes to browsers or mobile clients.
Best Practices
Principle of Least Privilege
- Grant only the permissions each role actually needs
- Use read-only roles for dashboards and reporting
- Scope API keys to specific operations
Role Design
- Create roles that match real job functions
- Avoid creating too many granular roles
- Document what each role is intended for
API Key Management
- Create separate API keys for each integration
- Rotate keys periodically
- Revoke keys immediately when no longer needed
- Never expose API keys in client-side code
Next Steps
- API Keys - Create and manage scoped API keys
- User Management - Invite team members and manage access
- Identity Configuration - Configure authentication settings