Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
5514919
feat: Extract groups and namespaces claims from JWT in OidcTokenParser
aniketpalu Mar 10, 2026
253eb34
Merge branch 'master' into oidc-support
aniketpalu Mar 10, 2026
9495db0
Minor formatting
aniketpalu Mar 10, 2026
57deeeb
Merge branch 'master' into oidc-support
aniketpalu Mar 10, 2026
41522ba
feat: Allow Feast SDK to accept a pre-existing OIDC token without con…
aniketpalu Mar 10, 2026
1f4d2d2
Merge branch 'master' into oidc-support
aniketpalu Mar 10, 2026
8c8e805
Merge branch 'master' into oidc-support
aniketpalu Mar 10, 2026
dca71da
fix: Raise error when configured token_env_var is empty
aniketpalu Mar 10, 2026
44a2727
Minor formatting changes
aniketpalu Mar 10, 2026
62947e7
Activate _check_mutually_exclusive groups only when all fields are se…
aniketpalu Mar 10, 2026
19ea1e3
Merge branch 'master' into oidc-support
aniketpalu Mar 11, 2026
b1bc8df
Merge branch 'master' into oidc-support
aniketpalu Mar 11, 2026
0bb5c57
Narrow OIDC client routing to use set-based key detection and extract…
aniketpalu Mar 11, 2026
c1e5ecf
Fix .sort() assertions in test_token_parser.py that always compared N…
aniketpalu Mar 11, 2026
3320cea
Guard against missing roles key in resource_access to prevent unhandl…
aniketpalu Mar 11, 2026
4904257
Fixed lint errors
aniketpalu Mar 11, 2026
8be0d21
Fixed lint error
aniketpalu Mar 11, 2026
e32c486
Fixed lint errors
aniketpalu Mar 11, 2026
5892ff5
Added support to read ServiceAccount token and Minor improvements
aniketpalu Mar 11, 2026
f55fc52
Improved code readibility
aniketpalu Mar 11, 2026
b34ad74
Minor reformatting
aniketpalu Mar 11, 2026
a835465
fix: Use exact dict-key lookup for kubernetes.io claim to satisfy Cod…
aniketpalu Mar 12, 2026
49294ef
feat: Add verify_ssl support to OIDC auth flow for self-signed certif…
aniketpalu Mar 20, 2026
24932db
Merge branch 'master' into oidc-support
aniketpalu Mar 20, 2026
712a2b9
feat: Lightweight SA token validation for OIDC auth — TokenReview onl…
aniketpalu Mar 23, 2026
b9726d5
Minor reformatting & lint related changes
aniketpalu Mar 23, 2026
d141df3
Update sdk/python/feast/permissions/auth/oidc_token_parser.py
aniketpalu Mar 23, 2026
7dfe9fd
Merge branch 'master' into oidc-support
aniketpalu Mar 23, 2026
1bfe74b
fix: Restore missing return in intra-comm check and add error handlin…
aniketpalu Mar 23, 2026
9c26b7b
Minor reformatting
aniketpalu Mar 23, 2026
ca1118c
Checks preferred_username first (Keycloak default), then falls back t…
aniketpalu Mar 23, 2026
b51a33f
feat(operator): Split server/client OIDC config and add secretKeyName…
aniketpalu Mar 24, 2026
98a0209
Reverted kustomization.yaml
aniketpalu Mar 24, 2026
8385a74
Merge branch 'master' into oidc-support
aniketpalu Mar 24, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 55 additions & 14 deletions docs/getting-started/components/authz_manager.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,52 +40,87 @@ auth:
With OIDC authorization, the Feast client proxies retrieve the JWT token from an OIDC server (or [Identity Provider](https://openid.net/developers/how-connect-works/))
and append it in every request to a Feast server, using an [Authorization Bearer Token](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication#bearer).

The server, in turn, uses the same OIDC server to validate the token and extract the user roles from the token itself.
The server, in turn, uses the same OIDC server to validate the token and extract user details — including username, roles, and groups — from the token itself.

Some assumptions are made in the OIDC server configuration:
* The OIDC token refers to a client with roles matching the RBAC roles of the configured `Permission`s (*)
* The roles are exposed in the access token that is passed to the server
* The roles are exposed in the access token under `resource_access.<client_id>.roles`
* The JWT token is expected to have a verified signature and not be expired. The Feast OIDC token parser logic validates for `verify_signature` and `verify_exp` so make sure that the given OIDC provider is configured to meet these requirements.
* The preferred_username should be part of the JWT token claim.

* The `preferred_username` should be part of the JWT token claim.
* For `GroupBasedPolicy` support, the `groups` claim should be present in the access token (requires a "Group Membership" protocol mapper in Keycloak).

(*) Please note that **the role match is case-sensitive**, e.g. the name of the role in the OIDC server and in the `Permission` configuration
must be exactly the same.

For example, the access token for a client `app` of a user with `reader` role should have the following `resource_access` section:
For example, the access token for a client `app` of a user with `reader` role and membership in the `data-team` group should have the following claims:
```json
{
"preferred_username": "alice",
"resource_access": {
"app": {
"roles": [
"reader"
]
}
}
},
"groups": [
"data-team"
]
}
```

An example of feast OIDC authorization configuration on the server side is the following:
#### Server-Side Configuration

The server requires `auth_discovery_url` and `client_id` to validate incoming JWT tokens via JWKS:
```yaml
project: my-project
auth:
type: oidc
client_id: _CLIENT_ID__
client_id: _CLIENT_ID_
auth_discovery_url: _OIDC_SERVER_URL_/realms/master/.well-known/openid-configuration
...
```

In case of client configuration, the following settings username, password and client_secret must be added to specify the current user:
When the OIDC provider uses a self-signed or untrusted TLS certificate (e.g. internal Keycloak on OpenShift), set `verify_ssl` to `false` to disable certificate verification:
```yaml
auth:
type: oidc
client_id: _CLIENT_ID_
auth_discovery_url: https://keycloak.internal/realms/master/.well-known/openid-configuration
verify_ssl: false
```

{% hint style="warning" %}
Setting `verify_ssl: false` disables TLS certificate verification for all OIDC provider communication (discovery, JWKS, token endpoint). Only use this in development or internal environments where you accept the security risk.
{% endhint %}

#### Client-Side Configuration

The client supports multiple token source modes. The SDK resolves tokens in the following priority order:

1. **Intra-communication token** — internal server-to-server calls (via `INTRA_COMMUNICATION_BASE64` env var)
2. **`token`** — a static JWT string provided directly in the configuration
3. **`token_env_var`** — the name of an environment variable containing the JWT
4. **`client_secret`** — fetches a token from the OIDC provider using client credentials or ROPC flow (requires `auth_discovery_url` and `client_id`)
5. **`FEAST_OIDC_TOKEN`** — default fallback environment variable
6. **Kubernetes service account token** — read from `/var/run/secrets/kubernetes.io/serviceaccount/token` when running inside a pod

**Token passthrough** (for use with external token providers like [kube-authkit](https://github.com/opendatahub-io/kube-authkit)):
```yaml
project: my-project
auth:
type: oidc
token_env_var: FEAST_OIDC_TOKEN
```

Or with a bare `type: oidc` (no other fields) — the SDK falls back to the `FEAST_OIDC_TOKEN` environment variable or a mounted Kubernetes service account token:
```yaml
project: my-project
auth:
type: oidc
...
username: _USERNAME_
password: _PASSWORD_
client_secret: _CLIENT_SECRET__
```

Below is an example of feast full OIDC client auth configuration:
**Client credentials / ROPC flow** (existing behavior, unchanged):
```yaml
project: my-project
auth:
Expand All @@ -97,6 +132,12 @@ auth:
auth_discovery_url: http://localhost:8080/realms/master/.well-known/openid-configuration
```

When using client credentials or ROPC flows, the `verify_ssl` setting also applies to the discovery and token endpoint requests.

#### Multi-Token Support (OIDC + Kubernetes Service Account)

When the Feast server is configured with OIDC auth and deployed on Kubernetes, the `OidcTokenParser` can handle both Keycloak JWT tokens and Kubernetes service account tokens. Incoming tokens that contain a `kubernetes.io` claim are validated via the Kubernetes Token Access Review API and the namespace is extracted from the authenticated identity — no RBAC queries are performed, so the server service account only needs `tokenreviews/create` permission. All other tokens follow the standard OIDC/Keycloak JWKS validation path. This enables `NamespaceBasedPolicy` enforcement for service account tokens while using `GroupBasedPolicy` and `RoleBasedPolicy` for OIDC user tokens.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we support OIDC token passing from ODH Notebook instead of service account token ? This we alreayd support for kubernetes token.

Not a blocker though, just for consistency.


### Kubernetes RBAC Authorization
With Kubernetes RBAC Authorization, the client uses the service account token as the authorizarion bearer token, and the
server fetches the associated roles from the Kubernetes RBAC resources. Feast supports advanced authorization by extracting user groups and namespaces from Kubernetes tokens, enabling fine-grained access control beyond simple role matching. This is achieved by leveraging Kubernetes Token Access Review, which allows Feast to determine the groups and namespaces associated with a user or service account.
Expand Down
15 changes: 15 additions & 0 deletions infra/feast-operator/api/v1/featurestore_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -709,6 +709,21 @@ type KubernetesAuthz struct {
// https://auth0.com/docs/authenticate/protocols/openid-connect-protocol
type OidcAuthz struct {
SecretRef corev1.LocalObjectReference `json:"secretRef"`
// The key within the Secret that contains the OIDC configuration as a YAML-encoded value.
// When set, only this key is read and its YAML value is expected to contain the OIDC properties
// (e.g. client_id, auth_discovery_url). This allows sharing a single Secret across services.
// When unset, each top-level key in the Secret is treated as a separate OIDC property.
// +optional
SecretKeyName string `json:"secretKeyName,omitempty"`
// The name of the environment variable that client pods will use to read a pre-existing OIDC token.
// When set, the client feature_store.yaml will include token_env_var with this value.
// When unset, the client config is bare `type: oidc` which falls back to FEAST_OIDC_TOKEN or the pod's SA token.
// +optional
TokenEnvVar *string `json:"tokenEnvVar,omitempty"`
// Whether to verify SSL certificates when communicating with the OIDC provider.
// Defaults to true. Set to false for self-signed certificates (common in internal OpenShift clusters).
// +optional
VerifySSL *bool `json:"verifySSL,omitempty"`
}

// TlsConfigs configures server TLS for a feast service. in an openshift cluster, this is configured by default using service serving certificates.
Expand Down
12 changes: 11 additions & 1 deletion infra/feast-operator/api/v1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ metadata:
}
]
capabilities: Basic Install
createdAt: "2026-03-10T20:00:10Z"
createdAt: "2026-03-24T07:09:46Z"
operators.operatorframework.io/builder: operator-sdk-v1.38.0
operators.operatorframework.io/project_layout: go.kubebuilder.io/v4
name: feast-operator.v0.61.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ spec:
OidcAuthz defines the authorization settings for deployments using an Open ID Connect identity provider.
https://auth0.
properties:
secretKeyName:
description: The key within the Secret that contains the OIDC
configuration as a YAML-encoded value.
type: string
secretRef:
description: |-
LocalObjectReference contains enough information to let you locate the
Expand All @@ -76,6 +80,15 @@ spec:
type: string
type: object
x-kubernetes-map-type: atomic
tokenEnvVar:
description: The name of the environment variable that client
pods will use to read a pre-existing OIDC token.
Comment on lines +84 to +85
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you clarify which client pods we are talking about here ?

type: string
verifySSL:
description: |-
Whether to verify SSL certificates when communicating with the OIDC provider.
Defaults to true.
type: boolean
required:
- secretRef
type: object
Expand Down Expand Up @@ -3129,6 +3142,10 @@ spec:
x-kubernetes-validations:
- message: One selection required.
rule: '[has(self.local), has(self.remote)].exists_one(c, c)'
runFeastApplyOnInit:
description: Runs feast apply on pod start to populate the registry.
Defaults to true. Ignored when DisableInitContainers is true.
type: boolean
scaling:
description: Scaling configures horizontal scaling for the FeatureStore
deployment (e.g. HPA autoscaling).
Expand Down Expand Up @@ -5695,7 +5712,6 @@ spec:
type: object
required:
- feastProject
- replicas
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this change from auto-scaling commit. Does this PR need rebase ?

type: object
x-kubernetes-validations:
- message: replicas > 1 and services.scaling.autoscaling are mutually
Expand Down Expand Up @@ -5754,6 +5770,10 @@ spec:
OidcAuthz defines the authorization settings for deployments using an Open ID Connect identity provider.
https://auth0.
properties:
secretKeyName:
description: The key within the Secret that contains the
OIDC configuration as a YAML-encoded value.
type: string
secretRef:
description: |-
LocalObjectReference contains enough information to let you locate the
Expand All @@ -5768,6 +5788,15 @@ spec:
type: string
type: object
x-kubernetes-map-type: atomic
tokenEnvVar:
description: The name of the environment variable that
client pods will use to read a pre-existing OIDC token.
type: string
verifySSL:
description: |-
Whether to verify SSL certificates when communicating with the OIDC provider.
Defaults to true.
type: boolean
required:
- secretRef
type: object
Expand Down Expand Up @@ -8871,6 +8900,11 @@ spec:
- message: One selection required.
rule: '[has(self.local), has(self.remote)].exists_one(c,
c)'
runFeastApplyOnInit:
description: Runs feast apply on pod start to populate the
registry. Defaults to true. Ignored when DisableInitContainers
is true.
type: boolean
scaling:
description: Scaling configures horizontal scaling for the
FeatureStore deployment (e.g. HPA autoscaling).
Expand Down Expand Up @@ -11458,7 +11492,6 @@ spec:
type: object
required:
- feastProject
- replicas
type: object
x-kubernetes-validations:
- message: replicas > 1 and services.scaling.autoscaling are mutually
Expand Down Expand Up @@ -13920,6 +13953,10 @@ spec:
x-kubernetes-validations:
- message: One selection required.
rule: '[has(self.local), has(self.remote)].exists_one(c, c)'
runFeastApplyOnInit:
description: Runs feast apply on pod start to populate the registry.
Defaults to true. Ignored when DisableInitContainers is true.
type: boolean
securityContext:
description: PodSecurityContext holds pod-level security attributes
and common container settings.
Expand Down Expand Up @@ -18163,6 +18200,11 @@ spec:
- message: One selection required.
rule: '[has(self.local), has(self.remote)].exists_one(c,
c)'
runFeastApplyOnInit:
description: Runs feast apply on pod start to populate the
registry. Defaults to true. Ignored when DisableInitContainers
is true.
type: boolean
securityContext:
description: PodSecurityContext holds pod-level security attributes
and common container settings.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ spec:
OidcAuthz defines the authorization settings for deployments using an Open ID Connect identity provider.
https://auth0.
properties:
secretKeyName:
description: The key within the Secret that contains the OIDC
configuration as a YAML-encoded value.
type: string
secretRef:
description: |-
LocalObjectReference contains enough information to let you locate the
Expand All @@ -76,6 +80,15 @@ spec:
type: string
type: object
x-kubernetes-map-type: atomic
tokenEnvVar:
description: The name of the environment variable that client
pods will use to read a pre-existing OIDC token.
type: string
verifySSL:
description: |-
Whether to verify SSL certificates when communicating with the OIDC provider.
Defaults to true.
type: boolean
required:
- secretRef
type: object
Expand Down Expand Up @@ -5757,6 +5770,10 @@ spec:
OidcAuthz defines the authorization settings for deployments using an Open ID Connect identity provider.
https://auth0.
properties:
secretKeyName:
description: The key within the Secret that contains the
OIDC configuration as a YAML-encoded value.
type: string
secretRef:
description: |-
LocalObjectReference contains enough information to let you locate the
Expand All @@ -5771,6 +5788,15 @@ spec:
type: string
type: object
x-kubernetes-map-type: atomic
tokenEnvVar:
description: The name of the environment variable that
client pods will use to read a pre-existing OIDC token.
type: string
verifySSL:
description: |-
Whether to verify SSL certificates when communicating with the OIDC provider.
Defaults to true.
type: boolean
required:
- secretRef
type: object
Expand Down
Loading
Loading