Skip to main content

Introducing Formengine - The New Formbuilder, try for FREE formengine.io.

Security Services

Security services in the Web API add authentication and authorization to Workflow API operations. They use standard ASP.NET authentication and read a compact WorkflowApiPermissions claim from the current ClaimsPrincipal.

The permission claim can describe both operation access and tenant access. This is important in multi-tenant mode: Workflow-Api-Tenant-ID selects the tenant context for the request, but it does not grant access by itself. The selected tenant must also be allowed by the WorkflowApiPermissions claim.

info

To integrate security services, first include the core and database provider services.

Integration

Security services are included in the OptimaJet.Workflow.Api NuGet package, which you should have already added when integrating the core services.

Add the security services during application startup by using an extension method on IServiceCollection. You can also configure their options:

builder.Services.AddWorkflowApiSecurity(options =>
{
// Configure the Workflow Engine Web API Security options.
options.DisableSecurity = false;
options.SecurityScheme = null;
});

You have now integrated the Web API security services. By default, they use the security scheme that is set as the default when configuring ASP.NET authentication services. This typically looks like:

builder.Services.AddAuthentication("YourScheme");

Security Options

You can configure options for the security services by using the WorkflowApiSecurityOptions record via ASP.NET IOptions in the service collection. The table below describes its properties:

NameTypeDefaultDescription
DisableSecurityboolfalseAllows disabling authentication and authorization. By default, authentication and authorization are enabled when adding AddWorkflowApiSecurity().
SecuritySchemestring?nullThe authentication scheme used for Workflow Engine API operations. When null, the default authentication scheme set in AuthenticationOptions will be used.

Permission Claim

When security is enabled, every Workflow API request must be authenticated and authorized. The Web API expects one permission claim:

NameValue
WorkflowApiConstants.PermissionsClaimTypeWorkflowApiPermissions

The value is a compact semicolon-separated list of permission rules:

<effect>:<target>[;<effect>:<target>]

The effect is a for allow and d for deny. The target is either an operation branch under workflow-api or a tenant rule under tenants.

Examples:

ValueMeaning
a:workflow-apiAllow all Workflow API operations.
d:workflow-apiDeny all Workflow API operations.
d:workflow-api;a:workflow-api.livenessDeny all operations except liveness.
d:workflow-api;a:workflow-api.rpcDeny all operations except the RPC branch.
a:workflow-api;d:workflow-api.rpc.delete-instanceAllow all operations except delete-instance.
a:tenantsAllow all configured tenants.
d:tenantsDeny all tenants.
a:tenants:TenantA,TenantBDeny all tenants except TenantA and TenantB.
d:tenants:TenantA,TenantBAllow all tenants except TenantA and TenantB.

Operation permissions are hierarchical. A branch target such as workflow-api.rpc applies to all operations below that branch, so do not append a .* suffix. If several operation rules match a request, the more specific rule wins. For example, a:workflow-api.rpc;d:workflow-api.rpc.delete-instance allows the RPC branch but denies workflow-api.rpc.delete-instance.

Tenant permissions are evaluated as one tenant rule. Use DenyAllTenantsExcept(...) for a strict allow list, or AllowAllTenantsExcept(...) when most tenants should be allowed with a small deny list.

The single compact claim keeps JWT payloads small, especially when the token is stored in authentication cookies. Prefer branch rules such as workflow-api.rpc or workflow-api.data.schemes instead of listing every leaf operation when the same access policy applies to the whole branch.

Claim Generation

Use the IWorkflowApiPermissions service to build and validate the claim value. It creates a normalized WorkflowApiPermissions claim and rejects unauthorized operation targets or tenant ids.

var claim = permissions.BuildClaim(builder => builder
.DenyAllOperations()
.Allow(
WorkflowApiOperationId.Liveness,
WorkflowApiOperationId.DataSchemesGetCollection,
WorkflowApiOperationId.DataSchemesGet)
.DenyAllTenantsExcept("TenantA"));

