Skip to main content

Authentication and Authorization

This guide describes how to configure authentication providers and tenant assignment for Feldera Enterprise.

Feldera supports authentication through OIDC/OAuth2 providers, enabling secure multi-tenant deployments with flexible tenant assignment strategies.

Authentication model

Feldera API supports two authentication types:

  • OIDC: Requests should include a valid OIDC Access token in the Authorization HTTP header in the shape Bearer <token>

  • API key: Authorized Feldera users can generate API keys to be included in the Authorization HTTP header in the shape Bearer <token>

Authorization model

Feldera Tenant is a scope of access to Feldera pipelines for their management and configuration. The same tenant can be assigned to multiple users for shared access. The ingress and egress business data flow, which is configured through connectors, has it's own connector-dependent authentication and is not subject to tenant-based authorization.

Interaction with Feldera is always authorized through a tenant, so access to the platform implies assigning tenant to the user. For OIDC authentication, the tenants a user may act in are stored by Feldera; a tenancy strategy can provision memberships automatically at login from the OIDC Access token. For API key authentication, the key is associated with the tenant through which the key was generated. We support multiple authorization use-cases through strategies to provision tenants and memberships for Feldera API and clients' users.

As an orthogonal feature, the authorized-groups startup parameter can be used to limit access to the users who are a member of at least one of the groups in this list. The membership is determined based on the groups claim of an OIDC Access token. Users must belong to at least one of the specified groups to access Feldera. If authorizedGroups is not specified or empty, no group restrictions apply.

This group check applies to every principal, including platform owners: the membership check runs before owner resolution, so an identity listed in owners that is not in any authorized group is still denied access. Being an owner does not exempt a user from the group requirement.

Tenant Assignment Strategies

A user acts in the tenants they hold a membership in, at the role the membership records. Memberships are granted through the member-management API and web console, and, by default (authorization.provisionOnLogin: true), also provisioned at login by one of three strategies:

Individual Tenancy (Enabled by default)

Each authenticated user gets their own private tenant based on the sub claim of the OIDC Access token. Does not require authentication provider configuration. Configured with authorization.individualTenant Helm value.

Organization-wide Tenancy

Users from the same organization share a tenant, derived from the issuer hostname of the authentication token. Does not require authentication provider configuration. Configured with authorization.issuerTenant Helm value.

Managed Tenancy (deprecated)

Each team's users are assigned to their tenant(s) through the dynamic tenants claim in the OIDC Access token. tenants can contain either a list, or a string of comma-separated tenant names; empty entries are ignored.

The claim provisions rather than restricts: the deliberately selected tenant is created if absent and the user enrolled, further listed names enroll the user into tenants that already exist, and the user may additionally act in any tenant they hold a membership in, whether the claim names it or not. Narrowing the claim therefore does not revoke access; remove the membership as well (see Revoking access).

This strategy is deprecated in favor of managing memberships in Feldera directly, which needs no claim mapping at the identity provider; see Migrating to Feldera-managed memberships. One consequence for new multi-entry-claim users: a listed tenant that does not exist yet is not created by their login unless they select it with the Feldera-Tenant header, so create tenants up front with POST /v0/tenants.

Turning login provisioning off

authorization.provisionOnLogin: false (default true) disables all three strategies at once: a login creates no tenant and enrolls no one, and access comes only from memberships granted through the API and console. This is the recommended end state for enterprise deployments, because access then has one audit trail and one revocation lever. It requires a configured authorization.owners or authorization.ownerTrusts; the manager refuses to start otherwise, because without an owner no principal could ever grant access.

The user interacts with the API through a single tenant at a time. A user who belongs to several tenants switches tenants in the Web Console, or names one in the Feldera-Tenant header on HTTP API calls.

Tenant Assignment use cases

Listed below are example configurations for common authorization use-cases achieved through a combination of tenant assignment strategy and whitelisted group access.

Development environment - no authentication

Helm Configuration:

auth:
enabled: false

Individual access

Every user gets their individual tenant based on their sub claim.

Helm Configuration:

auth:
enabled: true
provider: "generic-oidc"
clientId: "0oa1a2b3c4d5e6f7g8h9"
issuer: "https://dev-12345.okta.com/oauth2/default"

authorization:
individualTenant: true
issuerTenant: false
authAudience: "feldera-api"

Organization-wide shared access

All users in your organization share the same tenant based on the organization domain.

