Skip to main content

Policy Authoring with DSL

Goal

Write policy expressions using the FQL expression language for ABAC and RADAC policies, and JavaScript for Dynamic policies. After completing this guide, you can construct conditions using the available context objects, operators, and value types, and apply common expression patterns to real authorization scenarios.

Audience

Developers writing policy conditions directly in the code editor who need to understand the expression syntax and available context.

Prerequisites

  • Familiarity with the FQL code editor — this guide focuses on the language, not the editor
  • Understanding of the policy types where expressions are used (ABAC, RADAC, Dynamic)

Before You Start

Three policy types use expression-based authoring:

Policy TypeLanguagePurpose
ABACFQLAttribute-based conditions (declarative)
RADACFQLRisk-adaptive conditions (declarative)
DynamicJavaScriptCustom evaluation logic (imperative)

FQL expressions are declarative — they describe the condition that must be true for access to be granted. Dynamic policy scripts are imperative — they execute logic and call grant() or deny() explicitly.

Worked Example

In this guide, you write three expressions:

  1. An ABAC condition that restricts access by department and role
  2. A RADAC condition that combines risk score with location checks
  3. A Dynamic script that implements time-based access with custom logic

Steps

1. FQL expression basics

An FQL expression is a boolean condition built from field references, operators, and values.

Structure: field operator value

user.role == 'editor'

Compound expressions: Combine multiple conditions with logical operators.

user.role == 'editor' && resource.department == user.department

Grouping: Use parentheses to control evaluation order.

(user.role == 'admin' || user.role == 'manager') && context.time >= 900

2. Context objects and field access

FQL provides six context objects. Access their properties with dot notation.

ObjectDescriptionExample Fields
userRequesting user attributesuser.role, user.department, user.title, user.level
resourceTarget resource attributesresource.type, resource.owner, resource.department
tokenAccess token claimstoken.aud, token.scope, token.exp
contextRequest contextcontext.ip, context.time, context.location
orgOrganization attributesorg.settings.isActive, org.name
tenantTenant attributestenant.name, tenant.plan
note

The available fields for each object depend on your configured policy vocabulary. The editor's Fields panel shows all available fields — see Policy DSL Tooling for details.

3. Comparison operators

OperatorMeaningExample
==Equal touser.role == 'admin'
!=Not equal toresource.status != 'archived'
>Greater thanuser.level > 2
<Less thancontext.time < 1700
>=Greater than or equaluser.level >= 3
<=Less than or equaltoken.exp <= 7200
containsContains valueuser.groups contains 'engineering'

4. Logical operators

OperatorMeaningBehavior
&&ANDBoth conditions must be true
||ORAt least one condition must be true
!NOTNegates the condition

Evaluation order: && binds tighter than ||. Use parentheses when the default order does not match your intent.

user.role == 'admin' || user.role == 'manager' && context.time >= 900

This evaluates as: admin OR (manager AND time >= 900). To require time for both roles:

(user.role == 'admin' || user.role == 'manager') && context.time >= 900

5. Value types

TypeSyntaxExamples
StringSingle or double quotes'admin', "editor"
NumberInteger or decimal900, 3.14
BooleanUnquoted keywordstrue, false
warning

Do not mix quote styles in a single value. 'admin" produces an unclosed quote validation error.

6. Common ABAC patterns

Role-based restriction:

user.role == 'manager'

Department-scoped access:

resource.department == user.department

Multi-condition access:

user.role == 'editor' && resource.status != 'archived' && user.department == resource.department

Alternative roles:

user.role == 'admin' || user.role == 'superadmin'

Grouped conditions with fallback:

(user.role == 'manager' && user.department == resource.department) || user.role == 'admin'

7. Common RADAC patterns

RADAC expressions evaluate risk signals alongside access conditions.

Risk score range:

risk.score >= 0 && risk.score <= 5

Risk score with location exclusion:

risk.score >= 0 && risk.score <= 7 && context.location NOT IN ('restricted-zone')

Combined risk and attribute check:

risk.score <= 3 && user.role == 'admin'

8. Dynamic policy scripts (JavaScript)

Dynamic policies use JavaScript for custom evaluation logic. Your script has access to context objects and calls grant() or deny() to return the access decision.

Available objects:

ObjectProperties
userid, title, department, role
resourceid, type, owner
tokenaud, scope, exp
contextip, time, location

Decision functions:

FunctionPurpose
grant()Allow access
deny()Deny access

Example — role and resource type check:

if (user.role === 'manager' && resource.type === 'report') {
grant();
} else {
deny();
}

Example — time-based access:

if (context.time >= 900 && context.time <= 1700) {
grant();
} else {
deny();
}

Example — combined conditions:

if (user.department === resource.department && user.role === 'editor') {
grant();
} else if (user.role === 'admin') {
grant();
} else {
deny();
}
warning

Dynamic policy scripts run in a limited sandbox environment. Every script must include at least one grant() or deny() call. Scripts without a decision function fail validation.

9. Expression validation rules

Both FQL and JavaScript editors validate expressions in real time. Common validation errors:

ErrorCauseFix
Mismatched parenthesesUnbalanced ( and )Add the missing parenthesis
Unknown vocabularyField path not in vocabularyCheck the Fields panel for correct paths
Incomplete expressionField without an operatorAdd a comparison operator and value
Invalid operatorUnsupported operator (for example, ===)Use == instead
Unclosed quoteMissing closing ' or "Add the matching quote character

Validation Scenario

Scenario

You write an ABAC expression with two conditions and a logical AND, then verify the expression validates and the policy saves.

Expected Result

  1. The FQL editor shows no validation errors
  2. The policy is created with the expression stored
  3. Reopening the policy in expression mode shows the saved expression

How to Verify

  • UI evidence: Open the policy in the Admin Console, enable expression mode, and verify the expression text
  • API evidence: Query the policies endpoint and verify the expression field matches
  • Logs: Check the browser network tab for a successful mutation response

Troubleshooting

  • Validation fails with "Unknown vocabulary" — The field path does not match any configured vocabulary item. Use the Fields panel in the editor to find the correct path. The editor may suggest similar field names as quick fixes.
  • JavaScript validation fails with "Missing grant/deny" — Every Dynamic policy script must call grant() or deny() in at least one code path.
  • Expression works in editor but policy evaluation fails — The expression syntax is correct but the vocabulary field values do not match the runtime data. Verify that the attribute values in your expression match the actual values provided by the authorization context at evaluation time.

Next Steps

To use the editor's productivity features (auto-completion, formatting, field browser), see Policy DSL Tooling. To build conditions visually without writing expressions, see GUI-Based Policy Authoring.