This claim allows only the listed operations and only TenantA in multi-tenant mode.

To allow all operations and all tenants:

var claim = permissions.BuildClaim(builder => builder
.AllowAllOperations()
.AllowAllTenants());

To allow an operation branch with a more specific deny:

var claim = permissions.BuildClaim(builder => builder
.DenyAllOperations()
.Allow("workflow-api.rpc")
.Deny(WorkflowApiOperationId.RpcDeleteInstance)
.AllowAllTenants());

To store or send the permissions value separately from the JWT claim, use the builder directly:

var permissionsValue = permissions.CreateBuilder()
.DenyAllOperations()
.Allow("workflow-api.search")
.DenyAllTenantsExcept("TenantA", "TenantB")
.GetValue();

You can validate a stored value before saving it:

var isValid = permissions.CreateBuilder().ValidateValue(permissionsValue);

You can also build a claim from an already serialized value:

var claim = permissions.BuildClaim("d:workflow-api;a:workflow-api.search;a:tenants:TenantA,TenantB");

You can find a detailed JWT Bearer implementation in our GitHub sample.

JWT Example

The example below shows the relevant part of issuing a JWT token:

Claim[] claims =
[
permissions.BuildClaim(builder => builder
.DenyAllOperations()
.Allow("workflow-api.rpc")
.Deny(WorkflowApiOperationId.RpcDeleteInstance)
.DenyAllTenantsExcept("TenantA")),
new(ClaimTypes.Name, user.Name)
];

In multi-tenant mode, the client still sends Workflow-Api-Tenant-ID with each request:

curl -X POST \
-H "Authorization: Bearer <token>" \
-H "Workflow-Api-Tenant-ID: TenantA" \
-H "Content-Type: application/json" \
-d "{}" \
https://localhost:7169/workflow-api/rpc/runtime-get-running-status

The request is authorized only when both checks pass:

  1. The claim allows the requested operation.
  2. The claim allows the tenant resolved from Workflow-Api-Tenant-ID or from WorkflowApiCoreOptions.DefaultTenantId.

If the operation is denied, tenant permission is missing, the tenant header is missing and no default tenant is configured, the tenant id is invalid, the tenant is unknown, or the header is changed to a tenant not allowed by the token, the request returns 403 Forbidden. In single-tenant mode, the tenant permission rule is not required.

Operation Identifiers

Permissions in the Web API are organized in a tree structure, where each node represents either an operation identifier or a group of operations. You can use either exact operation identifiers or branch targets in permission rules. Below is a list of all existing operation identifiers.

WorkflowApi API

  • workflow-api.liveness — Check whether the API service is alive.
  • workflow-api.readiness — Check whether all tenants are ready to accept requests.
  • workflow-api.tenant-readiness — Check whether the current tenant is ready to accept requests.

Search API

  • workflow-api.search.runtimes — Search runtimes.
  • workflow-api.search.global-parameters — Search global parameters.
  • workflow-api.search.schemes — Search schemes.
  • workflow-api.search.statuses — Search process statuses.
  • workflow-api.search.processes — Search processes.
  • workflow-api.search.processes.parameters — Search process parameters.
  • workflow-api.search.processes.timers — Search process timers.
  • workflow-api.search.processes.transitions — Search process transitions.
  • workflow-api.search.processes.approvals — Search process approvals.
  • workflow-api.search.processes.inbox-entries — Search process inbox entries.

Data API

Runtimes

  • workflow-api.data.runtimes.get-collection — Get runtime collection.
  • workflow-api.data.runtimes.get — Get runtime.

Global Parameters

  • workflow-api.data.global-parameters.get-collection — Get global parameters collection.
  • workflow-api.data.global-parameters.create-collection — Create global parameters collection.
  • workflow-api.data.global-parameters.delete-collection — Delete global parameters collection.
  • workflow-api.data.global-parameters.get — Get global parameter.
  • workflow-api.data.global-parameters.create — Create global parameter.
  • workflow-api.data.global-parameters.update — Update global parameter.
  • workflow-api.data.global-parameters.delete — Delete global parameter.

