Open-Source Wikis

/

Temporal

/

Security

temporalio/temporal

Security

This page summarises the authentication, authorization, and trust boundaries the server enforces. Every concrete extension point is pluggable — operators inject their own implementations via temporal.ServerOption.

Trust boundaries

graph LR
    Client[SDK / CLI / UI<br/>untrusted] -->|TLS + JWT| FE[Frontend]
    FE -->|TLS + mTLS| H[History]
    FE -->|TLS + mTLS| M[Matching]
    H -->|TLS + mTLS| M
    H -->|TLS + cluster cert| Other[Peer cluster]
    Workers[Internal Worker] -->|TLS + service cert| FE
  • Public ingress is the Frontend. Everything outside the cluster talks here.
  • Internal traffic (Frontend ↔ History ↔ Matching, replication between clusters) is mutually-authenticated TLS in production.
  • The Internal Frontend variant exists specifically so cluster-internal traffic can be routed away from the public-facing Frontend.

Authentication

TLS is configured per gRPC listener under the tls: block of YAML config. The implementation lives in common/rpc/encryption/.

Two TLS surfaces:

  • Server TLS — every gRPC server (Frontend, History, Matching) runs TLS.
  • Client TLS — internal clients in client/ carry mTLS certificates so peers can identify them.

JWT authentication is handled by the ClaimMapper and Authorizer interfaces in common/authorization/. The default noopAuthorizer accepts everything; production deployments inject a JWT-based one.

// from cmd/server/main.go
authorizer, _ := authorization.GetAuthorizerFromConfig(&cfg.Global.Authorization)
claimMapper, _ := authorization.GetClaimMapperFromConfig(&cfg.Global.Authorization, logger)
audienceMapper, _ := authorization.GetAudienceMapperFromConfig(&cfg.Global.Authorization)

The flag --allow-no-auth is required when running with the noop authorizer; otherwise the server warns loudly that future versions will reject this configuration.

Authorization

The Authorizer interface receives a Claims plus the target namespace and API name. Standard implementation patterns:

  • JWT scopes — claims contain a list of namespace:operation permissions.
  • Per-namespace ACL — claims map to a role with a stored permission set.
  • Custom plugins — operators implement the interface with their internal IAM system.

Source: common/authorization/. The interceptor that enforces it is wired into Frontend's gRPC handler stack.

Per-namespace authorization

Namespaces are the primary administrative boundary. Most production policies are written per-namespace; the authorizer receives the resolved namespace ID along with the claims so it can answer cleanly. Special "system" namespaces (e.g. temporal-system) host internal workflows and have their own policy.

Replication trust

Cross-cluster replication uses mutual TLS. Each peer cluster's address and certificate are stored in the cluster_metadata table; the cluster bootstrap reads them and constructs gRPC clients with the right credentials. See common/cluster/ and common/rpc/encryption/.

Sensitive data handling

  • Payload encryption is the SDK's responsibility, not the server's. Workflows can encrypt/decrypt payloads using a DataConverter; the server only sees opaque bytes.
  • Logs and metrics are filtered by common/log/tag/ — workflow IDs and namespaces are emitted, payloads are not.
  • Visibility search attributes are user-supplied and are visible in queries; sensitive material should not be a search attribute.

Rate limits as a security control

Several rate limiters exist — see common/quotas/. They enforce per-namespace, global, and per-API limits. Beyond DoS protection they also bound the blast radius of a misbehaving client.

Common pitfalls

  • Forgetting --allow-no-auth — the server runs but logs warnings every minute.
  • Cluster certificate rotation — needs to land on every cluster simultaneously; operationally awkward.
  • Custom authorizers throwing panics — wrap every authorizer call in a recover, otherwise a single bad token can crash the host.

Where to read more

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Security – Temporal wiki | Factory