---
title: Extend Role-Based Authentication in Self-Hosted Temporal with Helm
description: Learn how to integrate custom ClaimMappers and Authorizers into Temporal's default Helm structure, configure the internalFrontend service, and authenticate workers and SDK clients via OIDC.
image: https://www.bitovi.com/hubfs/Extend-Role-Based-Authentication-in-Self-Hosted-Temporal-with-Helm.png
---

- ![AI implementation](https://www.bitovi.com/hubfs/AIConsultingIcon.svg)
  
  [AI implementation](https://www.bitovi.com/services/ai-consulting)
- ![Systems engineering](https://www.bitovi.com/hubfs/icon%20-%20backend.svg)
  
  [Systems engineering](https://www.bitovi.com/services/systems-engineering-consulting)
- ![Project Management](https://www.bitovi.com/hubfs/icon%20-%20PM.svg)
  
  [Project Management](https://www.bitovi.com/services/agile-project-management-consulting)
- ![Product Design](https://www.bitovi.com/hubfs/icon%20-%20design.svg)
  
  [Product Design](https://www.bitovi.com/services/product-design-consulting)
- ![Frontend development](https://www.bitovi.com/hubfs/icon%20-%20frontend.svg)
  
  [Frontend development](https://www.bitovi.com/services/frontend-development-consulting)
- [View more
  
  →
  
  ](https://www.bitovi.com/digital-consulting-services)

We're Experts in...

- [JavaScript](https://www.bitovi.com/services/frontend/javascript-consulting)
- [AI training](https://www.bitovi.com/ai-training-for-software-engineers)
- [Angular](https://www.bitovi.com/services/frontend/angular-consulting)
- [Design systems](https://www.bitovi.com/services/axure-figma-migration)
- [React](https://www.bitovi.com/services/frontend/react-consulting)
- [Temporal](https://www.bitovi.com/services/backend/temporal-consulting)
- [React Native](https://www.bitovi.com/services/frontend/react-consulting/react-native)
- [Node.js](https://www.bitovi.com/services/backend/nodejs-consulting)

Showcase

![Yum! Brands](https://www.bitovi.com/hubfs/yum-showcase-link-1.png)

[View case study](https://www.bitovi.com/en/bitovi-yum-case-study)

More Projects

- [![Levi's](https://www.bitovi.com/hubfs/levis.svg)](https://www.bitovi.com/web-application-consulting-work/levis-ecommerce-responsive-redesign)
- [![Christie's International Real Estate](https://www.bitovi.com/hubfs/christies.svg)](https://design.bitovi.com/christies)
- [![BAFS](https://www.bitovi.com/hubfs/bafs.svg)](https://www.bitovi.com/ux-design-consulting/ux-case-studies/bafs-ppp)
- [View more
  
  →
  
  ](https://www.bitovi.com/our-software-consulting-work)

Open Source Tools

We build powerful tools and open source them to support the community.

[See what we've built →](https://www.bitovi.com/open-source)

- [![Blog](https://www.bitovi.com/hubfs/icon%20-%20blog.svg)
  
  BlogWe post about delivering products and solving problems.
  
  ](https://www.bitovi.com/blog)
- [![Partnerships](https://www.bitovi.com/hubfs/Handshake-1.svg)
  
  PartnershipsLearn about Bitovi's technology partners
  
  ](https://www.bitovi.com/partnerships)
- [![Academy](https://www.bitovi.com/hubfs/icon%20-%20academy%20(4).svg)
  
  AcademyFree courses to build delivery skills
  
  ](https://www.bitovi.com/academy)
- [![Open source tools](https://www.bitovi.com/hubfs/icon%20-%20open%20source.svg)
  
  Open source toolsUse or contribute to our community
  
  ](https://www.bitovi.com/open-source)

Let's Connect

- [![Discord](https://www.bitovi.com/hubfs/DiscordLogo.svg)
  
  Discord
  
  ](https://discord.gg/J7ejFsZnJ4)
- [![LinkedIn](https://www.bitovi.com/hubfs/LinkedinLogo.svg)
  
  LinkedIn
  
  ](https://www.linkedin.com/company/bitovi/)
- [![GitHub](https://www.bitovi.com/hubfs/GithubLogo.svg)
  
  GitHub
  
  ](https://github.com/bitovi/)

![Eggbot](https://www.bitovi.com/hubfs/build_assets/bitovi-limbo-cms-react/338/js_client_assets/assets/eggbot-LTGhdSGL.png)

Name *

Work Email *

Phone

What's your project?

Send

### Contact Us

(312) 620-0386contact@bitovi.com

[ Backend ](https://www.bitovi.com/blog/topic/backend) |  March 10, 2026

# Extend Role-Based Authentication in Self-Hosted Temporal with Helm

 Learn how to integrate custom ClaimMappers and Authorizers into Temporal's default Helm structure, configure the internalFrontend service, and authenticate workers and SDK clients via OIDC.

![Matt Chaffe](https://www.bitovi.com/hubfs/headshot-matt-square.jpg)

 Matt Chaffe

Share:

[![Twitter](https://www.bitovi.com/hubfs/limbo-generated/_astro/twitter-white.os3xLc3C_Z2nW4or.svg) ](https://twitter.com/intent/tweet?text=) [![Reddit](https://www.bitovi.com/hubfs/limbo-generated/imgs/icons/reddit.png) ](http://reddit.com/submit?url=)

**Repo:** [temporal-auth (helm-support branch)](https://github.com/bitovi/temporal-auth/tree/helm-support)

In [Part 1 of this series](https://www.bitovi.com/blog/implementing-role-based-authentication-for-self-hosted-temporal), we laid the foundation for securing Temporal namespaces with fine-grained access control. In Part 2, we go deeper: integrating custom ClaimMappers and Authorizers into Temporal's default Helm structure, splitting internal from external traffic, and authenticating both human users and service workers via OIDC.

This post covers:

- What ClaimMappers and Authorizers do
- How to extend Temporal's server to integrate your custom logic
- How to use the custom image with Helm
- Why the `internalFrontend` service is needed, and how to configure it
- How to integrate OIDC logins and Server-to-Server tokens for workers and clients

## What are ClaimMappers and authorizers in Temporal?

Before diving into code, here's a quick recap of the two core concepts:

**ClaimMapper** A ClaimMapper takes an incoming authentication token (typically an OIDC/JWT), validates it, and extracts structured claims such as user ID, roles, and organization.

Example flow:

- Validate JWT signature against your OIDC provider
- Extract `email`, `groups`, `namespace_permissions`

**Authorizer** An Authorizer is called on every Temporal request. It checks the target API (e.g., `StartWorkflowExecution`) and target namespace against the user's claims, then allows or denies the request.

Together, they let you enforce organization-specific rules:

- Only the finance team can start workflows in the `payroll` namespace
- Developers may query workflow status but cannot terminate them
- Service accounts may only interact with a subset of task queues

### Implementing custom ClaimMapper and authorizer logic

Here's the core server extension. The key detail: the `internalFrontend` service uses Noop implementations to bypass auth for internal cluster traffic.

```
temporalService := os.Getenv("SERVICES")
if temporalService != "" {
  log.Printf("Starting service: %s", temporalService)
  startService = []string{temporalService}
} else {
  log.Printf("Starting all services")
  startService = temporal.DefaultServices
}

oidc := NewOIDCClaimMapper()
claim := NewOIDCAuthorizer()

if slices.Contains(startService, "internal-frontend") {
    log.Printf("Using noop authentication for internal-frontend")
    oidc = authorization.NewNoopClaimMapper()
    claim = authorization.NewNoopAuthorizer()
}
```

We use Noop for the `internalFrontend` service, to bypass security.

Temporal is composed of multiple services (`frontend`, `history`, `matching`, `worker`). They constantly talk to each other internally. These internal calls don’t need to be authorized through OIDC, otherwise your cluster would effectively block itself.

That’s where the `internalFrontend` comes in:

- It’s a clone of the frontend service that runs inside the cluster.
- Internal Temporal services ( `history` , `matching` , `workers` ) talk to `internalFrontend` .
- External requests (from SDK clients and workers) hit the frontend, which enforces authentication and authorization.

This split allows you to add custom logic for external calls while avoiding unnecessary checks for internal traffic.

![Mermaid Chart - Create complex, visual diagrams with text. A smarter way of creating diagrams.-2025-09-23-123846](https://www.bitovi.com/hs-fs/hubfs/Mermaid%20Chart%20-%20Create%20complex%2c%20visual%20diagrams%20with%20text.%20A%20smarter%20way%20of%20creating%20diagrams.-2025-09-23-123846.png?width=760&height=502&name=Mermaid%20Chart%20-%20Create%20complex%2c%20visual%20diagrams%20with%20text.%20A%20smarter%20way%20of%20creating%20diagrams.-2025-09-23-123846.png)

## Configuring Temporal with Helm

With the server changes above, build and deploy your custom image, then reference it in the Temporal Helm chart:

```
server:
  image: 
    repository: temporal-auth # Update to your custom repo+image
    tag: latest # Update to your custom tag
    imagePullPolicy: Always
  internalFrontend:
    enabled: true
  additionalEnv:
    - name: TEMPORAL_CONFIG_FILENAME
      value: config
    - name: TEMPORAL_CONFIG_PATH
      value: /app/config
   - name: TEMPORAL_CONFIG_TEMPLATE_PATH
      value: /etc/temporal/config/config_template.yaml
    - name: TEMPORAL_AUTH_PROVIDER_URL
      valueFrom:
        secretKeyRef:
          name: temporal-auth-secrets
          key: issuer_url
    - name: TEMPORAL_AUTH_CLIENT_ID
      valueFrom:
        secretKeyRef:
          name: temporal-auth-secrets
          key: client_id

web:
  additionalEnv:
    - name: TEMPORAL_AUTH_ENABLED
      value: "true"
    - name: TEMPORAL_AUTH_CALLBACK_URL
      value: "http://localhost:8080/auth/sso/callback"
    - name: TEMPORAL_AUTH_SCOPES
      value: "openid,email,profile"
    - name: TEMPORAL_AUTH_PROVIDER_URL
      valueFrom:
        secretKeyRef:
          name: temporal-auth-secrets
          key: issuer_url
    - name: TEMPORAL_AUTH_CLIENT_ID
      valueFrom:
        secretKeyRef:
          name: temporal-auth-secrets
          key: client_id
    - name: TEMPORAL_AUTH_CLIENT_SECRET
      valueFrom:
        secretKeyRef:
          name: temporal-auth-secrets
          key: client_secret
```

The above helm values will enable auth for the external-facing frontend, is configured by the additionalEnv field, and creates a separate internal vs external frontend deployment.

Here is what the `secrets.yaml` would look like for your deployment.

```
apiVersion: v1
kind: Secret
metadata:
  name: temporal-auth-secrets
stringData:
  issuer_url: https://YOUR_OIDC_DOMAIN
  client_id:  (from your Okta app)
  client_secret:  (from your Okta app)
```

## Authenticating workers and SDK clients with OIDC

### What Is OIDC?

OpenID Connect (OIDC) is an identity layer built on OAuth 2.0. It lets applications like Temporal verify a user's identity through an external Identity Provider (IdP) such as Okta, Auth0, or Keycloak. OIDC issues signed JWTs containing user claims, which drive both authentication and authorization decisions.

### Human Users

For users, the entry point is the Temporal Web UI. With OIDC configured:

1. Users log in through your identity provider
2. The Web UI receives a token and passes it with each request
3. The ClaimMapper and Authorizer enforce access based on the claims in that token

### Workers and SDK Clients (Server-to-Server)

Workers and SDK clients need a Server-to-Server (S2S) flow:

- Mint service tokens from your OIDC provider using the client credentials flow, static service accounts, or a token exchange endpoint
- Configure workers/clients to attach these tokens when connecting to Temporal
- Your Authorizer logic should distinguish between human users and service accounts

Here's a minimal Go example showing how a worker attaches a JWT Bearer token to Temporal requests:

```
// SimpleTokenProvider provides a basic Bearer token for authentication
type SimpleTokenProvider struct {
	Token string
}

// GetHeaders returns the Authorization header with the Bearer token
func (s *SimpleTokenProvider) GetHeaders(ctx context.Context) (map[string]string, error) {
	return map[string]string{
		"Authorization": "Bearer " + s.Token,
	}, nil
}

// NewSimpleTokenProvider creates a new simple token provider
func NewSimpleTokenProvider(token string) *SimpleTokenProvider {
	return &SimpleTokenProvider{
		Token: token,
	}
}

func main() {
	token := os.Getenv("TEMPORAL_AUTH_TOKEN")
	if token == "" {
		log.Fatalln("Set TEMPORAL_AUTH_TOKEN environment variable for custom token.")
	}

	c, err := client.Dial(client.Options{
		HostPort:        "localhost:7233",
		Namespace:       "bitovi-project",
		HeadersProvider: auth.NewSimpleTokenProvider(token),
	})
	if err != nil {
		log.Fatalln("Unable to create client", err)
	}
	defer c.Close()

	w := worker.New(c, "hello-world", worker.Options{})

	w.RegisterWorkflow(helloworld.Workflow)
	w.RegisterActivity(helloworld.Activity)

	err = w.Run(worker.InterruptCh())
	if err != nil {
		log.Fatalln("Unable to start worker", err)
	}
}
```

## Conclusion

Extending Temporal's authentication layer isn't just a security checkbox. It's how you make a self-hosted Temporal cluster actually production-ready. With a custom ClaimMapper and Authorizer in place, you control exactly who can do what, in which namespace, and from which service. The `internalFrontend` pattern keeps that enforcement from collapsing under the weight of internal cluster traffic, and the Helm configuration makes the whole thing repeatable across environments.

If you're building on top of Part 1, you now have the full picture: from claim extraction to authorization logic to worker authentication. The next step is hardening your token issuance strategy and making sure your Authorizer handles edge cases like expired tokens, missing claims, and service account rotation.

## Work with Bitovi on Temporal

Setting up Temporal authentication is one piece of a larger architecture decision. If your team is evaluating self-hosted Temporal, migrating from a managed service, or trying to get role-based access right across multiple namespaces, Bitovi can help.

Our engineers have hands-on experience building and scaling Temporal workflows in production. We work embedded with your team, not around it.

[Talk to a Temporal consultant at Bitovi →](https://www.bitovi.com/services/backend/temporal-consulting)

---

## FAQ

**What is a ClaimMapper in Temporal?** A ClaimMapper is a component that validates an incoming JWT from an OIDC provider and extracts structured claims (user ID, roles, namespace permissions) that the Authorizer uses to make access decisions.

**What is the internalFrontend service in Temporal?** The `internalFrontend` is a separate instance of Temporal's frontend service used exclusively for internal cluster communication. It bypasses OIDC auth so that internal services like `history` and `matching` can communicate without being blocked by the external auth layer.

**How do Temporal workers authenticate with OIDC?** Workers use a Server-to-Server (S2S) token flow. They mint a service token from the OIDC provider and attach it as a Bearer token on each request via a `HeadersProvider`. The Authorizer then validates the token and grants or restricts access based on the service account's claims.

**Can I use this setup with any OIDC provider?** Yes. The ClaimMapper and Authorizer logic is provider-agnostic. Okta, Auth0, Keycloak, and PocketID all work as long as they issue standard OIDC JWTs.

[![Tag for temporal](https://www.bitovi.com/hubfs/limbo/icons/tag.svg) temporal ](https://www.bitovi.com/blog/topic/temporal)

 Previous Post

![](https://www.bitovi.com/hs-fs/hubfs/HowtoBuildFlexibleTableComponentsinFigmaUsingSlots.png?height=117&name=HowtoBuildFlexibleTableComponentsinFigmaUsingSlots.png) [ How to Build Flexible Table Components in Figma Using Slots ](https://www.bitovi.com/blog/how-to-build-flexible-table-components-in-figma-using-slots)

  

 Next Post

![](https://www.bitovi.com/hubfs/Figma_Lockup-4.svg) [ Figma's MCP Just Gave AI Agents 'Write' Access. A First Look at What It Can Do. ](https://www.bitovi.com/blog/figma-just-opened-the-canvas-to-agents.-heres-what-actually-happens)

```json
{
  "@context" : "http://schema.org",
  "@type" : "Organization",
  "address" : {
    "@type" : "PostalAddress",
    "addressCountry" : "United States",
    "addressLocality" : "Libertyville",
    "addressRegion" : "IL",
    "postalCode" : "60048",
    "streetAddress" : "1134 Pine Tree Lane "
  },
  "alternateName" : "Bitovi",
  "areaServed" : {
    "@type" : "GeoCircle",
    "geoMidpoint" : {
      "@type" : "GeoCoordinates",
      "latitude" : "41.8781",
      "longitude" : "87.6298"
    },
    "geoRadius" : "5000 km"
  },
  "description" : "Bitovi is a UX, UI design and front-end JavaScript development consulting company",
  "email" : "contact@bitovi.com",
  "image" : "https://www.bitovi.com/hubfs/bitovi-logo-x2.png",
  "logo" : "https://www.bitovi.com/hubfs/bitovi-logo-23-1.svg",
  "mainEntityOfPage" : {
    "@id" : "https://www.bitovi.com/blog/extend-role-based-authentication-in-self-hosted-temporal-with-helm",
    "@type" : "WebPage",
    "description" : "Learn how to integrate custom ClaimMappers and Authorizers into Temporal's default Helm structure, configure the internalFrontend service, and authenticate workers and SDK clients via OIDC."
  },
  "naics" : "541511",
  "name" : "Bitovi Web App Consulting",
  "sameAs" : [ "https://www.facebook.com/BitoviLLC/", "https://twitter.com/bitovi", "https://www.linkedin.com/company/bitovi" ],
  "telephone" : "312-620-0386",
  "url" : "http://bitovi.com"
}
```

```json
{
  "@context" : "http://schema.org",
  "@type" : "BlogPosting",
  "author" : {
    "@type" : "Person",
    "name" : "Matt Chaffe"
  },
  "dateModified" : "April 8, 2026, 5:17:38 PM",
  "datePublished" : "2026-03-10 13:00:07",
  "description" : "Learn how to integrate custom ClaimMappers and Authorizers into Temporal's default Helm structure, configure the internalFrontend service, and authenticate workers and SDK clients via OIDC.",
  "headline" : "Extend Role-Based Authentication in Self-Hosted Temporal with Helm",
  "image" : {
    "@type" : "ImageObject",
    "url" : "https://www.bitovi.com/hubfs/Extend-Role-Based-Authentication-in-Self-Hosted-Temporal-with-Helm.png"
  },
  "publisher" : {
    "@type" : "Organization",
    "logo" : {
      "@type" : "ImageObject",
      "url" : "https://www.bitovi.com/hubfs/bitovi-logo-23-1.svg"
    },
    "name" : "Bitovi"
  }
}
```

```json
{
  "@context" : "https://schema.org",
  "@type" : "BlogPosting",
  "articleSection" : "Engineering",
  "author" : {
    "@type" : "Person",
    "name" : "Matt Chaffe",
    "url" : "https://www.bitovi.com/community/matt-chaffe"
  },
  "dateModified" : "2026-03-10",
  "datePublished" : "2026-03-10",
  "description" : "Learn how to integrate custom ClaimMappers and Authorizers into Temporal's default Helm structure, configure the internalFrontend service, and authenticate workers and SDK clients via OIDC.",
  "headline" : "Extend Role-Based Authentication in Self-Hosted Temporal with Helm",
  "isPartOf" : {
    "@type" : "BlogPosting",
    "name" : "Role-Based Authentication for Self-Hosted Temporal",
    "url" : "https://www.bitovi.com/blog/implementing-role-based-authentication-for-self-hosted-temporal"
  },
  "keywords" : [ "Temporal authentication", "role-based access control Temporal", "Temporal Helm configuration", "ClaimMapper Temporal", "Authorizer Temporal", "OIDC Temporal", "self-hosted Temporal", "internalFrontend Temporal", "Temporal worker authentication", "Temporal JWT" ],
  "mainEntityOfPage" : {
    "@id" : "https://www.bitovi.com/blog/extend-role-based-authentication-in-self-hosted-temporal-with-helm",
    "@type" : "WebPage"
  },
  "publisher" : {
    "@type" : "Organization",
    "logo" : {
      "@type" : "ImageObject",
      "url" : "https://www.bitovi.com/hubfs/Bitovi_April2022/Images/bitovi-logo.svg"
    },
    "name" : "Bitovi",
    "url" : "https://www.bitovi.com"
  },
  "url" : "https://www.bitovi.com/blog/extend-role-based-authentication-in-self-hosted-temporal-with-helm"
}
```

```json
{
  "@context" : "https://schema.org",
  "@type" : "TechArticle",
  "author" : {
    "@type" : "Person",
    "name" : "Matt Chaffe",
    "url" : "https://www.bitovi.com/community/matt-chaffe"
  },
  "dateModified" : "2026-03-10",
  "datePublished" : "2026-03-10",
  "dependencies" : "Temporal, Helm, Kubernetes, OIDC (Okta / Auth0 / Keycloak)",
  "description" : "A technical guide to integrating ClaimMappers, Authorizers, and OIDC into a self-hosted Temporal cluster using Helm, including internalFrontend configuration and worker token authentication.",
  "headline" : "How to Extend Role-Based Authentication in Self-Hosted Temporal with Helm",
  "proficiencyLevel" : "Expert",
  "programmingLanguage" : "Go",
  "publisher" : {
    "@type" : "Organization",
    "name" : "Bitovi",
    "url" : "https://www.bitovi.com"
  },
  "url" : "https://www.bitovi.com/blog/extend-role-based-authentication-in-self-hosted-temporal-with-helm"
}
```

```json
{
  "@context" : "https://schema.org",
  "@type" : "FAQPage",
  "mainEntity" : [ {
    "@type" : "Question",
    "acceptedAnswer" : {
      "@type" : "Answer",
      "text" : "A ClaimMapper is a component that validates an incoming JWT from an OIDC provider and extracts structured claims (user ID, roles, namespace permissions) that the Authorizer uses to make access decisions."
    },
    "name" : "What is a ClaimMapper in Temporal?"
  }, {
    "@type" : "Question",
    "acceptedAnswer" : {
      "@type" : "Answer",
      "text" : "The internalFrontend is a separate instance of Temporal's frontend service used exclusively for internal cluster communication. It bypasses OIDC auth so that internal services like history and matching can communicate without being blocked by the external auth layer."
    },
    "name" : "What is the internalFrontend service in Temporal?"
  }, {
    "@type" : "Question",
    "acceptedAnswer" : {
      "@type" : "Answer",
      "text" : "Workers use a Server-to-Server (S2S) token flow. They mint a service token from the OIDC provider and attach it as a Bearer token on each request via a HeadersProvider. The Authorizer then validates the token and grants or restricts access based on the service account's claims."
    },
    "name" : "How do Temporal workers authenticate with OIDC?"
  }, {
    "@type" : "Question",
    "acceptedAnswer" : {
      "@type" : "Answer",
      "text" : "Yes. The ClaimMapper and Authorizer logic is provider-agnostic. Okta, Auth0, Keycloak, and PocketID all work as long as they issue standard OIDC JWTs."
    },
    "name" : "Can I use this Temporal authentication setup with any OIDC provider?"
  } ]
}
```