OIDC Management

ACP can redirect users to a standards-based OIDC identity provider and create or update their platform identity after successful login.

Use the Form tab for the shortest initial integration. Use the YAML tab when the returned username Claim must be selected explicitly, Claims must be remapped, UserInfo must be queried, or OIDC groups and extra fields are required. See Add OIDC Using YAML.

Before You Begin

Prepare these values:

  • Issuer URL, labeled in ACP as Server Provider URL.
  • Client ID.
  • Client Secret, labeled in ACP as Client Key.
  • One representative test account with an email address that is not already used by an ACP local user or another IDP.
  • A stable username Claim returned for that test account. The tested YAML fallback uses preferred_username.

Register this exact callback with the upstream identity provider:

https://<ACP_ADDRESS>/dex/callback

ACP derives the callback from the platform address. The form does not contain a Redirect URI field.

Server Provider URL must be the Issuer root, not an authorization endpoint, token endpoint, or login page. Its discovery document is normally available at this path:

<ISSUER_URL>/.well-known/openid-configuration

You can inspect discovery from a diagnostic host with ACP-equivalent reachability:

curl -fsS 'https://idp.example.com/.well-known/openid-configuration'

For an upstream service that uses a private CA, independently verify the certificate chain with that CA:

curl -fsS --cacert /path/to/oidc-ca.pem \
  'https://idp.example.com/.well-known/openid-configuration'

This external query is preliminary evidence. ACP Connector creation is the cluster-side discovery and reachability check.

Confirm the Returned Claims

Ask the upstream identity administrator to provide the ID token or UserInfo Claim names for one representative account. Claim names are case-sensitive. ACP Connector creation validates discovery and client reachability, but it does not prove that a real user's token contains the required Claims.

Claim or settingRequired whenACP use
subAlwaysStable upstream subject used by the OIDC protocol. It must be a string.
nameNo userNameKey is configuredDefault source for the ACP username.
Claim selected by userNameKeyThe default name Claim is absent or unsuitableSource for the ACP username. The validated fallback is preferred_username.
email or the Claim selected by claimMapping.emailThe email scope is requestedACP user identity. It must be a string and should not collide with an existing ACP user.
email_verifiedThe email scope is requestedBoolean verification flag required by the current login flow.
Claim selected by claimMapping.groupsOIDC group processing is enabledString or array of group names used to create and associate ACP groups.
Claims selected by claimMapping.phone and claimMapping.mailThose optional profile fields are configuredString values copied to the ACP user's mobile and mail fields.
Claim listed in claimExtraThe extra value must be stored in ACPValue copied to spec.extra when its configured type matches. This guide documents the validated string type.

Complete one real browser login before rollout and inspect the generated ACP user. That login is the authoritative check for Claim availability, mapping, collision behavior, and group restrictions.

Upstream OIDC certificate verification limitation

In this ACP release, Connector validation and the OIDC login runtime use insecureSkipVerify: true. ACP therefore does not verify the upstream OIDC server certificate. HTTPS still encrypts the connection, but successful Connector creation is not evidence that the certificate chain is trusted.

If the customer's security policy requires upstream server certificate verification, this release does not meet that requirement. Resolve the product-version or security-policy requirement before rollout.

Add OIDC Using the Form

  1. Go to Users > IDP.
  2. Click Add OIDC.
  3. Complete Basic Info: Name, Display Name, and optional Description.
  4. Complete Server Setting: Server Provider URL, Client ID, and Client Key.
  5. Leave Logout URL empty for this integration workflow.
  6. Click Add.

During creation, ACP reads OIDC discovery from the Issuer URL. An invalid or unreachable Issuer is rejected at this stage. The current creation check does not prove that Client Key is correct or that the upstream TLS certificate is trusted: a Connector with an incorrect key can still be created and then fail during the browser callback, while an untrusted self-signed certificate can be accepted. A real login is therefore required for authentication, and certificate compliance must be assessed separately as described above.

After creation, ACP moves the submitted Client Key to a managed Secret. The stored Connector references that Secret instead of retaining clientSecret in its configuration.

Console Field Reference

ACP console fieldYAML fieldProduct behavior
Nameid and metadata.nameUse the same DNS-compatible value for both fields.
Display NamenameName shown on the ACP IDP chooser.
Descriptionmetadata.annotations["cpaas.io/description"]Optional operator-facing description.
Server Provider URLspec.config.issuerIssuer root used for OIDC discovery.
Client IDspec.config.clientIDClient identifier registered upstream.
Client Keyspec.config.clientSecretInitial-creation input; ACP stores it in a managed Secret.
Logout URLlogoutUrlLeave empty. The validated runtime did not use it as the post-logout redirect.

The form does not expose redirectURI, scopes, UserInfo, Claim mappings, group processing, or extra Claims. Configure those fields through YAML only after confirming the upstream response.

