Skip to content

adaltas/oidc-dcr

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Keycloak DCR registration

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.

Architecture

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.

Roadmap

  • Validate/enrich the configuration
  • Addtionnal example
  • values.yaml JSON 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

Configuration

  • image
    The Alpine-based Docker image used to run the registration script. It must include curl and jq. (Default: alpine:latest)

  • mapping

    • use_default
      Controls the key generation for the output object. If set to true, all alias keys defined in the default_keys section will be injected into the secret (default option). If false, only custom keys defined manually will be included. It is possible to set custom keys while keeping the default ones by setting use_default to true. 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 as jq filters 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. 0 disables 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 the request section. 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 are native or web. (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 include client_secret_basic, client_secret_post, client_secret_jwt, private_key_jwt, and none. 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>)

Data Mapping

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
    • .scope List 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.

Keycloak Notes

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.

Headlamp Example

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/headlamp

The 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>"
}

About

Automatic client's registration with OIDC providers supporting DCR

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors