<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: Securing Temporal with Keycloak: Implementing Custom Role-Based Access Control in Servers - General</title>
    <link>https://community.hpe.com/t5/servers-general/securing-temporal-with-keycloak-implementing-custom-role-based/m-p/7271039#M22055</link>
    <description>&lt;P&gt;Hello,&lt;BR /&gt;This is a great deep dive into securing Temporal for enterprise environments. I especially like the decision to integrate authorization directly into the gRPC layer instead of relying on a proxy, as it keeps security close to the execution path while avoiding unnecessary complexity. The Keycloak JWT validation, custom claim mapping, and context-based token propagation provide a clean zero-trust implementation. The HR vs. Finance example clearly demonstrates the practical value of namespace isolation and granular RBAC. I'd also be interested in learning how you handle JWT caching, token refresh, and performance under high workflow throughput, as those are often critical considerations in production deployments.&lt;BR /&gt;&lt;BR /&gt;&lt;BR /&gt;Best Regards&lt;/P&gt;</description>
    <pubDate>Mon, 03 Aug 2026 15:11:27 GMT</pubDate>
    <dc:creator>olio35xender</dc:creator>
    <dc:date>2026-08-03T15:11:27Z</dc:date>
    <item>
      <title>Securing Temporal with Keycloak: Implementing Custom Role-Based Access Control</title>
      <link>https://community.hpe.com/t5/servers-general/securing-temporal-with-keycloak-implementing-custom-role-based/m-p/7271037#M22054</link>
      <description>&lt;P&gt;&lt;STRONG&gt;Introduction &amp;amp; Problem Statement&lt;/STRONG&gt;&lt;/P&gt;&lt;P&gt;As distributed architectures scale, workflow orchestration platforms like Temporal rapidly become the mission-critical nervous system of the enterprise. By default, Temporal offers powerful workflow execution capabilities, but in a highly regulated enterprise environment, relying on basic authentication or perimeter security isn't enough.&lt;/P&gt;&lt;P&gt;The engineering team faced a significant problem: How do we enforce strict, multi-tenant isolation and granular Role-Based Access Control (RBAC) using our central Identity Provider (Keycloak), without sacrificing performance or forking the entire Temporal codebase? This post explores the journey of integrating Keycloak directly into the Temporal gRPC layer, ensuring that every workflow execution, signal, and query is cryptographically verified and strictly authorized.&lt;/P&gt;&lt;P&gt;&lt;STRONG&gt;Why RBAC Matters in Temporal&lt;/STRONG&gt;&lt;/P&gt;&lt;P&gt;Temporal's architecture is highly transparent, meaning any client with network access to the frontend service can potentially start, query, or terminate workflows. Without granular RBAC, the blast radius of a compromised service or an accidental script is cluster wide.&lt;/P&gt;&lt;P&gt;Implementing RBAC natively at the gRPC layer ensures a zero-trust boundary. It guarantees that a microservice can only interact with the workflows and namespaces it explicitly owns and can only perform actions (like signalling or terminating) that its assigned role permits.&lt;/P&gt;&lt;P&gt;&lt;STRONG&gt;Real-World Enterprise Use Case&lt;/STRONG&gt;&lt;/P&gt;&lt;P&gt;Imagine a scenario where the Human Resources team's onboarding workflows and the Finance team's payroll processing workflows reside on the same Temporal cluster.&lt;/P&gt;&lt;P&gt;Without strict namespace isolation and role checks, an errant script in the HR domain could potentially query sensitive financial workflows or, worse, send a termination signal to a payroll process. By implementing custom RBAC, the platform securely segregates these domains. A developer debugging HR workflows is granted a&amp;nbsp;workflow-operator&amp;nbsp;role restricted entirely to the HR namespace, ensuring complete isolation from Finance.&lt;/P&gt;&lt;P&gt;&lt;STRONG&gt;Architecture Overview&lt;/STRONG&gt;&lt;/P&gt;&lt;P&gt;Rather than building a brittle proxy layer in front of Temporal, the team leveraged Temporal's extensible architecture. By importing Temporal as a Go library, the team injected custom authorization plugins and compiled a bespoke&amp;nbsp;temporal-server&amp;nbsp;binary.&lt;/P&gt;&lt;P&gt;The architecture intercepts every request to the Temporal server, validates an incoming Keycloak JSON Web Token (JWT), and evaluates the identity's permissions against the requested action.&lt;/P&gt;&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="rbac architechture.png" style="width: 338px;"&gt;&lt;img src="https://community.hpe.com/t5/image/serverpage/image-id/158346i20ADE974EBC4F274/image-size/medium?v=v2&amp;amp;px=400" role="button" title="rbac architechture.png" alt="rbac architechture.png" /&gt;&lt;/span&gt;&lt;/P&gt;&lt;P&gt;&lt;STRONG&gt;Token Propagation Design&lt;/STRONG&gt;&lt;/P&gt;&lt;P&gt;Security begins at the client edge. When a frontend application or external service makes an HTTP request to the internal backend APIs, it includes a Keycloak JWT in the&amp;nbsp;Authorization&amp;nbsp;header.&lt;/P&gt;&lt;P&gt;The backend API extracts this token and injects it into the Go&amp;nbsp;context.Context. To ensure this token reaches Temporal, a custom&amp;nbsp;TokenHeadersProvider&amp;nbsp;is attached to the Temporal client SDK. This provider automatically extracts the token from the context and attaches it as gRPC metadata to every outgoing call made to the Temporal cluster, ensuring the identity is propagated securely across network boundaries.&lt;/P&gt;&lt;P&gt;&lt;STRONG&gt;Custom Claim Mapper&lt;/STRONG&gt;&lt;/P&gt;&lt;P&gt;The&amp;nbsp;ClaimMapper&amp;nbsp;interface acts as the bridge between Keycloak and Temporal. It intercepts the gRPC request, validates the JWT signature against the Keycloak JWKS endpoint, and translates Keycloak's&amp;nbsp;realm_access&amp;nbsp;roles into Temporal's internal roles (RoleAdmin,&amp;nbsp;RoleWriter,&amp;nbsp;RoleReader).&lt;/P&gt;&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="claim mapper.png" style="width: 400px;"&gt;&lt;img src="https://community.hpe.com/t5/image/serverpage/image-id/158347iD0F41988F8A320C7/image-size/medium?v=v2&amp;amp;px=400" role="button" title="claim mapper.png" alt="claim mapper.png" /&gt;&lt;/span&gt;&lt;/P&gt;&lt;P&gt;&lt;STRONG&gt;Custom Authorizer&lt;/STRONG&gt;&lt;/P&gt;&lt;P&gt;With claims mapped, the&amp;nbsp;Authorizer&amp;nbsp;evaluates the request. To solve the business problem of restricting state-mutating actions, the logic explicitly intercepts and guards specific API calls, such as signals.&lt;BR /&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="custom authorizer.png" style="width: 400px;"&gt;&lt;img src="https://community.hpe.com/t5/image/serverpage/image-id/158348i384BEC6E9466D58A/image-size/medium?v=v2&amp;amp;px=400" role="button" title="custom authorizer.png" alt="custom authorizer.png" /&gt;&lt;/span&gt;&lt;/P&gt;&lt;P&gt;&lt;STRONG&gt;End-to-End Request Flow&lt;/STRONG&gt;&lt;/P&gt;&lt;P&gt;When an HTTP request triggers a workflow signal, the full lifecycle looks like this:&lt;/P&gt;&lt;OL&gt;&lt;LI&gt;&lt;STRONG&gt;Client&lt;/STRONG&gt;: A service calls the backend API with a valid Keycloak JWT.&lt;/LI&gt;&lt;LI&gt;&lt;STRONG&gt;Propagation&lt;/STRONG&gt;: The backend Temporal Client attaches the JWT to the gRPC metadata.&lt;/LI&gt;&lt;LI&gt;&lt;STRONG&gt;Validation&lt;/STRONG&gt;: Temporal receives the gRPC call; the&amp;nbsp;ClaimMapper&amp;nbsp;intercepts the JWT and validates its signature against Keycloak's public keys.&lt;/LI&gt;&lt;LI&gt;&lt;STRONG&gt;Mapping&lt;/STRONG&gt;: The&amp;nbsp;ClaimMapper&amp;nbsp;sees the&amp;nbsp;workflow-operator&amp;nbsp;role and maps it to&amp;nbsp;RoleWriter&amp;nbsp;for the target namespace.&lt;/LI&gt;&lt;LI&gt;&lt;STRONG&gt;Authorization&lt;/STRONG&gt;: The&amp;nbsp;Authorizer&amp;nbsp;checks the requested API (SignalWorkflowExecution). Since the identity holds&amp;nbsp;RoleWriter, the action is permitted.&lt;/LI&gt;&lt;LI&gt;&lt;STRONG&gt;Execution&lt;/STRONG&gt;: The workflow is successfully signaled.&lt;/LI&gt;&lt;/OL&gt;&lt;P&gt;&lt;STRONG&gt;Testing and Validation&lt;/STRONG&gt;&lt;/P&gt;&lt;P&gt;Testing authorization logic requires simulating both authorized and unauthorized identities.&lt;/P&gt;&lt;P&gt;During development, the team utilized a local Go runner (go run main.go auth.go) combined with a mock Identity Provider. Integration tests were written to forcefully inject expired tokens, tokens with missing roles, and tokens with incorrect signatures to verify that the Temporal server correctly instantly rejected the gRPC calls with&amp;nbsp;PermissionDenied&amp;nbsp;errors.&lt;/P&gt;&lt;P&gt;&lt;STRONG&gt;Production Considerations&lt;/STRONG&gt;&lt;/P&gt;&lt;P&gt;Deploying a custom Temporal binary into production involves specific operational strategies. By using a multi-stage&amp;nbsp;Dockerfile, the custom Go binary is compiled and subsequently injected into the official&amp;nbsp;temporalio/server&amp;nbsp;base image.&lt;/P&gt;&lt;P&gt;This ensures that the deployment retains all official startup scripts, database schemas, and tooling. When deploying via Kubernetes, the&amp;nbsp;image&amp;nbsp;directive simply points to the custom registry image, and the Keycloak JWKS URL is provided dynamically via environment variables (KEYCLOAK_JWKS_URL), ensuring seamless promotion across staging and production environments.&lt;/P&gt;&lt;P&gt;&lt;STRONG&gt;Lessons Learned&lt;/STRONG&gt;&lt;/P&gt;&lt;P&gt;Building native Temporal RBAC came with valuable insights:&lt;/P&gt;&lt;OL&gt;&lt;LI&gt;&lt;STRONG&gt;Caching is Critical&lt;/STRONG&gt;: The&amp;nbsp;ClaimMapper&amp;nbsp;must validate the JWT signature using Keycloak's public keys. Fetching the JWKS on every gRPC call would cripple performance. Utilizing a robust JWKS caching library is non-negotiable.&lt;/LI&gt;&lt;LI&gt;&lt;STRONG&gt;Debugging Interceptors&lt;/STRONG&gt;: When authorization fails at the gRPC level, the client simply sees a generic&amp;nbsp;PermissionDenied&amp;nbsp;error. Emitting highly detailed, structured logs inside the&amp;nbsp;ClaimMapper&amp;nbsp;and&amp;nbsp;Authorizer&amp;nbsp;proved essential for diagnosing token expiry or role misconfigurations.&lt;/LI&gt;&lt;LI&gt;&lt;STRONG&gt;Backward Compatibility&lt;/STRONG&gt;: It is crucial to ensure that internal Temporal system calls (e.g., to the&amp;nbsp;temporal-system&amp;nbsp;namespace) bypass the standard authorization checks to prevent the cluster from locking itself out of its own internal workflows.&lt;/LI&gt;&lt;/OL&gt;&lt;P&gt;&lt;STRONG&gt;Conclusion&lt;/STRONG&gt;&lt;/P&gt;&lt;P&gt;By treating Temporal as a flexible framework rather than a black box, the engineering team successfully transformed a standard orchestration engine into a secure, multi-tenant platform.&lt;/P&gt;&lt;P&gt;The gRPC layer now acts as an intelligent, zero-trust boundary, perfectly aligned with the enterprise's central identity policies. For any team scaling Temporal across multiple domains, investing in custom RBAC via the&amp;nbsp;ClaimMapper&amp;nbsp;and&amp;nbsp;Authorizer&amp;nbsp;is a foundational step toward mature, secure orchestration.&lt;/P&gt;</description>
      <pubDate>Mon, 03 Aug 2026 05:01:11 GMT</pubDate>
      <guid>https://community.hpe.com/t5/servers-general/securing-temporal-with-keycloak-implementing-custom-role-based/m-p/7271037#M22054</guid>
      <dc:creator>Manjunatha-KJ</dc:creator>
      <dc:date>2026-08-03T05:01:11Z</dc:date>
    </item>
    <item>
      <title>Re: Securing Temporal with Keycloak: Implementing Custom Role-Based Access Control</title>
      <link>https://community.hpe.com/t5/servers-general/securing-temporal-with-keycloak-implementing-custom-role-based/m-p/7271039#M22055</link>
      <description>&lt;P&gt;Hello,&lt;BR /&gt;This is a great deep dive into securing Temporal for enterprise environments. I especially like the decision to integrate authorization directly into the gRPC layer instead of relying on a proxy, as it keeps security close to the execution path while avoiding unnecessary complexity. The Keycloak JWT validation, custom claim mapping, and context-based token propagation provide a clean zero-trust implementation. The HR vs. Finance example clearly demonstrates the practical value of namespace isolation and granular RBAC. I'd also be interested in learning how you handle JWT caching, token refresh, and performance under high workflow throughput, as those are often critical considerations in production deployments.&lt;BR /&gt;&lt;BR /&gt;&lt;BR /&gt;Best Regards&lt;/P&gt;</description>
      <pubDate>Mon, 03 Aug 2026 15:11:27 GMT</pubDate>
      <guid>https://community.hpe.com/t5/servers-general/securing-temporal-with-keycloak-implementing-custom-role-based/m-p/7271039#M22055</guid>
      <dc:creator>olio35xender</dc:creator>
      <dc:date>2026-08-03T15:11:27Z</dc:date>
    </item>
    <item>
      <title>Re: Securing Temporal with Keycloak: Implementing Custom Role-Based Access Control</title>
      <link>https://community.hpe.com/t5/servers-general/securing-temporal-with-keycloak-implementing-custom-role-based/m-p/7271069#M22056</link>
      <description>&lt;P&gt;Hi olio,&lt;/P&gt;&lt;P&gt;Thanks for your comment! I'm happy you found the post useful. You're right, adding authorization at the gRPC layer has some clear advantages, but things like token management become important once you're running this in production. Here's the general approach we follow:&lt;/P&gt;&lt;HR /&gt;&lt;P&gt;&lt;STRONG&gt;1. JWT Validation and Caching&lt;/STRONG&gt;&lt;/P&gt;&lt;P&gt;- We don't call the identity provider(keycloak) to validate every token because that would add unnecessary network calls and slow things down.&lt;/P&gt;&lt;P&gt;- Instead, we validate JWTs locally using the public keys (JWKS). Those keys are cached in memory, so most token validations happen locally and are very fast.&lt;/P&gt;&lt;P&gt;- If the identity provider rotates its keys, we refresh the cache periodically or whenever we see a new key ID that isn't already cached.&lt;/P&gt;&lt;P&gt;&lt;STRONG&gt;2. Token Refresh&lt;/STRONG&gt;&lt;/P&gt;&lt;P&gt;- Since Temporal workflows and workers can run for a long time, access tokens will eventually expire.&lt;/P&gt;&lt;P&gt;- Rather than waiting for a request to fail, we keep track of the token's expiry time. If it's getting close to expiring, a background process fetches a new token and updates the cached one. This happens automatically, so the application keeps running without interruptions.&lt;/P&gt;&lt;P&gt;- If a request still fails because of an expired token, the retry mechanism can retry it after a fresh token is available.&lt;/P&gt;&lt;P&gt;&lt;STRONG&gt;3. Performance at Scale&lt;/STRONG&gt;&lt;/P&gt;&lt;P&gt;- When you're processing a large number of workflows, the goal is to keep the authorization checks lightweight.&lt;/P&gt;&lt;P&gt;- Because token validation happens locally, there are no extra network calls for every request. Signature verification is also fast, so the additional CPU cost is usually small.&lt;/P&gt;&lt;P&gt;- If role or permission checks are needed, we keep that logic simple and efficient instead of doing expensive processing for every request.&lt;/P&gt;&lt;P&gt;- We also use rate limiting to protect the service during sudden traffic spikes.&lt;/P&gt;&lt;HR /&gt;&lt;P&gt;It takes a little work to set up the caching and refresh logic properly, but once it's in place, it performs well and scales without adding much overhead.&lt;/P&gt;&lt;P&gt;Thanks again for reading and for the great questions!&lt;/P&gt;</description>
      <pubDate>Mon, 03 Aug 2026 12:08:18 GMT</pubDate>
      <guid>https://community.hpe.com/t5/servers-general/securing-temporal-with-keycloak-implementing-custom-role-based/m-p/7271069#M22056</guid>
      <dc:creator>Manjunatha-KJ</dc:creator>
      <dc:date>2026-08-03T12:08:18Z</dc:date>
    </item>
  </channel>
</rss>

