Access Control
Three layers of access control for Data Ocean application data — tenant isolation (automatic), workflow-level role enforcement (configured), and row-level data scoping (query-level).
Access Control Layers
Application data access control is enforced at three independent layers. Each layer provides a different scope of protection:
| Layer | Where Enforced | Protection Scope | Configured By |
|---|---|---|---|
| Layer 1: Tenant Isolation | SQL node execution engine | Prevents cross-tenant data access entirely | Automatic — no configuration needed |
| Layer 2: Workflow Access | Workflow trigger authentication | Controls which users/roles can call a workflow | Workflow designer (role claims) |
| Layer 3: Row-Level Scoping | SQL WHERE clause in workflow | Controls which rows within a tenant a user can see | Workflow SQL node queries |
Layer 1: Tenant Isolation (Automatic)
Tenant isolation is automatic and non-bypassable. The SQL node execution engine extracts tenantId from the authenticated workflow execution context and makes it available as {{workflow.tenantId}}. The framework validates that this parameter is used in every SQL query.
Users authenticated to Tenant A cannot construct a request that accesses Tenant B's data — the tenantId comes from the token, not from the request payload.
Do not use {{input.tenantId}} in SQL parameters. Always use {{workflow.tenantId}}, which is sourced from the authenticated session — not from the API caller. Caller-supplied tenant IDs would allow tenant hopping attacks.
Layer 2: Workflow Access Control
Configure which roles can trigger each workflow using the workflow's Access Policy:
// Workflow access policy configuration
{
"workflowId": "lead-delete",
"accessPolicy": {
"requireAuthentication": true,
"allowedRoles": ["SalesManager", "Administrator"],
"denyRoles": [],
"allowedUsers": [],
"requireClaims": []
}
}
// lead-list — accessible to all sales roles
{
"workflowId": "lead-list",
"accessPolicy": {
"requireAuthentication": true,
"allowedRoles": ["SalesRep", "SalesManager", "Administrator", "ReadOnly"]
}
}
When a user without the required role calls a restricted workflow trigger, the API returns:
HTTP 403 Forbidden
{
"error": "Access denied",
"requiredRoles": ["SalesManager", "Administrator"],
"userRoles": ["SalesRep"]
}
Layer 3: Row-Level Data Scoping
Within a tenant, you can restrict which rows a user can see or modify based on their identity or role. This is implemented in the SQL node query using {{workflow.userId}} and {{workflow.userRoles}} context variables.
Sales Rep Sees Only Their Leads
{
"query": "SELECT LeadId, FullName, Email, Status, EstimatedValue FROM Lead WHERE TenantId = @tenantId AND IsDeleted = 0 AND (@isSalesManager = 1 OR AssignedToUserId = @userId)",
"parameters": {
"tenantId": "{{workflow.tenantId}}",
"userId": "{{workflow.userId}}",
"isSalesManager": "{{workflow.hasRole('SalesManager')}}"
}
}
-- Result: SalesManagers see all leads; SalesReps see only their assigned leads
Role-Based Field Masking
To prevent certain roles from seeing sensitive fields, use SQL CASE expressions to mask values in the query result:
SELECT
LeadId,
FullName,
CASE WHEN @isSalesManager = 1 THEN Email ELSE '***@***.***' END AS Email,
CASE WHEN @isSalesManager = 1 THEN CAST(EstimatedValue AS nvarchar) ELSE 'Hidden' END AS EstimatedValue,
Status
FROM Lead
WHERE TenantId = @tenantId
AND IsDeleted = 0;
Form-Level Access Control
Atlas Forms provides field-level visibility rules based on user roles:
// AtlasForms field visibility rule
{
"field": "EstimatedValue",
"visibilityRule": {
"type": "role",
"allowedRoles": ["SalesManager", "Administrator"]
// SalesRep users will not see the EstimatedValue field at all
}
}
// Section-level visibility
{
"section": "AI Enrichment Data",
"visibilityRule": {
"type": "role",
"allowedRoles": ["Administrator", "DataEngineer"]
}
}
Hiding a field in the form designer prevents it from appearing in the UI — but an API caller can still retrieve the value by calling the workflow directly. If a field must be inaccessible to a role, enforce the restriction at the SQL query level (Layer 3) in addition to the form visibility rule.