-
Bug
-
Resolution: Done
-
Undefined
-
None
-
False
-
-
False
-
-
Before reporting an issue
[x] I have read and understood the above terms for submitting issues, and I understand that my issue may be closed without action if I do not follow them.
Area
core
Describe the bug
For us the problem occured on 26.0.12 but I could reproduce it with 26.3.3 as well.
We had an old 32 bit hmac-generated key hanging around, which was still used for signing refresh tokens.
After generating a new rsa key (totally unrelated to the hmac) and changing the order of the keys in the ui, the old 32bit hmac was recreated with a new kid, algorithm, size and priority. The old one was gone.
This was a very unfortunate event, bc we did not notice it and it took us a while to figure out what was happening.
In the meanwhile all users with a "old" refresh token got a "invalid refresh token" error when performing a token refresh, which led to a lot of users beeing logged out (at least in our frontend app implementation)
Version
26.3.3
Regression
[ ] The issue is a regression
Expected behavior
When changing the order of the keys in the ui, old hmac-generated 32bit keys are not re-created.
Actual behavior
When changing the order of the keys in the ui, old hmac-generated 32bit keys are re-created.
How to Reproduce?
1. Start Keycloak
2. Create a test realm
3. Run following script to insert old hmac-generated 32bit key: (values from a test environment)
INSERT INTO component(id, name, parent_id, provider_id, provider_type, realm_id, sub_type) VALUES (
'da946d6f-c989-4e57-a642-782b734bfdc6',
'hmac-generated',
(select id from realm where name='test'),
'hmac-generated',
'org.keycloak.keys.KeyProvider',
(select id from realm where name='test'),
null);
INSERT INTO component_config(id, component_id, name, value) VALUES ('9e8f4ad8-81f3-40ef-9392-82ef423f7270', 'da946d6f-c989-4e57-a642-782b734bfdc6', 'priority', '100'); INSERT INTO component_config(id, component_id, name, value) VALUES ('1eeba382-06f5-4912-8926-107eee6d8a88', 'da946d6f-c989-4e57-a642-782b734bfdc6', 'secret', 'Vm4tTcOyVQdoXZAXSDf9EoIsVk5BhF0bMw56ogpO6e0'); INSERT INTO component_config(id, component_id, name, value) VALUES ('6ad0954d-5760-4c5e-a61e-f2cb07533860', 'da946d6f-c989-4e57-a642-782b734bfdc6', 'kid', '6ccd546a-968e-44fa-adff-3df342c059bb');
4. Go to master realm. Clear realm cache and keys cache
5. Go to test realm
6. Go to keys tab.
7. Change the order of the keys under Tab "Add providers" (drag&drop)
8. Notice that the kid of the hmac-generated key changed.
Dockerfile:
FROM quay.io/keycloak/keycloak ENV KC_DB=postgres RUN /opt/keycloak/bin/kc.sh build \ --http-relative-path /auth \ --health-enabled=true \ --metrics-enabled=true \ --features scripts ENTRYPOINT [ "/opt/keycloak/bin/kc.sh", "--debug", "start", "--http-enabled=true", "--hostname-strict=false"]
docker-compose.yaml:
version: '3.8'
services:
keycloak_local:
build:
context: .
dockerfile: ./Dockerfile
environment:
- KC_BOOTSTRAP_ADMIN_USERNAME=admin
- KC_BOOTSTRAP_ADMIN_PASSWORD=admin
- KC_DB=postgres
- KC_DB_URL_HOST=postgres_keycloak_local
- KC_DB_URL_DATABASE=keycloak
- KC_DB_PASSWORD=password
- KC_DB_USERNAME=keycloak
- KC_DB_SCHEMA=public
- KC_HTTP_RELATIVE_PATH=/auth
- KC_METRICS_ENABLED=true
- DEBUG_PORT='*:8787'
ports: - 8080:8080
- 9000:9000
- 8787:8787
- 9000:9000
depends_on:
postgres_keycloak_local:
condition: service_healthypostgres_keycloak_local:
image: postgres:16.2
command: - postgres
volumes: - ./keycloak_local/postgres:/var/lib/postgresql/data
environment: - POSTGERS_DB=keycloak
- POSTGRES_USER=keycloak
- POSTGRES_PASSWORD=password
healthcheck:
test: [ "CMD-SHELL", "pg_isready -U keycloak -d keycloak" ]
interval: 10s
timeout: 10s
retries: 5
ports: - 5432:5432
Anything else?
Looking in the code there a several things i would like to highlight:
+ Before changing the order in the ui all keys had a priority of 100. With the change of the order of one key all keys got a new priority and were updated. I would not expect that.
+ The root of the problem lays within this class AbstractGeneratedSecretKeyProviderFactory and it's validateConfiguration method.
I would not expect a an update of a key in a validate method.
public abstract class AbstractGeneratedSecretKeyProviderFactory<T extends KeyProvider> implements KeyProviderFactory<T> {
@Override
public void validateConfiguration(KeycloakSession session, RealmModel realm, ComponentModel model) throws ComponentValidationException
int size = model.get(Attributes.SECRET_SIZE_KEY, getDefaultKeySize()); // <---
if (!(model.contains(Attributes.SECRET_KEY))) { generateSecret(model, size); logger().debugv("Generated secret for {0}", realm.getName()); } else { int currentSize = Base64Url.decode(model.get(Attributes.SECRET_KEY)).length; if (currentSize != size) { // <--- generateSecret(model, size); // <--- logger().debugv("Secret size changed, generating new secret for {0}", realm.getName()); } } }
getDefaultKeySize() returns 64/128 since 2017, but the old key only has 32bit
- links to