Skip to content
Reeflow
Start Building

Roles

Roles are the central mechanism for controlling access in Reeflow. A role bundles permissions with user attribute rules, defining both what a principal can do and what context they must provide.

Roles have four components:

  • Permissions: Actions the role can perform on specific resources. See Permissions.
  • Required user attributes: User attributes a principal must provide to assume the role. If missing, the role is skipped entirely.
  • Fixed user attributes: Values the role provides, overriding any value the principal supplies. Use these to enforce constraints that principals cannot bypass.
  • Principals: Entities that can be assigned roles: teams, API keys, and embedded users.

When a principal makes a request, Reeflow resolves their effective permissions and user attributes in three steps:

  1. Resolve assumable roles: Identify which of the principal’s assigned roles they can assume. A role is assumable only if the principal provides all its required user attributes. Roles without required user attributes are always assumable.
  2. Merge permissions: Combine permissions from all assumable roles using union semantics. If any role grants an action, the principal can perform it.
  3. Resolve user attributes: Start with the principal’s user attributes, then apply fixed user attributes from each assumable role. Fixed values override the principal’s values.

An embedded user has a role that requires tenant_id and grants query access to the orders table with a row filter tenant_id = RF_USER_ATTR('tenant_id').

The principal provides tenant_id = 'acme' in their session token:

  1. Role resolved: The role applies because tenant_id is provided.
  2. User attributes resolved: tenant_id = 'acme'.
  3. Result: Queries to orders are rewritten to SELECT * FROM orders WHERE tenant_id = 'acme'. Only Acme’s rows are returned.

Same role as above, but the backend is misconfigured and does not pass tenant_id in the session token:

  1. Role resolved: The role is skipped because tenant_id is missing.
  2. Result: No assumable roles, so no permissions apply. The API returns 403 Forbidden for any request.

Permissions control what actions a principal can perform on which resources. Each permission specifies an action and a scope.

Reeflow supports five actions:

ActionPurpose
createCreate new instances of a resource
retrieveRead resource details
updateModify existing resources
deleteRemove resources
queryExecute data queries through connections

The query action is special: it only applies to connections and enables table, column, and row-level security controls.

Each permission uses a scope to specify which resource instances are accessible. There are two options:

  • All instances: Grants access to every instance of the resource, including any created in the future.
  • Specific instances: Restricts access to only the resource IDs you specify.

Resources not listed in a role’s permissions are denied by default.

Query permissions define what data a principal can access when querying a connection. They operate at four levels:

LevelWhat it controlsExample
ConnectionWhich connections can be queriedAllow queries only to the analytics connection
TableWhich tables can be queried within allowed connectionsRestrict access to orders and customers only
ColumnWhich columns are visible per tableHide salary from the employees table
RowWhich rows are returned, based on dynamic filtersFilter by tenant_id = RF_USER_ATTR('tenant_id')

For details on configuring these levels, see Connection and table security, Column-level security, and Row-level security.

Roles can configure user attributes in two ways to enforce security constraints.

TypePurposeBehavior
RequiredEnsure context is present before granting accessRole is skipped if the principal does not provide the user attribute
FixedEnforce a specific value that principals cannot overrideValue is set by the role, ignoring any value the principal provides

A user attribute cannot be both required and have a fixed value on the same role. Required user attributes expect the principal to supply a value; fixed user attributes supply the value themselves.

Example: Fixed user attributes override principal values

Section titled “Example: Fixed user attributes override principal values”

A role grants query access to the reports table with a fixed user attribute region = 'us' and a row filter region = RF_USER_ATTR('region').

The principal provides region = 'eu' in their session token:

  1. Role resolved: The role applies (no required user attributes).
  2. User attributes resolved: region = 'us' (fixed value overrides the principal’s 'eu').
  3. Result: Queries filter to region = 'us'. The principal cannot access EU data by passing a different value.

Roles can be assigned to three types of principals:

PrincipalHow roles are assignedUse case
TeamsConsole or APIPlatform users (team members) inherit permissions from their team’s roles
API keysConsole or APIProgrammatic access for backend services, scheduled jobs, or integrations
Embedded usersSession tokens or APIEnd users in your application viewing embedded analytics

For embedded users, roles are typically assigned when creating a session token. This allows your backend to control access dynamically:

const API_KEY_ID = 'key_abc123xyz';
const API_KEY_SECRET = 'your-api-key-secret';
const credentials = Buffer.from(`${API_KEY_ID}:${API_KEY_SECRET}`).toString('base64');
const response = await fetch('https://api.reeflow.io/embed/sessions', {
method: 'POST',
headers: {
Authorization: `Basic ${credentials}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
embedded_user: {
external_user_id: 'user-123',
role_ids: ['role_viewer', 'role_tenant_access'],
attributes: {
tenant_id: 'acme',
},
},
}),
});
const { token } = await response.json();

When a principal has multiple assumable roles, permissions are combined using union semantics:

ElementMerge behavior
ActionsIf any role grants an action on a resource, the principal can perform it
Resource scopeIf any role grants access to a resource instance, the principal can access it
Table scopeIf any role grants access to a table, the principal can query it
Column scopeVisible columns are the union of all roles’ allowed columns
Row filtersRow filters from all roles are combined. All filters apply to every query

Create a role in the Console

Create a new role to define permissions and user attribute requirements for principals. This guide shows how to create a role with a required user attribute for multi-tenant security.

Navigate to Roles in the main navigation, then click New Role to open the form.

Enter a Name for the role. Choose a descriptive name that indicates what access the role provides.

Optionally add a Description to explain the role’s purpose and when to assign it.

Expand User Attributes and click Add Attribute. Select an attribute key and set it as Required. Principals must provide this attribute to assume the role.

Expand Connections and enable the Query action to allow data access. You can configure connection scope, table access, and row filters from here.

Click Create Role to save. The role now appears in the list and can be assigned to principals.

For configuring query permissions (connections, tables, columns, and row filters), see:

Reeflow enforces the following constraints on roles:

ConstraintLimit
Name length100 characters
Description length500 characters
User attributes per role10
Row constraints per table10

User attribute keys referenced in role configuration must be defined in the organization. Attempting to use an undefined user attribute key returns an error.

ScenarioResult
No assumable roles (missing required user attributes)403 Forbidden
Required user attribute missing from principalRole is skipped; may result in 403 Forbidden if no other roles apply
Action not permitted on resource403 Forbidden
Invalid user attribute key in role configuration400 Bad Request