Schemes

  • workflow-api.data.schemes.get-collection — Get schemes collection.
  • workflow-api.data.schemes.create-collection — Create schemes collection.
  • workflow-api.data.schemes.delete-collection — Delete schemes collection.
  • workflow-api.data.schemes.get — Get scheme.
  • workflow-api.data.schemes.create — Create scheme.
  • workflow-api.data.schemes.update — Update scheme.
  • workflow-api.data.schemes.delete — Delete scheme.

Statuses

  • workflow-api.data.statuses.get-collection — Get statuses collection.
  • workflow-api.data.statuses.get — Get status.

Processes

  • workflow-api.data.processes.get-collection — Get processes collection.
  • workflow-api.data.processes.get — Get process.
  • workflow-api.data.processes.update — Update process.
Process Parameters
  • workflow-api.data.processes.parameters.get-collection — Get process parameters collection.
  • workflow-api.data.processes.parameters.create-collection — Create process parameters collection.
  • workflow-api.data.processes.parameters.delete-collection — Delete process parameters collection.
  • workflow-api.data.processes.parameters.get — Get process parameter.
  • workflow-api.data.processes.parameters.create — Create process parameter.
  • workflow-api.data.processes.parameters.update — Update process parameter.
  • workflow-api.data.processes.parameters.delete — Delete process parameter.
Process Timers
  • workflow-api.data.processes.timers.get-collection — Get process timers collection.
  • workflow-api.data.processes.timers.create-collection — Create process timers collection.
  • workflow-api.data.processes.timers.delete-collection — Delete process timers collection.
  • workflow-api.data.processes.timers.get — Get process timer.
  • workflow-api.data.processes.timers.create — Create process timer.
  • workflow-api.data.processes.timers.update — Update process timer.
  • workflow-api.data.processes.timers.delete — Delete process timer.
Process Transitions
  • workflow-api.data.processes.transitions.get-collection — Get process transitions collection.
  • workflow-api.data.processes.transitions.delete-collection — Delete process transitions collection.
  • workflow-api.data.processes.transitions.get — Get process transition.
  • workflow-api.data.processes.transitions.delete — Delete process transition.
Process Approvals
  • workflow-api.data.processes.approvals.get-collection — Get process approvals collection.
  • workflow-api.data.processes.approvals.delete-collection — Delete process approvals collection.
  • workflow-api.data.processes.approvals.get — Get process approval.
  • workflow-api.data.processes.approvals.delete — Delete process approval.
Process Inbox Entries
  • workflow-api.data.processes.inbox-entries.get-collection — Get process inbox entries collection.
  • workflow-api.data.processes.inbox-entries.delete-collection — Delete process inbox entries collection.
  • workflow-api.data.processes.inbox-entries.get — Get process inbox entry.
  • workflow-api.data.processes.inbox-entries.delete — Delete process inbox entry.

RPC API

Bulk API

  • workflow-api.rpc.bulk-create-instance — Create multiple process instances.
  • workflow-api.rpc.bulk-get-process-instance — Get multiple process instances with parameters.
  • workflow-api.rpc.bulk-get-process-instances-tree — Get multiple root process instances with all subprocesses as trees.
  • workflow-api.rpc.bulk-get-available-commands — Get multiple lists of commands available for current activities and identities.
  • workflow-api.rpc.bulk-execute-command — Execute multiple commands with specified identity.
  • workflow-api.rpc.bulk-update-scheme-if-obsolete — Update multiple schemes of process instances if they are obsolete.
  • workflow-api.rpc.bulk-delete-instance — Delete multiple process instances with all their subprocesses.
  • workflow-api.rpc.bulk-is-process-exists — Check existence of multiple process instances.

Commands API

  • workflow-api.rpc.get-available-commands — Get the list of commands available for current activity and identities.
  • workflow-api.rpc.execute-command — Execute command with specified identity.
  • workflow-api.rpc.get-initial-commands — Get the list of commands available for initial activity and identities.