The tenant name is extracted from OIDC issuer domain:

  • https://acme-corp.okta.com/oauth2/defaultacme-corp.okta.com tenant

Helm Configuration:

auth:
enabled: true
provider: "generic-oidc"
clientId: "0oa1a2b3c4d5e6f7g8h9"
issuer: "https://acme-corp.okta.com/oauth2/default"

authorization:
individualTenant: false
issuerTenant: true
authAudience: "feldera-api"

Group-based whitelist with organization-wide shared access

Users must belong to at least one of the specified groups to access Feldera. All authorized users share the organization tenant.

Helm Configuration:

auth:
enabled: true
provider: "generic-oidc"
clientId: "0oa1a2b3c4d5e6f7g8h9"
issuer: "https://company.okta.com/oauth2/default"

authorization:
individualTenant: false
issuerTenant: true
authorizedGroups:
- "feldera-engineering"
- "feldera-qa"
authAudience: "feldera-api"

Shared access within a user group (managed tenancy)

Tenant assignment via tenants claim in JWT configured in your OIDC provider.

Helm Configuration:

auth:
enabled: true
provider: "generic-oidc"
clientId: "0oa1a2b3c4d5e6f7g8h9"
issuer: "https://company.okta.com/oauth2/default"

authorization:
individualTenant: false
issuerTenant: false
authAudience: "feldera-api"

Individual access to whitelisted user groups

Each user gets their individual tenant, but only users belonging to specified groups can access Feldera.

Helm Configuration:

auth:
enabled: true
provider: "generic-oidc"
clientId: "0oa1a2b3c4d5e6f7g8h9"
issuer: "https://company.okta.com/oauth2/default"

authorization:
individualTenant: true
issuerTenant: false
authorizedGroups:
- "feldera-engineering"
- "feldera-qa"
authAudience: "feldera-api"

Changing your authentication setup

Feldera supports a single identity provider at a time. Two supported changes alter which tenant a login lands in: 1) enabling authentication on a deployment that ran without it, and 2) pointing an authenticated deployment at a different provider. Both need planning, because a tenant is where pipelines live.

How a tenant is identified

A tenant is identified by its name alone. The name is derived from the token on each login, by whichever tenant assignment strategy you configured.

A user is identified by the pair (issuer, subject), where the subject is the token's sub claim. That pair is what memberships and roles are based on. Note, OIDC only guarantees sub to be unique within one issuer, which is why the issuer is part of the pair.

In short, a tenant can survive a provider change, but the users in it cannot. Users arrive as new identities and must be granted their roles again.

Enabling authentication on an existing deployment

Plan this before you enable authentication

Without authentication, all pipelines live in a built-in tenant named default, whose id is the all-zero UUID 00000000-0000-0000-0000-000000000000.

When authentication is enabled for the first time in such a deployment, logins resolve to a tenant named by your authentication provider and tenant strategy. This makes default tenant pipelines and API keys no longer visible to authenticated logins, even though the data is intact.

To avoid this problem, plan the following steps before enabling authentication on a deployment that already holds pipelines.

A platform owner can still reach the default tenant by naming it explicitly:

curl -H "Authorization: Bearer $OWNER_TOKEN" \
-H "Feldera-Tenant: 00000000-0000-0000-0000-000000000000" \
https://<your-host>/v0/pipelines

There are two options:

  • Recreate the resources in the tenant your logins now reach, then stop and delete the pipelines left behind in default. Deleting them matters: a pipeline nobody can see still holds its Kubernetes pods and volumes, running and unaccounted for.
  • Put default in that tenant's place, by giving it the new tenant name your logins resolve.

To rename the default tenant, 00000000-0000-0000-0000-000000000000, to acme.us-west1.idp.com:

curl -X PATCH -H "Authorization: Bearer $OWNER_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "acme.us-west1.idp.com", "displace_existing": true}' \
https://<your-host>/v0/tenants/00000000-0000-0000-0000-000000000000

The first login after the switch already created a tenant named acme.us-west1.idp.com, so the rename needs displace_existing. It hands the name over: default takes it, and the tenant that held it is renamed out of the way and reported in the response under displaced. Logins now resolve to your original pipelines.

The displaced tenant is empty, so delete it:

curl -X DELETE -H "Authorization: Bearer $OWNER_TOKEN" \
https://<your-host>/v0/tenants/<displaced id>

Changing the identity provider

