The oidc-dcr chart provides automatic client's registration with OIDC providers supporting the OpenID Connect Dynamic Client Registration (DCR) protocol (such as Keycloak). It is used to automate the registration of applications that need OIDC authentication without any manual intervention and elevated privileges.
The chart creates a Kubernetes Job that executes a bash script to perform the dynamic client registration. The script sends a JSON payload to the specified HTTP DCR registration endpoint and processes the response to extract relevant information (like client ID and secret). This information is then stored in a Kubernetes Secret for use by other applications.
- Validate/enrich the configuration
- Addtionnal example
values.yamlJSON schema- Respect Helm documentation best-practices
- Helm test best practices
- Fix error "Resource not found in cluster" in Argo CD
- Externalise the script to an external file
- Any other Helm best practices
-
image
The Alpine-based Docker image used to run the registration script. It must includecurlandjq. (Default:alpine:latest) -
mappinguse_default
Controls the key generation for the output object. If set totrue, all alias keys defined in thedefault_keyssection will be injected into the secret (default option). Iffalse, only custom keys defined manually will be included. It is possible to set custom keys while keeping the default ones by settinguse_defaulttotrue. In this case, the custom keys will overwrite the default ones if they share the same name.key_mapping
Defines custom mappings between the DCR response fields and the keys in the Kubernetes Secret. The keys represent the desired field names in the output secret, while the values specify how to extract or define the corresponding values from the DCR response. Values starting with a dot (.) are Dynamic Fields. They are interpreted asjqfilters applied directly to the DCR JSON response (e.g.,.client_id==>jq | .client_id). Values without a leading dot are Static Fields and are written directly as hard-coded strings.default_keys
A pre-defined set of common mappings in different naming conventions to provide a "ready to use" configuration for the most common use cases.
-
registration_url
The OIDC provider registration URL used to process the dynamic registration. -
ttl_seconds
Time-to-live duration (in seconds) to preserve the Kubernetes Job logs after execution for debugging purposes.0disables automatic deletion or relies on cluster-level defaults. (Default:60) -
request
The JSON payload sent to the OIDC identity provider during registration is defined under therequestsection. It supports all the standard fields defined in the OpenID Connect Dynamic Client Registration specification, as well as some Keycloak-specific extensions. The most common fields are:application_type
Kind of the application. Supported values arenativeorweb. (Default:"web")client_name
The display name of the OIDC client shown on login and consent screens. (Default:"")logo_uri
URL pointing to the logo of the client application. (Default:"")grant_types
OAuth 2.0 grant types that the client restricts itself to using. (Default:["authorization_code", "client_credentials"])redirect_uris
List of allowed callback URLs where the identity provider can redirect users after authentication. (Default:[])response_types
List of expected OAuth 2.0 response type values (e.g.,code). (Default:[])client_uri
URL of the home page of the client application. (Default:"")token_endpoint_auth_method
Authentication method used by the client at the token endpoint. Supported values includeclient_secret_basic,client_secret_post,client_secret_jwt,private_key_jwt, andnone. Using none creates a public client (client without secret) (Default:client_secret_basic)
-
secret
Control the name for the created Kubernetes Secret. If left empty, the Helm chart name is used. -
security
Names of the Kubernetes ServiceAccount and RBAC role used to execute the Job and grant it permissions to create the Secret.security.service_account
Name of the Kubernetes ServiceAccount used to execute the job. (Default:<Chart name>)security.role
Name of the RBAC role associated with the ServiceAccount to grant Secret creation permissions. (Default:<Chart name>)
The mapping section defines how the response from the OIDC provider is transformed into the data stored in the Kubernetes Secret. It provides a flexible mechanism to map response fields of the DCR request into the output Kubernetes secret.
The available fields in the DCR response are the following:
- IDENTIFIERS & SECRETS
.client_id: Unique generated identifier (UUID). Required for OIDC_CLIENT_ID..client_secret: The client's password. Required for OIDC_CLIENT_SECRET..client_id_issued_at: Unix timestamp of when the client was created..client_secret_expires_at: 0 means the secret never expires. Note, the client secret rotation is currently not supported by Keycloak.
- DYNAMIC MANAGEMENT
.registration_client_uri: Unique URL to read or modify this specific client..registration_access_token: Security token required to access the registration_client_uri.
On top of those standard fields, the DCR response also includes keykloak-specific fields that can be mapped for more advanced use cases:
- FLOW CONFIGURATION
.redirect_uris
List of allowed callback URLs after authentication..post_logout_redirect_uris
List of allowed URLs to redirect to after logging out..grant_types: List of Authorized OAuth2 flows (e.g., authorization_code, client_credentials)..response_types
List of expected response type (e.g., code)..token_endpoint_auth_method
Auth method for the token endpoint (client_secret_basic).
- SCOPES & IDENTITY
.scopeList of granted permissions (e.g., openid, offline_access, microprofile-jwt)..subject_type"public" (same user ID across all clients) or "pairwise"..client_name
The display name shown on the login/consent screen.
- ADVANCED SECURITY
.tls_client_certificate_bound_access_tokens
Token binding to TLS certificates (mTLS)..dpop_bound_access_tokens
Use of DPoP to bind tokens to the client..backchannel_logout_session_required
Whether Keycloak sends logout notifications in the background..frontchannel_logout_session_required
Whether logout notifications are sent via the browser..require_pushed_authorization_requests
Whether PAR (RFC 9126) is mandatory..request_uris
Pre-registered list of URLs for Request Objects.
Note
registration_client_uri and registration_access_token fields are mapped even if use_default is set to false to allow the script to automatically detect the registration of the client in case the job is restarted.
Some DCR fields are not supported by Keybase (e.g., contacts). Those fields can still be included in the request section but will be ignored by Keycloak and won't be present in the response.
The umbrella chart Chart.yaml declares keycloack and the OIDC DCR dependencies.
apiVersion: v2
name: headlamp
version: 1.0.0
dependencies:
- name: oidc-dcr
version: 0.1.0
repository: file://../oidc-dcr
- name: headlamp
version: 0.30.1
repository: https://kubernetes-sigs.github.io/headlampThe values for a Headlamp deployment with Keycloak as OIDC provider is defined.
headlamp:
#...
config:
oidc:
secret:
create: false
name: dcr
externalSecret:
enabled: true
name: dcr
#...
oidc-dcr:
registration_url: http://keycloak-http.keycloak.svc:80/auth/realms/adaltas/clients-registrations/openid-connect/
request:
application_type: native
client_name: Headlamp
redirect_uris:
- "https://headlamp.admin.k8s.demo/oidc-callback"
- "http://localhost:18080/*"
secret: headlamp-secret
mapping:
use_default: false
key_mapping:
OIDC_CLIENT_ID: ".client_id"
OIDC_CLIENT_SECRET: ".client_secret"
OIDC_ISSUER_URL: "https://keycloak.admin.k8s.demo/auth/realms/adaltas"
OIDC_SCOPES: "openid email profile"The corresponding Kubernetes Secret is created by the Job.
{
"apiVersion": "v1",
"data": {
"OIDC_CLIENT_ID": "<base64-encoded clientId>",
"OIDC_CLIENT_SECRET": "<base64-encoded clientSecret>",
"OIDC_ISSUER_URL": "<base64-encoded issuer URL>",
"OIDC_SCOPES": "<base64-encoded scopes>",
"registration_access_token": "<base64-encoded registration access token>",
"registration_client_uri": "<base64-encoded registration client URI>"
},
"kind": "Secret",
"metadata": {
"creationTimestamp": "<timestamp>",
"name": "headlamp-secret",
"namespace": "headlamp",
"resourceVersion": "<resource version>",
"uid": "<UUID>"
},
"type": "Opaque"
}The clear text data is then retrieved using kubectl get secrets -n <namespace> <secret-name> -o json | jq '.data | map_values(@base64d)':
{
"OIDC_CLIENT_ID": "<clientId>",
"OIDC_CLIENT_SECRET": "<clientSecret>",
"OIDC_ISSUER_URL": "http://keycloak-http.keycloak.svc:80/auth/realms/adaltas",
"OIDC_SCOPES": "openid email profile",
"registration_access_token": "<registration access token>",
"registration_client_uri": "http://keycloak-http.keycloak.svc/auth/realms/adaltas/clients-registrations/openid-connect/<clientId>"
}