Verify the Integration

  1. Start a separate browser session without an ACP login state.
  2. Open ACP and select the configured OIDC Display Name.
  3. Complete authentication at the upstream identity provider.
  4. Confirm that the browser returns to ACP instead of an HTTP 500 error.
  5. In Users, find the generated user and verify its IDP source, email, username, and active state.
  6. If the username is empty because the upstream response does not contain the default name Claim, recreate or update the Connector with the YAML example below and repeat the login.
  7. Assign a minimal role with Manage User Roles.
  8. Log in again and confirm that the assigned ACP permission is available.
Email identity collisions

In this release, logging in through another OIDC Connector with the same mapped email updates and reassociates the existing ACP user with the newer Connector. It does not create a second user or reject the collision. Use a dedicated, non-colliding account for acceptance testing, and check existing ACP users before rollout.

Connector creation, upstream authentication, ACP user creation, and ACP authorization are separate checkpoints. Verify each checkpoint independently.

Add OIDC Using YAML

Use Users > IDP > Add OIDC > YAML when the upstream response requires explicit Claim selection or advanced mapping. The complete example below assumes that the upstream response contains sub, preferred_username, email, email_verified, groups, and phone_number, and that the test user belongs to acp-users. Remove optional mappings and group restrictions that the real upstream response does not satisfy.

apiVersion: dex.coreos.com/v1
kind: Connector
id: corporate-oidc
name: Corporate OIDC
type: oidc
metadata:
  name: corporate-oidc
  namespace: cpaas-system
  annotations:
    cpaas.io/description: Corporate OIDC
    # cpaas.io/idp.validation: "false"
  labels:
    cpaas.io/idp.version: v2
spec:
  config:
    issuer: https://idp.example.com
    clientID: <CLIENT_ID>
    clientSecret: <CLIENT_SECRET>
    redirectURI: https://acp.example.com/dex/callback
    scopes:
      - profile
      - email
    getUserInfo: true
    userNameKey: preferred_username
    overrideClaimMapping: true
    claimMapping:
      preferred_username: preferred_username
      email: email
      groups: groups
      phone: phone_number
      mail: email
    claimExtra:
      - field: preferred_username
        type: string
    insecureEnableGroups: true
    allowedGroups:
      - acp-users

Replace the Issuer, credentials, ACP address, Claim names, and allowed group before submission. If the provider does not expose a UserInfo endpoint or all required Claims are already in the ID token, set getUserInfo: false. If group processing is not required, remove insecureEnableGroups, allowedGroups, and claimMapping.groups.

Do not add openid to scopes; the Connector adds it to the authorization request. If the upstream provider requires a provider-specific scope for group Claims, add that scope only after confirming it in the discovery and provider configuration.

Submit this initial configuration through the ACP console YAML tab. ACP moves clientSecret to a managed Secret, and the stored Connector contains clientSecretRef instead. Do not use kubectl apply with an inline clientSecret: the Kubernetes last-applied annotation can retain the submitted secret in the Connector metadata.

Complete OIDC Field Reference

Top-level and metadata fields:

FieldRequiredProduct behavior
apiVersionYesUse dex.coreos.com/v1.
kindYesUse Connector.
idYesConnector identity. Keep it equal to metadata.name.
nameYesDisplay name shown on the ACP login chooser.
typeYesUse oidc.
metadata.nameYesKubernetes resource name and ACP Connector lookup key.
metadata.namespaceYesUse cpaas-system.
metadata.annotations["cpaas.io/description"]NoDescription shown by ACP.
metadata.annotations["cpaas.io/idp.validation"]Temporary troubleshooting onlyString value "false" skips upstream connectivity validation for this creation or spec-changing update; format validation still runs. Do not set it to "true".
metadata.labels["cpaas.io/idp.version"]RecommendedUse v2; current ACP also adds this label during creation.

Connection and login fields:

FieldRequiredProduct behavior
issuerYesIssuer root used to retrieve /.well-known/openid-configuration.
clientIDYesClient identifier registered upstream.
clientSecretInitial creationPlain input accepted by the ACP YAML page. ACP removes it and stores it in a managed Secret.
clientSecretRefStored outputManaged Secret reference written by ACP. Do not submit it together with clientSecret or edit it manually.
redirectURIYesExact ACP callback registered upstream: https://<ACP_ADDRESS>/dex/callback.
scopesNoAdditional scopes such as profile and email. ACP automatically adds openid.
getUserInfoNoWhen true, requests the UserInfo endpoint and merges returned Claims before mapping. Verify that the provider supports this endpoint.
userNameKeyNoClaim used as the ACP username instead of the default name; preferred_username is the validated fallback.

Claim and group fields:

FieldRequiredProduct behavior
overrideClaimMappingWhen forcing a custom mappingSet to true when a standard Claim is also present but ACP must use the Claim selected below.
claimMapping.preferred_usernameNoClaim used as the preferred username.
claimMapping.emailWhen remapping emailClaim used as the ACP primary identity. Check for collisions before rollout.
claimMapping.groupsWhen group processing is enabledClaim containing a string or array of group names. This nested field is the runtime group mapping.
claimMapping.phoneNoString Claim copied to the ACP user's mobile field.
claimMapping.mailNoString Claim copied to the ACP user's mail field.
claimExtra[].fieldNoClaim copied to the ACP user's spec.extra map.
claimExtra[].typeWith claimExtra[].fieldUse string for the validated workflow in this guide. Remove the entry when the Claim is absent or has another type.
insecureEnableGroupsWhen group processing is requiredSet to true to read the mapped group Claim and create or associate ACP groups during login.
allowedGroupsNoWhen non-empty, login is rejected unless at least one mapped group matches. ACP retains only the matching allowed groups.

If email is present in scopes, the selected email Claim must be a string and email_verified must be a Boolean in the merged response. Missing either value causes login to fail.

Temporary validation bypass

Use cpaas.io/idp.validation: "false" only when the Connector must be staged while the upstream service is temporarily unreachable. ACP still checks the configuration structure, but it skips discovery and upstream connectivity checks. The resulting Connector can therefore exist even though browser login cannot work.

The admission webhook removes this annotation from the stored Connector and copies the skip marker to the managed credential Secret. A later spec-changing Connector update without the annotation runs normal Connector validation. To restore validation for future Client Key changes, update the credential through the Connector without the annotation; do not edit the managed Secret directly. Do not use cpaas.io/idp.validation: "true"; omit the annotation for normal validation.

Before rollout, complete a normally validated creation or real corrective update, then perform a real browser login and inspect the generated ACP user. A metadata-only update is not evidence that normal validation ran.

ACP-managed and ineffective fields

Stored YAML can contain controller-added defaults such as issuerAlias: "", top-level groupsKey: groups, and insecureSkipVerify: true.

  • Configure group mapping with claimMapping.groups. The current runtime does not use the controller-added top-level groupsKey as the group Claim selector.
  • Do not use insecureSkipVerify: false as a certificate-trust control. The validated runtime does not verify the upstream certificate, as described in Before You Begin.
  • Leave issuerAlias out of the validated workflow unless a product-specific integration procedure explicitly requires it.

Login, Update, and Delete Behavior

  • OIDC users are created or updated after a successful browser login. OIDC does not provide LDAP-style manual or scheduled user synchronization.
  • After updating the username mapping, start a new browser session and log in again to verify the updated user.
  • Deleting the Connector through ACP without cleanup retains source users and marks them invalid.
  • Selecting Clean up IDP users and User Groups deletes the generated source users and the managed Secret with the Connector.

Use the ACP console action or ACP product API for deletion. Deleting the underlying Connector custom resource directly with kubectl bypasses the ACP user-invalidation and cleanup behavior.

Logout Behavior

In this release, ACP logout ends the ACP session and returns the browser to the ACP IDP chooser. Selecting the same OIDC entry again can reuse the still-active upstream session and sign the user in without another credential prompt. ACP logout therefore does not prove that the upstream session has ended.

The flow does not use the configured Logout URL as a browser redirect. Leave this field empty and validate upstream session termination separately when the customer's security requirements require it.

Troubleshoot by Stage

SymptomProven stageNext check
ACP rejects the Connector during creation.Discovery or cluster-side reachability did not complete.Confirm that Server Provider URL is the Issuer root, retrieve its discovery document from an ACP-equivalent network path, and retry creation.
Connector creation succeeds, but the callback returns HTTP 500 with unauthorized_client or Invalid client secret.Discovery and the upstream authorization page worked; client authentication at the token endpoint failed.Correct Client Key, then repeat the full login in a new browser session. Creation alone does not validate this value.
Login succeeds, but the ACP username is empty.ACP accepted the upstream identity and created the user.Confirm that preferred_username is present, set userNameKey: preferred_username through YAML, and log in again.
Login fails with a missing email or email_verified message.Authorization and token exchange completed, but required Claims were absent or had the wrong type.Inspect the ID token and UserInfo response, correct scopes or claimMapping.email, and repeat login.
Login fails with user not a member of allowed groups.The mapped group Claim was read, but no value matched allowedGroups.Confirm the exact case-sensitive group values, then correct the upstream membership, claimMapping.groups, or allowedGroups.
Login succeeds, but no ACP groups are associated.Authentication and user mapping completed without a usable group result.Confirm that insecureEnableGroups: true, inspect the mapped group Claim type and values, and verify claimMapping.groups.
A configured extra Claim is absent from the ACP user.Login completed, but the Claim was missing or did not match the configured type.Inspect the merged ID token and UserInfo Claims; for this guide, use type: string only for a string Claim.
An existing user's IDP source or mapping changes after the test login.The callback mapped an email already used by an ACP user.Stop the rollout, choose a non-colliding test account, and review existing ACP users before retrying.
ACP logout returns to the IDP chooser, but choosing OIDC signs in without another prompt.The ACP session ended, while the upstream session remained active.Treat ACP and upstream logout as separate acceptance checks; do not rely on the unverified Logout URL field.
Users remain active after the Connector custom resource is deleted with kubectl.The ACP product deletion workflow was bypassed.Restore the test Connector if needed, then delete it with the ACP console action and select the required cleanup option.

For callback and user-mapping evidence, inspect the current ACP login component logs:

kubectl -n cpaas-system logs deployment/apollo --since=10m