Instance API

  • workflow-api.rpc.create-instance — Create instance of the process.
  • workflow-api.rpc.delete-instance — Delete process instance and all child subprocesses.
  • workflow-api.rpc.is-process-exists — Check existence of the process instance.
  • workflow-api.rpc.get-process-instance-tree — Get the root process instance and all subprocesses as a tree.
  • workflow-api.rpc.get-process-instance — Get the process instance with all parameters.
  • workflow-api.rpc.get-process-history — Get the history records for the process instance.
  • workflow-api.rpc.get-process-history-count — Get the count of history records for the process instance.
  • workflow-api.rpc.set-process-new-status — Set a new status for the process instance.
  • workflow-api.rpc.get-process-status — Get the status of the process instance.
  • workflow-api.rpc.delete-all-subprocesses — Delete all subprocesses of the process instance.
  • workflow-api.rpc.check-all-subprocesses-completed — Check if all subprocesses of the process instance are completed.
  • workflow-api.rpc.set-process-parameter — Set the value of a process parameter with persistence purpose.
  • workflow-api.rpc.get-process-parameter — Get the value of a process parameter.

Log API

  • workflow-api.rpc.log-debug — Logs a debug message with parameters.
  • workflow-api.rpc.log-debug-if-logger-exists — Logs a debug message with parameters if the logger exists.
  • workflow-api.rpc.log-info — Logs an info message with parameters.
  • workflow-api.rpc.log-info-if-logger-exists — Logs an info message with parameters if the logger exists.
  • workflow-api.rpc.log-error — Logs an error message with parameters.
  • workflow-api.rpc.log-error-if-logger-exists — Logs an error message with parameters if the logger exists.

Pre-Execution API

  • workflow-api.rpc.pre-execute-from-initial-activity — Pre-execute from the initial activity of the process instance.
  • workflow-api.rpc.pre-execute-from-current-activity — Pre-execute from the current activity of the process instance.
  • workflow-api.rpc.pre-execute — Pre-execute from the specified activity of the process instance.

Runtime API

  • workflow-api.rpc.runtime-shut-down — Shuts down the workflow runtime.
  • workflow-api.rpc.runtime-start — Starts the workflow runtime.
  • workflow-api.rpc.runtime-cold-start — Starts the workflow runtime in cold start mode.
  • workflow-api.rpc.runtime-get-running-status — Gets the running status of the workflow runtime.

Scheme API

  • workflow-api.rpc.get-scheme-codes — Get scheme codes with optional filtering by tags.
  • workflow-api.rpc.set-scheme-is-obsolete — Set all process schemes with the specified scheme code as obsolete.
  • workflow-api.rpc.update-scheme-if-obsolete — Update scheme of the process instance if it is obsolete.
  • workflow-api.rpc.get-process-scheme — Get the scheme of the process instance.

State API

  • workflow-api.rpc.get-available-states-to-set — Get the list of all available to set states for the process instance.
  • workflow-api.rpc.get-available-states-to-set-by-scheme-code — Get the list of all available to set states for the scheme.
  • workflow-api.rpc.set-state-without-execution — Set state for the process instance without execution.
  • workflow-api.rpc.set-state-with-execution — Set state for the process instance with execution.
  • workflow-api.rpc.set-activity-without-execution — Set activity for the process instance without execution.
  • workflow-api.rpc.set-activity-with-execution — Set activity for the process instance with execution.
  • workflow-api.rpc.resume — Resumes the process instance execution.
  • workflow-api.rpc.get-current-state-name — Get the current state name of the process instance.
  • workflow-api.rpc.get-current-activity-name — Get the current activity name of the process instance.
  • workflow-api.rpc.get-current-state — Get the current state of the process instance.
  • workflow-api.rpc.get-initial-state — Get the initial state of the scheme.

Designer API

  • workflow-api.designer — Workflow Designer connector access.
  • workflow-api.designer.get — Workflow Designer connector access.

IWorkflowApiPermissions

Service for building and authorizing Workflow Engine API permission claims.

CreateBuilder()

Creates a new IWorkflowApiPermissionsBuilder instance. Builder instances are independent and can be used to create, validate, or normalize serialized permission values.

Returns

TypeDescription
IWorkflowApiPermissionsBuilderA new permissions builder.

BuildClaim(string value)

Builds a WorkflowApiPermissions claim from a serialized permissions value. The value is validated and normalized by the builder before the claim is returned.

Parameters

NameTypeDescription
valuestringA serialized permissions value.

Returns

TypeDescription
ClaimA Workflow API permissions claim.

BuildClaim(Action<IWorkflowApiPermissionsBuilder> configure)

Builds a WorkflowApiPermissions claim using a temporary permissions builder.

Parameters

NameTypeDescription
configureAction<IWorkflowApiPermissionsBuilder>A delegate that configures builder.

Returns

TypeDescription
ClaimA Workflow API permissions claim.

HttpContextHasAccess(ClaimsPrincipal principal, string operationId)

Checks whether the principal has access to the specified operation and to the tenant resolved from the current HTTP context. This method is used by the Workflow API authorization pipeline.

Parameters

NameTypeDescription
principalClaimsPrincipalThe current claim principal.
operationIdstringThe operation identifier to authorize, such as workflow-api.liveness.

Returns

TypeDescription
booltrue when access is granted; otherwise false.

IWorkflowApiPermissionsBuilder

Fluent builder for serialized Workflow API permission values.

AllowAllOperations()

Replaces the current operation permissions with a policy that allows all operations by default. Additional explicit operation rules may deny specific branches or exact operations.

DenyAllOperations()

Replaces the current operation permissions with a policy that denies all operations by default. Additional explicit operation rules may allow specific branches or exact operations.

Allow(params string[] targets) and Allow(IEnumerable<string> targets)

Adds explicit allow operation rules to the selected operation policy. This method is available after AllowAllOperations() or DenyAllOperations() because it belongs to IWorkflowApiOperationPermissionsBuilder.

Parameters

NameTypeDescription
targetsstring[] or IEnumerable<string>Exact operation identifiers or operation branch targets to allow.

Deny(params string[] targets) and Deny(IEnumerable<string> targets)

Adds explicit deny operation rules to the selected operation policy. This method is available after AllowAllOperations() or DenyAllOperations() because it belongs to IWorkflowApiOperationPermissionsBuilder.

Parameters

NameTypeDescription
targetsstring[] or IEnumerable<string>Exact operation identifiers or operation branch targets to deny.

AllowAllTenants()

Replaces the current tenant permissions with a policy that allows all tenants by default.

AllowAllTenantsExcept(params string[] tenantIds) and AllowAllTenantsExcept(IEnumerable<string> tenantIds)

Replaces the current tenant permissions with a policy that allows all tenants by default except the specified tenant ids.

Parameters

NameTypeDescription
tenantIdsstring[] or IEnumerable<string>Tenant ids to deny.

DenyAllTenants()

Replaces the current tenant permissions with a policy that denies all tenants by default.

DenyAllTenantsExcept(params string[] tenantIds) and DenyAllTenantsExcept(IEnumerable<string> tenantIds)

Replaces the current tenant permissions with a policy that denies all tenants by default except the specified tenant ids.

Parameters

NameTypeDescription
tenantIdsstring[] or IEnumerable<string>Tenant ids to allow.

GetValue()

Returns the serialized permissions value from the current builder state.

Returns

TypeDescription
stringA serialized permissions value.

SetValue(string value)

Replaces the current builder state with the rules from a serialized permissions value.

Parameters

NameTypeDescription
valuestringA serialized permissions value.

Returns

TypeDescription
IWorkflowApiPermissionsBuilderThe current permissions builder.

ValidateValue(string value)

Validates a serialized permissions value.

Parameters

NameTypeDescription
valuestringA serialized permissions value.

Returns

TypeDescription
booltrue when value is valid; otherwise false.