Managing custom realm keys in Keycloak programmatically

August 19, 2022 – Samuli Seppänen

Keycloak's authentication protocols make use of private and public keys for signing and encrypting, as described in the official documentation. These keys are realm-specific, and by default managed internally in Keycloak. So, when you create a realm using the Keycloak Admin API, kcadm.sh or manually using the Web UI, new keypair(s) get generated automatically. These are called "Managed keys". The currently used key is selected based on the priority of all active keys. So, in this context active does not automatically mean that the keypair is being used, only that it is has not been explicitly made passive.

While managed keys are convenient, you may want to add your own custom keypairs instead. The official documentation on how to do this via kcadm and/or the API is missing, so this blog post aims to fill that void. Here we use kcadm.sh, but the process is very similar for raw API calls.

The first step is to create a keypair (borrowed from here):

$ openssl genpkey -algorithm RSA -out private_key.pem -pkeyopt rsa_keygen_bits:2048
$ openssl rsa -pubout -in private_key.pem -out public_key.pem

The next step is to create a JSON payload, which should look like this:

{
  "name" : "rsa-shared",
  "providerId" : "rsa",
  "providerType" : "org.keycloak.keys.KeyProvider",
  "parentId" : "Test",
  "config" : {
    "publicKey" : ["-----BEGIN PUBLIC KEY-----\n<public-key-body>\n-----END PUBLIC KEY-----"],
    "privateKey": ["-----BEGIN PRIVATE KEY-----\n<private-key-body>\n-----END PRIVATE KEY-----"],
    "certificate" : [],
    "active" : [ "true" ],
    "priority" : [ "123" ],
    "enabled" : [ "true" ],
    "algorithm" : [ "RS256" ]
  }
}

A couple of notes regarding the payload:

  • The name field is the human-readable name of the key
  • The parentId should match the "id" property of the realm the keypair should belong to, which is essentially the realm name.
  • The priority field determines which key Keycloak actually uses at any given time
  • The private and public keys should be added as-is, except that you must replace the linefeeds with \n.

To apply the payload use

$ /opt/keycloak/bin/kcadm.sh create components -r test -f payload-add-key.json --no-config --server http://localhost:8080/auth --realm master --user admin --password changeme

Internally Keycloak handles realm keypairs as "components" and stores them the COMPONENT_CONFIGS table in the database. That's why you won't see any "keypair" or "key" methods in the REST API, nor be able to find the keypairs as properties of the realm. While kcadm.sh does have a "get keys" method, keys can only be added, deleted or modifies as components.

If you need to get rid of you custom keypair in Keycloak, first list all keypairs:

/opt/keycloak/bin/kcadm.sh get keys -r test --no-config --server http://localhost:8080/auth --realm master --user admin --password changeme

Figure out the providerId of the keypair you want to remove, then remove it, replacing <provider-id> with the correct one:

/opt/keycloak/bin/kcadm.sh delete components/<provider-id> -r test --no-config --server http://localhost:8080/auth --realm master --user admin --password changeme

It should be noted that the same keypair can be imported to multiple realms, if that should be necessary.

Want to talk to an expert?

If you want to reach us, just send us a message or book a free call!
menucross-circle