# Configure OIDC federation in Keycloak

Use this page to configure an external OpenID Connect identity provider in the Keycloak Metaco realm.

## Before you begin

Prepare the following values from your identity provider:

| Value | Notes |
|  --- | --- |
| Discovery endpoint | URL ending in `.well-known/openid-configuration`. Keycloak must be able to reach it. |
| Client ID | Static client ID reserved for Custody federation. |
| Client secret | Secret for the client ID. Store and rotate it through your standard secret-management process. |
| Redirect URI | Keycloak broker endpoint for the provider alias. Register it with the upstream IdP. |
| Claim choice | Claim used to identify users, such as `sub`, `email`, or another stable claim emitted by the IdP. |
| Required claim | Optional claim that proves the user is assigned to the Custody application in the upstream IdP. |
| Provider alias | Unique lower-case alias. This must match the Custody `loginIds.providerId` value. |


## Configure the identity provider

1. Log in to the Keycloak Admin Console.
2. Select the **Metaco** realm.
3. Go to **Identity providers**.
4. Create a new **OpenID Connect** provider.
5. Enter the provider alias, discovery endpoint, client ID, and client secret.
6. Disable user info if the required claims are already present in the ID token.
7. In advanced settings, set scopes to request the claims your mappers require, for example `openid email profile`.
8. Set **First login flow** to **Harmonize Flow**.
9. If your identity provider requires a mandatory claim for Custody access, configure an essential-claim check.
10. Save the provider.


The provider alias is not just a display name. It is the value Custody uses as the `providerId` in user `loginIds`.

Keep the client secret configured in Keycloak synchronized with the secret configured in the upstream identity provider. If you rotate one side, update and verify the other side during the same change window.

## Configure provider mappers

Create the mappers required for stable user linking and downstream token behavior.

| Mapper | Purpose |
|  --- | --- |
| `BROKER_ID Username Template Importer` | Sets the federated identity lookup key for repeat logins. |
| `BROKER_USERNAME Username Template Importer` | Sets the broker username used for display and downstream mapping. |
| `Username with provider alias` | Prefixes the local Keycloak username with the provider alias to avoid collisions. |
| `Hardcoded user session attribute` | Stores the identity provider alias in the Keycloak user session. |


### BROKER_ID Username Template Importer

| Field | Value |
|  --- | --- |
| Name | `BROKER_ID Username Template Importer` |
| Mapper Type | `Username Template Importer` |
| Sync Mode | `Inherit` |
| Template | `${ALIAS}:${CLAIM.<claim-name>}` |
| Target | `BROKER_ID` |


### BROKER_USERNAME Username Template Importer

| Field | Value |
|  --- | --- |
| Name | `BROKER_USERNAME Username Template Importer` |
| Mapper Type | `Username Template Importer` |
| Sync Mode | `Inherit` |
| Template | `${ALIAS}:${CLAIM.<claim-name>}` |
| Target | `BROKER_USERNAME` |


### Username with provider alias

| Field | Value |
|  --- | --- |
| Name | `Username with provider alias` |
| Mapper Type | `Append provider alias to username` |
| Sync Mode | `Force` |


### Hardcoded user session attribute

| Field | Value |
|  --- | --- |
| Name | `Hardcoded user session attribute` |
| Mapper Type | `Hardcoded User Session Attribute` |
| Attribute | `identity_provider_alias` |
| Attribute Value | Your provider alias |
| Sync Mode | `Force` |


Use `:` as the separator in username template values, for example `${ALIAS}:${CLAIM.email}`. Do not use `.` as the separator.

## Map Custody users to the provider

Each federated user must have a Custody `loginIds` entry for the provider alias and identifier emitted by the mapper.


```json
{
  "loginIds": [
    {
      "id": "user@example.com",
      "providerId": "corporate-oidc"
    }
  ]
}
```

Update users through the governed user-management flow. For procedures, see [Manage users and roles](/products/custody/governance/users/manage-users-and-roles).

## Verify the integration

Before enabling the provider for a wider user group:

1. Confirm Keycloak can reach the discovery document and JWKS endpoint.
2. Confirm the upstream IdP returns the claims required by the mapper templates.
3. Confirm any required or essential claim is present only for users assigned to the Custody application.
4. Confirm a test user can sign in through Keycloak.
5. Confirm repeat login reuses the same user instead of creating a duplicate identity.
6. Confirm the Keycloak-issued token contains the expected subject and audience values.
7. Confirm Ripple Custody maps the token to the expected user, domain, and roles.
8. Confirm session and logout behavior matches your requirements.


For common failure modes, see [Troubleshoot SSO](/products/custody/identity-and-access/sso/troubleshooting).