When changing identity providers, each tenant's name (per the provider-supplied tokens) decides whether it survives the migration:

StrategyTenant name comes fromSurvives a provider change?
Managed tenancythe tenants claimYes, if you configure the new provider to emit the same values
Organization-widethe issuer hostnameOnly if the hostname is unchanged, e.g. a new authorization server on the same domain
Individual tenancythe sub claimNo, in practice: a new provider issues different subjects

Managed tenancy migrates cleanly, because the tenant name is a value you control at the provider rather than something derived from it. Use this strategy if you expect to change providers regularly.

Where the name does change, the old tenant keeps every pipeline and is no longer reachable by ordinary logins. Recover it the same way as above: an owner selects it with Feldera-Tenant (by name or UUID; GET /v0/tenants lists both, and GET /v0/tenants/{tenant_id} retrieves one by either selector) and moves what is needed, or gives it the name the new provider produces, with displace_existing, so the logins land back on it.

In general, do not leave pipelines in an unreachable tenant. The corresponding pipelines use system resources (like Kubernetes pods) while running and can go unnoticed. Stop and delete those pipelines, then delete the empty tenant with DELETE /v0/tenants/{tenant_id}.

The destructive rename works the opposite way: taking a name away from the tenant whose users still arrive under it. Say you rename acme.us-west1.idp.com to an unreachable tmp while the provider keeps asserting acme.us-west1.idp.com. The next request from those users re-creates that name as an empty tenant, which is where they then work. Rename a tenant only to a name you want its users to arrive under.

Roles are not carried across a provider change

Even when the tenant survives, its members do not. A membership is keyed to (issuer, subject), so after the switch every user is a new identity with no membership, and each is admitted at authorization.defaultRole. Administrators and pre-provisioned members must be granted their roles again, and at least one identity from the new provider must be listed in authorization.owners so that someone can do the granting. See Roles.

Migrating to Feldera-managed memberships

A deployment using the deprecated managed tenancy (tenants claim) moves to Feldera-managed memberships as follows:

  1. Upgrade Feldera. provisionOnLogin stays true; nothing changes at the identity provider yet.
  2. Audit existing memberships per tenant with GET /v0/tenant/users: every past login left a membership row, including for users whose claim no longer names the tenant. Remove rows that should not confer access, because they do now.
  3. Populate the memberships you want: let every user log in once, or pre-provision them with POST /v0/tenant/users.
  4. Verify per tenant that the member list matches the intended access.
  5. Confirm authorization.owners (or ownerTrusts) is set; the manager refuses to start without one in the next step.
  6. Set authorization.provisionOnLogin: false and restart.
  7. Delete the tenants claim mapping at the identity provider.

Deployments on individual or organization-wide tenancy need no migration: behavior is unchanged until an admin grants cross-tenant memberships, and provisionOnLogin: false is available whenever explicit provisioning is preferred.

How members are identified in the member list

A membership is keyed to an OIDC subject, which is rarely a string anyone recognizes. So that an administrator can tell members apart, GET /v0/tenant/users, the web console's member list, and fda member list also report the name and email the identity provider holds:

FieldSource
subjectthe token's sub; the identity itself
display_namethe provider's name, or preferred_username
emailthe provider's email, or an email supplied when pre-provisioning
email_verifiedwhether the provider vouches for email

Feldera reads the name and email from the provider's OIDC UserInfo endpoint, because an access token often carries neither.

Configuration options

Mapping Pipeline Manager Options to Helm Chart Values

Feldera's authentication and authorization are configured through pipeline-manager command-line options. When deploying via Helm, these options map to values in your values.yaml file.

Complete Configuration Template

Below is a comprehensive template showing all available authentication and authorization options:

# Authentication provider configuration
auth:
enabled: true # Enable/disable authentication
provider: "generic-oidc" # Maps to: AUTH_PROVIDER; Options: "none", "aws-cognito", "generic-oidc"
clientId: "your-client-id" # Maps to: FELDERA_AUTH_CLIENT_ID
issuer: "https://your-domain/oauth2/default" # Maps to: FELDERA_AUTH_ISSUER

# AWS Cognito specific (only when provider: "aws-cognito")
cognitoLoginUrl: "" # Maps to: AWS_COGNITO_LOGIN_URL
cognitoLogoutUrl: "" # Maps to: AWS_COGNITO_LOGOUT_URL

