Users and Client Secrets in Keycloak Realm Exports

Keycloak is an open source Identity and Access Management (IAM) solution that’s easy to run in Docker using a Configuration as Code (CAC) strategy enabling a workflow where a git source control repository can be cloned by a developer who can run one non-interactive script that starts Keycloak and gets it into a consistent state ready for use. Using this approach, most developers wouldn’t even need to know anything about Keycloak; they can just focus on developing and testing against its standard interfaces (such as OAuth2). However, developers will quickly hit a bump in the road: the Keycloak export created in the UI doesn’t include users nor does it include client secrets. In other words, when that export is imported, that data is missing. Which means that each time the import runs, Keycloak generates new client secrets and there no no users, which is clearly not a reproducible, consistent, usable state for the development team. Here are some workarounds for that shortcoming.

Note that actual, production secrets and other sensitive information should never be saved in source control and shared amongst a team. Only testing secrets used for developers in their development effort should be stored in that fashion.

Keycloak administrative interface showing the export function
The produced realm export json doesn’t include secrets or users

Option A: Use Keycloak’s Export Command Line Option

One way to work around this omission of data is to use a different approach to the export. The documentation covers a way to stop Keycloak then use a command line option to generated a realm data export json file that does include users and secrets. However, that approach has a significant downside in that it requires Keycloak to be stopped and it’s harder to automate, especially when an ephemeral database (such as H2) is used.

Option B: Edit the Administrative Interface’s Realm Export Json

Another approach is to add the missing data to the realm export json. To use this approach, use the administrative interface’s export function to save the realm export json file then open in an edit.

  • To add a client secret, search for the client with the secret that should be saved (for example, search for "clientId": "my-client-app") and find the "secret": "**********" within it, and replace the stars with the client secret that should be saved.
  • To add users, for example, add the following before the final }:
,
"users": [
  {
    "username": "user",
    "enabled": true,
    "credentials": [
      {
        "type": "password",
        "value": "password"
      }
    ],
    "clientRoles": {
      "realm-management": [ "realm-admin" ],
      "account": [ "manage-account" ]
    }
  }
]

Using the Realm Export

With this realm export json that now contains secrets and users, it can be committed to source control and used by developers to create consistent, reproducible experience for the whole team. In the following example, the realm data file is named application-realm.json.

---
version: "3.8"

services:
  postgres:
    image: postgres:11
    volumes:
      - postgres_data:/var/lib/postgresql/data
    environment:
      POSTGRES_DB: application
      POSTGRES_USER: application
      POSTGRES_PASSWORD: supersecretpassword
    networks:
      - common-network
  keycloak:
    image: jboss/keycloak
    volumes:
     - type: bind
       source: ./application-realm.json
       target: /application-realm.json
       read_only: true
    ports:
      - "8180:8180"
    command:
      - "-Djboss.socket.binding.port-offset=100"
      - "-Dkeycloak.migration.action=import"
      - "-Dkeycloak.migration.provider=singleFile"
      - "-Dkeycloak.migration.strategy=OVERWRITE_EXISTING"
      - "-Dkeycloak.migration.file=/application-realm.json"
    environment:
      DB_VENDOR: POSTGRES
      DB_ADDR: postgres
      DB_DATABASE: application
      DB_USER: application
      DB_PASSWORD: supersecretpassword
      DB_SCHEMA: public
      KEYCLOAK_USER: keycloak-admin
      KEYCLOAK_PASSWORD: keycloak-password
      KEYCLOAK_HOSTNAME: localhost
      KEYCLOAK_FRONTEND_URL: http://localhost:8180/auth
    depends_on:
      - postgres
    networks:
      - common-network
networks:
  common-network:
    driver: bridge
volumes:
  postgres_data:
    driver: local

Note that keycloak.migration.* properties are used instead of jboss/keycloak’s KEYCLOAK_IMPORT environment variable. KEYCLOAK_IMPORT will not overwite existing realm data and has no option that can do so. keycloak.migration.* can overwrite existing realm data. Overwriting existing realm data is important because it makes the Keycloak state reproducible – anyone who runs this docker-compose configuration will end up with Keycloak in the same state as anyone else.

CC BY-SA 4.0 Users and Client Secrets in Keycloak Realm Exports by Craig Andrews is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.