Configuring advanced direct authentication fields
You can configure advanced direct authentication fields in the authentications.config.openshift.io custom resource definition (CRD) to enable enhanced OIDC configurations, security enforcement, and flexible token validation for standalone and hosted control plane (HCP) clusters.
Advanced direct authentication fields is a Technology Preview feature only. Technology Preview features are not supported with Red Hat production service level agreements (SLAs) and might not be functionally complete. Red Hat does not recommend using them in production. These features provide early access to upcoming product features, enabling customers to test functionality and provide feedback during the development process.
For more information about the support scope of Red Hat Technology Preview features, see Technology Preview Features Support Scope.
About advanced direct authentication fields
Advanced direct authentication fields provide flexibility and security for OIDC-based authentication in OpenShift Container Platform. You can configure advanced OIDC settings, implement custom token validation logic, and enforce security policies on usernames and groups.
The following capabilities are available:
- Custom OIDC discovery URL
Specify a custom OIDC discovery endpoint when your identity provider does not use the standard discovery URL format. Useful for complex networking setups or non-standard identity providers.
- CEL-based claim mapping
Use Common Expression Language (CEL) expressions to construct usernames and groups from JWT token claims with fallback logic. This addresses scenarios where different user types require varying claim mappings.
- Claim validation rules
Use CEL expressions to implement advanced token validation logic, such as enforcing maximum token lifetimes, validating multiple claims, or implementing custom security policies.
- User validation rules
Enforce security policies on usernames and groups extracted from tokens to prevent privilege escalation by blocking reserved system usernames and group prefixes.
These fields extend the base OIDC authentication configuration introduced in OpenShift Container Platform 4.14. You must first configure an external OIDC identity provider before using these advanced fields.
These fields require the TechPreviewNoUpgrade feature set to be enabled. They are available on standalone OpenShift Container Platform clusters and hosted control plane (HCP) environments.
These advanced authentication fields are available as a Technology Preview feature. Ensure you have a backup authentication method, such as a certificate-based kubeconfig file, before configuring these fields.
Configuring a custom OIDC discovery URL
Configure a custom OIDC discovery URL when your identity provider does not follow the standard discovery endpoint format.
Prerequisites
- You have configured an external OIDC identity provider for direct authentication.
- You have access to the cluster as a user with the
cluster-adminrole. - You have access to a long-lived authentication method, such as a certificate-based kubeconfig file.
Procedure
- Create a YAML file named
authentication-discovery-url.yamlwith your custom discovery URL configuration:yamlapiVersion: config.openshift.io/v1 kind: Authentication metadata: name: cluster spec: type: OIDC oidcProviders: - name: my-oidc-provider issuer: issuerURL: https://idp.example.com discoveryURL: https://custom-discovery.example.com/.well-known/openid-configuration audiences: - my-audience claimMappings: username: claim: emailwhere:
issuerURLSpecifies the issuer URL displayed in JWT token
issclaim.discoveryURLSpecifies the custom OIDC discovery endpoint URL. Must differ from
issuerURL, use HTTPS, and must not contain query parameters, fragments, or user info. Maximum length: 2048 characters.
NoteReplace the placeholder values (
my-oidc-provider,https://idp.example.com,https://custom-discovery.example.com/.well-known/openid-configuration,my-audience) with your actual OIDC provider configuration. - Apply the configuration:terminal
$ oc apply -f authentication-discovery-url.yaml
Verification
- Monitor the cluster authentication Operator status to ensure the configuration is applied successfully:terminal
$ oc get clusteroperator authenticationThe Operator should report
Available=TrueandDegraded=False. - Check the cluster authentication Operator logs for any errors:terminal
$ oc logs -n openshift-authentication-operator deployments/authentication-operator - Verify the kube-apiserver is using the custom discovery URL by checking the authentication configuration:terminal
$ oc get configmap kube-apiserver-to-kubelet-client-ca -n openshift-kube-apiserver -o yamlterminal$ oc get authentication.config.openshift.io/cluster -o jsonpath='{.spec.oidcProviders[0].issuer.discoveryURL}'The output should display your custom discovery URL.
Configuring CEL expressions for username and groups claim mapping
You can use Common Expression Language (CEL) expressions to construct usernames and groups from JWT token claims. This provides flexible claim mapping, including fallback logic when specific claims are not present.
Prerequisites
- You have configured an external OIDC identity provider for direct authentication.
- You have access to the cluster as a user with the
cluster-adminrole. - You have access to a long-lived authentication method, such as a certificate-based kubeconfig file.
- You are familiar with CEL expression syntax.
Procedure
- Create a YAML file named
authentication-cel-mapping.yamlwith your CEL expression configuration:ImportantWhen using
expression, do not set theclaimfield. You must use eitherclaimorexpression, but not both. Setting both will result in a validation error. Additionally, when usingexpression, do not setprefixPolicytoPrefix. Prefix policies are only compatible withclaim-based mappings.NoteWhen using the
emailclaim in CEL expressions, you must also validateemail_verifiedto ensure the email address has been verified by the identity provider.yamlapiVersion: config.openshift.io/v1 kind: Authentication metadata: name: cluster spec: type: OIDC oidcProviders: - name: my-oidc-provider issuer: issuerURL: https://idp.example.com audiences: - my-audience claimMappings: username: expression: 'claims.?upn.orValue(claims.?oid.orValue(claims.sub))' groups: expression: 'claims.?groups.orValue([])' # ...where:
username.expressionSpecifies the fallback logic for username:
upnif present, elseoid, elsesub.groups.expressionSpecifies that the
groupsclaim is used if present, else an empty array.
NoteReplace the placeholder values (
my-oidc-provider,https://idp.example.com,my-audience) with your actual OIDC provider configuration. - Apply the configuration:terminal
$ oc apply -f authentication-cel-mapping.yaml
Verification
- Verify that the authentication configuration is applied successfully:terminal
$ oc get authentication.config.openshift.io/cluster -o yaml - Authenticate with a user account and verify the username is constructed correctly:terminal
$ oc whoami - Monitor the cluster authentication Operator status:terminal
$ oc get clusteroperator authenticationThe Operator should report
Available=TrueandDegraded=False.NoteCEL expressions have access to standard CEL string functions (
lowerAscii(),upperAscii(),contains(),startsWith(),endsWith(),matches(),split()), operators (+,?,has(), ternary? :), and theorValue()method for optional chaining. See the CEL specification link in Additional resources for the complete function reference.
You can use the following CEL expression patterns for claim mapping:
- Use the optional chaining Operator
?to safely access claims that might not exist - yaml
username: expression: 'claims.email_verified ? claims.email : claims.sub'Uses
emailif verified, otherwisesub. When using theemailclaim, you must also checkemail_verified. - Concatenate multiple claims
- yaml
username: expression: 'claims.givenname + "." + claims.surname'Combines given name and surname claims.
- Transform claim values
- yaml
username: expression: 'claims.email.lowerAscii()'Converts email to lowercase.
- Conditional logic for different user types
- yaml
username: expression: 'has(claims.upn) ? claims.upn : claims.oid'Uses
upnfor regular users,oidfor service principals. - Extract domain from email
- yaml
groups: expression: 'claims.?email.orValue("").split("@").size() > 1 ? [claims.email.split("@")[1]] : []'Safely extracts domain from email address for group assignment, returning an empty array if email is missing or malformed.
- Combine group sources
- yaml
groups: expression: 'claims.?groups.orValue([]) + claims.?roles.orValue([])'Combines
groupsandrolesclaims.
Configuring claim validation rules
Use Common Expression Language (CEL) expressions to define custom validation rules for JWT token claims and enforce advanced security policies such as maximum token lifetimes.
All claim validation rules must pass for authentication to succeed. Incorrectly configured validation rules can lock all users out of the cluster. Ensure you complete the following tasks:
- Have a backup authentication method, such as a certificate-based kubeconfig file, before applying these rules
- Test validation rules in a non-production environment first
- Verify your CEL expressions are correct to avoid blocking valid users from accessing the cluster
Prerequisites
- You have configured an external OIDC identity provider for direct authentication.
- You have access to the cluster as a user with the
cluster-adminrole. - You have access to a long-lived authentication method, such as a certificate-based kubeconfig file.
- You are familiar with CEL expression syntax.
Procedure
- Create a YAML file named
authentication-claim-validation.yamlwith your claim validation rules:yamlapiVersion: config.openshift.io/v1 kind: Authentication metadata: name: cluster spec: type: OIDC oidcProviders: - name: my-oidc-provider issuer: issuerURL: https://idp.example.com audiences: - my-audience claimMappings: username: claim: email claimValidationRules: - type: CEL cel: expression: 'claims.exp - claims.nbf <= 86400' message: 'Total token lifetime must not exceed 24 hours' - type: CEL cel: expression: 'has(claims.email) && claims.email_verified && claims.email.contains("@example.com")' message: 'Email claim must be verified and from example.com domain'where:
claimValidationRulesSpecifies an array of validation rules. All must pass for authentication.
typeSpecifies the validation type. Set to
CELfor CEL-based validation.cel.expressionSpecifies the CEL expression that must evaluate to
true.cel.messageSpecifies the error message displayed when validation fails.
NoteReplace the placeholder values (
my-oidc-provider,https://idp.example.com,my-audience,@example.com) with your actual OIDC provider configuration and validation requirements. - Apply the configuration:terminal
$ oc apply -f authentication-claim-validation.yaml
Verification
- Verify that the authentication configuration is applied successfully:terminal
$ oc get authentication.config.openshift.io/cluster -o yaml - Authenticate with a token that matches your validation rules to confirm they are enforced correctly.
- Check the cluster authentication Operator logs for validation errors:terminal
$ oc logs -n openshift-authentication-operator deployments/authentication-operator
When writing CEL expressions for claim validation:
- Access claims using
claimsvariable (for example,claims.suborclaims.foo.barfor nested claims) - Expressions must evaluate to boolean values
- Use
has()to check claim existence - Standard CEL operators and functions available:
&&,||,!,contains(),startsWith(),endsWith()
Common use cases include:
- Enforce maximum token lifetime
- yaml
claimValidationRules: - type: CEL cel: expression: 'claims.exp - claims.nbf <= 86400' message: 'Token lifetime must not exceed 24 hours' - Require specific claim values
- yaml
claimValidationRules: - type: CEL cel: expression: 'claims.tenant == "production"' message: 'Only production tenant tokens are allowed' - Validate email domain
- yaml
claimValidationRules: - type: CEL cel: expression: 'has(claims.email) && claims.email_verified && claims.email.endsWith("@trusted-domain.com")' message: 'Email must be verified and from trusted-domain.com'When using the
emailclaim, you must also checkemail_verifiedto ensure the email address has been verified by the identity provider. - Combine conditions
- yaml
claimValidationRules: - type: CEL cel: expression: 'has(claims.role) && (claims.role == "admin" || claims.role == "developer")' message: 'User must have admin or developer role'
If authentication fails after the configuration is applied
- Troubleshooting
Even if your claim validation rules pass the configuration validation gates, runtime authentication errors can occur. Check the kube-apiserver logs for detailed error messages explaining why authentication failed:
terminal$ oc logs -n openshift-kube-apiserver -l app=openshift-kube-apiserver | grep -i authThese log messages will indicate which validation rule failed and include the custom
messageyou specified in the CEL expression.- If you incorrectly configure validation rules and lock users out of the cluster
- Use your certificate-based kubeconfig to authenticate as
cluster-admin. - Edit the Authentication custom resource to remove or fix invalid rules:
terminal$ oc edit authentication.config.openshift.io/cluster- Monitor the cluster authentication Operator to confirm it returns to
Availablestatus:
terminal$ oc get clusteroperator authentication- Use your certificate-based kubeconfig to authenticate as
Configuring user validation rules
You can define validation rules to enforce security policies on the user object created from an authenticated token. This helps prevent privilege escalation by blocking reserved usernames and group prefixes.
User validation rules are evaluated after claim mapping is complete, including all prefix transformations. Your CEL expressions must validate the final username and group names as they will appear in RBAC policies, not the raw claim values from the JWT token.
All user validation rules must pass for authentication to succeed. Incorrectly configured validation rules can lock all users out of the cluster. Ensure you:
- Have a backup authentication method, such as a certificate-based kubeconfig file, before applying these rules
- Test validation rules in a non-production environment first
- Verify your CEL expressions correctly validate the final username and groups to avoid blocking valid users or allowing unauthorized access
Prerequisites
- You have configured an external OIDC identity provider for direct authentication.
- You have access to the cluster as a user with the
cluster-adminrole. - You have access to a long-lived authentication method, such as a certificate-based kubeconfig file.
- You are familiar with CEL expression syntax.
Procedure
- Create a YAML file named
authentication-user-validation.yamlwith your user validation rules:yamlapiVersion: config.openshift.io/v1 kind: Authentication metadata: name: cluster spec: type: OIDC oidcProviders: - name: my-oidc-provider issuer: issuerURL: https://idp.example.com audiences: - my-audience claimMappings: username: claim: email groups: claim: groups userValidationRules: - expression: "!user.username.startsWith('system:')" message: 'Username cannot use reserved system: prefix' - expression: "!user.groups.exists(g, g.startsWith('system:'))" message: 'Groups cannot use reserved system: prefix'where:
userValidationRulesSpecifies an array of validation rules. All must pass for authentication.
expressionSpecifies the CEL expression that must evaluate to
true.messageSpecifies the error message displayed when validation fails.
NoteReplace the placeholder values (
my-oidc-provider,https://idp.example.com,my-audience) with your actual OIDC provider configuration. - Apply the configuration:terminal
$ oc apply -f authentication-user-validation.yaml
Verification
- Verify that the authentication configuration is applied successfully:terminal
$ oc get authentication.config.openshift.io/cluster -o yaml - Authenticate with credentials that would create a user matching your validation rules to confirm they are enforced correctly.
- Check the cluster authentication Operator logs for validation errors:terminal
$ oc logs -n openshift-authentication-operator deployments/authentication-operator
When writing CEL expressions for user validation:
- Access user fields:
user.username,user.groups(array),user.uid,user.extra(map) - Expressions must evaluate to boolean values
- Use
startsWith(),endsWith(),contains()for string matching - Use
exists()for array checks (for example,user.groups.exists(g, g == "admin"))
Common use cases include:
- Prevent reserved username prefixes
- yaml
userValidationRules: - expression: "!user.username.startsWith('system:')" message: 'Username cannot use reserved system: prefix' - Prevent reserved group prefixes
- yaml
userValidationRules: - expression: "!user.groups.exists(g, g.startsWith('system:'))" message: 'Groups cannot use reserved system: prefix' - Require username format
- yaml
userValidationRules: - expression: "user.username.matches('^[a-z0-9]([-a-z0-9]*[a-z0-9])?$')" message: 'Username must be a valid DNS subdomain' - Validate group membership
- yaml
userValidationRules: - expression: "user.groups.exists(g, g == 'verified-users')" message: 'User must be a member of verified-users group' - Combine conditions
- yaml
userValidationRules: - expression: "!user.username.startsWith('system:') && !user.username.startsWith('kube:')" message: 'Username cannot use reserved system: or kube: prefixes'
Troubleshooting
If you incorrectly configure validation rules and lock users out of the cluster:
- Use your certificate-based kubeconfig to authenticate as
cluster-admin. - Edit the Authentication custom resource to remove or fix invalid rules:terminal
$ oc edit authentication.config.openshift.io/cluster - Monitor the cluster authentication Operator to confirm it returns to
Availablestatus:terminal$ oc get clusteroperator authentication
Advanced authentication field reference
The following table describes the advanced authentication configuration fields available as Technology Preview in OpenShift Container Platform.
Advanced oidcProviders configuration fields
| Parameter | Description |
|---|---|
issuer.discoveryURL |
Optional parameter. Custom OIDC discovery endpoint URL for retrieving identity provider metadata from a non-standard location. Requirements:
{issuerURL}/.well-known/openid-configuration.Example: issuer: issuerURL: https://idp.example.com discoveryURL: https://custom-discovery.example.com/.well-known/openid-configuration |
claimValidationRules |
Optional parameter. Array of validation rules for JWT token claims using Common Expression Language (CEL) expressions. All rules must evaluate to true for authentication to succeed (AND operation).Each rule has:
claims variable (for example, claims.sub).Example: claimValidationRules:
- type: CEL
cel:
expression: 'claims.exp - claims.nbf <= 86400'
message: 'Total token lifetime must not exceed 24 hours'
- type: CEL
cel:
expression: 'has(claims.email) && claims.email.contains("@example.com")'
message: 'Email claim must be present and from example.com domain' |
claimValidationRules[].type |
Required. Validation rule type. Set to CEL for CEL-based validation. Requires cel field. |
claimValidationRules[].cel |
Required when type is CEL. Contains expression (CEL expression to evaluate) and message (error text). |
claimValidationRules[].cel.expression |
Required. CEL expression that validates token claims. Must evaluate to true for authentication to succeed.Constraints: 1-1024 characters, must evaluate to boolean. Access claims by using claims variable: claims.sub, claims.foo.bar (nested), has(claims.email) (existence check).
|
claimValidationRules[].cel.message |
Required. Error message displayed when validation fails. Constraints: 1-256 characters. |
userValidationRules |
Optional parameter. Array of validation rules for user objects by using CEL expressions. All rules must evaluate to true for authentication to succeed (AND operation).Each rule has expression (must evaluate to true) and message (error text).CEL expressions access user object by using user variable: user.username (string), user.groups (array), user.uid (string), user.extra (map).Example: userValidationRules:
- expression: "!user.username.startsWith('system:')"
message: 'Username cannot use reserved system: prefix'
- expression: "!user.groups.exists(g, g.startsWith('system:'))"
message: 'Groups cannot use reserved system: prefix' |
userValidationRules[].expression |
Required. CEL expression that validates the user object. Must evaluate to true for authentication to succeed.Constraints: 1-1024 characters, must evaluate to boolean. Access user fields: user.username.startsWith('system:'), user.groups.exists(g, g == "admin"), user.extra["example.com/role"]. |
userValidationRules[].message |
Required. Error message displayed when validation fails. Must not be empty. |