# Authorization and tenant assignment configuration
authorization:
# Individual tenant mode - each user gets their own tenant (default: true)
individualTenant: true # Maps to: FELDERA_AUTH_INDIVIDUAL_TENANT

# Issuer-based tenant - derive tenant from auth issuer domain (default: false)
issuerTenant: false # Maps to: FELDERA_AUTH_ISSUER_TENANT

# Group-based access control - restrict access to specific groups
# Users must have at least one of these groups in their 'groups' claim
authorizedGroups: # Maps to: FELDERA_AUTH_AUTHORIZED_GROUPS
- "feldera-users"
- "data-engineers"

# OIDC audience claim validation (default: "feldera-api")
authAudience: "feldera-api" # Maps to: FELDERA_AUTH_AUDIENCE

# Platform owners: identities granted the platform-wide `owner` role (default: [])
owners: # Maps to: FELDERA_OWNERS
- "ops@example.com"

# Workloads granted `owner`, matched on their OIDC token (default: [])
ownerTrusts: # Maps to: FELDERA_OWNER_TRUSTS
- issuer: "https://token.actions.githubusercontent.com"
subject: "repo:acme/infra:ref:refs/heads/main"
audience: "https://github.com/acme"

# Role for an authenticated user with no explicit membership yet (default: "read")
# Ship "write" when upgrading a pre-RBAC deployment; see the Roles page.
defaultRole: "write" # Maps to: FELDERA_AUTH_DEFAULT_ROLE

# Role for the user whose login first creates a tenant (default: "admin")
# Set to "write"/"read" for a shared sandbox; see the Roles page.
firstUserRole: "admin" # Maps to: FELDERA_AUTH_FIRST_USER_ROLE

# Provision tenants and memberships at login per the tenancy strategy
# (default: true). false = access comes only from memberships granted
# through the API and console; requires owners or ownerTrusts.
provisionOnLogin: true # Maps to: FELDERA_AUTH_PROVISION_ON_LOGIN

Environment Variables Reference

If you need to configure pipeline-manager directly (without Helm), use these environment variables:

Required Variables

# OIDC provider configuration
FELDERA_AUTH_ISSUER=https://<your-domain>/oauth2/<custom-auth-server-id>
FELDERA_AUTH_CLIENT_ID=<your-client-id>

Optional Variables

# Authorization configuration
FELDERA_AUTH_INDIVIDUAL_TENANT=true # default: true
FELDERA_AUTH_ISSUER_TENANT=false # default: false
FELDERA_AUTH_AUTHORIZED_GROUPS=group1,group2 # comma-separated list
FELDERA_AUTH_AUDIENCE=feldera-api # default: feldera-api
FELDERA_OWNERS=ops@example.com # comma-separated; default: (none)
FELDERA_OWNER_TRUSTS='[{"issuer":"https://token.actions.githubusercontent.com","subject":"repo:acme/infra:*"}]'
# JSON array; default: []
FELDERA_AUTH_DEFAULT_ROLE=read # read or write; default: read
FELDERA_AUTH_FIRST_USER_ROLE=admin # read, write, or admin; default: admin
FELDERA_AUTH_PROVISION_ON_LOGIN=true # default: true; false requires owners

# AWS Cognito specific
AWS_COGNITO_LOGIN_URL=https://...
AWS_COGNITO_LOGOUT_URL=https://...

Tenant Resolution

A login's acting tenant comes from the user's memberships:

  1. A Feldera-Tenant header (tenant name or UUID) selects the tenant; it must be one the user holds a membership in. An unknown tenant and one the user is no member of are answered alike, so the header cannot be used to probe which tenants exist.
  2. Without a header, a user with exactly one membership acts in it.
  3. Without a header, a user with several memberships is refused; the session endpoint still answers, listing the memberships so a client can pick one (the Web Console shows a tenant picker).
  4. A user with no membership at all is denied, again except for the session endpoint, which answers with an empty membership list so a client can show a useful message.

Before this resolution, and only while provisionOnLogin is true (the default), the login provisions memberships in priority order: the tenants claim, the issuer domain (when issuerTenant: true), or the user's sub (when individualTenant: true). With all three strategies off, or with provisionOnLogin: false, a login provisions nothing and case 4 applies until an admin grants a membership.

Provider-Specific Setup

Feldera supports the following authentication providers:

  • AWS Cognito
  • Okta
  • Google Identity
  • Generic OIDC

Each authentication provider requires specific configuration. Choose your provider below: