Skip to main content

15. Authentication and permissions

Principle

Every caller of the engine, and the engine itself when it calls other services, holds an Entra identity. There are no shared API keys and no anonymous endpoints. The gateway (Azure API Management) validates every token before the engine sees the request.

Token flow

  1. The caller obtains a token from Entra for the engine's application: a managed identity, a client credential, a federated identity, or a signed-in user.
  2. The caller sends the request to the gateway with the token.
  3. The gateway checks the issuer, the audience, expiry, and the role claim. A request that fails any check is rejected at the gateway.
  4. The gateway forwards the request to the engine with the caller's application id and object id in headers.
  5. The engine applies its own checks for the operation: the worker's task types, the operator's scope.

Tokens are short-lived and issued by Entra. The engine stores no credentials for its callers.

Callers

CallerHow it authenticatesRoleMay call
PipelineGitHub OIDC federated to an Entra application (workload identity federation). No stored secret.deployerMetadata, event, schedule endpoints
Applications, Teams bridgeApp registration or managed identitystarterStart runs; post human gate decisions
Workers in AzureManaged identity of the Container App or Functions appworkerPoll and post results for their task types
Workers outside AzureClient credential with a certificate, not a secretworkerAs above
OperatorsSigned-in Entra user, through the UI or the Azure CLI, member of the operators groupoperatorRead everything; run control; admin

Roles are app roles on the engine's application registration, assigned to each identity in Entra.

Worker task types

A worker may poll only the task types it implements. Entra app roles do not carry that list, so the engine keeps it: a table of application id to allowed task types, generated by the pipeline from the task definitions and the worker manifests. The gateway checks the worker role; the engine checks the table on every poll and rejects other task types.

Engine identity

The engine runs with one managed identity. It uses that identity for every outbound call: Azure SQL, Service Bus, Blob, Durable Task Scheduler, Key Vault, App Configuration, and Foundry through the gateway. No connection strings or keys are configured.

Per-workflow tool scope

The engine has one identity, so the gateway cannot tell workflows apart by token. Every tool call carries the header x-yml-workflow: name@version. The gateway holds a policy mapping each workflow to the tools and agents it may call. The pipeline generates that policy from the definitions on every change, so a workflow can only call tools its definition names.

Tools are grouped in trust tiers on separate gateway endpoints: read, write, high-risk. A workflow that uses a high-risk tool declares its own Entra agent identity in the definition. The pipeline provisions it, and calls to the high-risk endpoint use that identity, so the audit trail names the workflow rather than the engine.

People behind calls

When a person starts a run or answers a human gate, the calling application (the UI or the Teams bridge) authenticates as itself and includes the person's Entra object id in the request. The engine records it as startedBy or decidedBy on the run or task. The engine never receives or forwards a user's token; it acts under its own identity for everything it does.

Configuration and secrets

ReferenceSourceNotes
${workflow.env.NAME}App Configuration, labelled per environmentNon-secret values: URLs, feature flags
${workflow.secrets.NAME}Key Vault, through App Configuration referencesResolved inside the activity; never written to history or logs

Workers hold the credentials for the systems they access. The engine does not hold them.