Rémy Schumm blog ingénieur

Keycloak Häcks

publiziert am 06. 05. 2026 um 10:00

As I am running several Keycloak Instances in various environments (serious, private, student clusters), sometimes I lock myself out by bad experiments. This blog post is about ugly häcks how to get me into my Keycloak-Instance again.

Prerequisite

on all my Keycloaks, I have access to:

For ease of use I always use direct access to the Database to fix stuff if possible.

Häcks

access to Database (in general):

psql -U keycloak -d keycloak

Required User Action crashing

e.g.: here I activated a webauthn-register-passwordless user required action which is crashing and preventing me to access the master realm. to get rid of it:

SELECT ue.id, ue.username, ura.required_action
FROM user_entity ue
JOIN realm r ON r.id = ue.realm_id
LEFT JOIN user_required_action ura ON ura.user_id = ue.id
WHERE r.name = 'master'
  AND ue.username = 'remy';


DELETE FROM user_required_action ura
USING user_entity ue, realm r
WHERE ura.user_id = ue.id
  AND ue.realm_id = r.id
  AND r.name = 'master'
  AND ue.username = 'remy'
  AND ura.required_action = 'webauthn-register-passwordless';

bad login flow

if activated a bad / corrupted login flow:

display active flow details (e.g. browser flow for master realm):

SELECT r.name, f.id, f.alias
FROM realm r
JOIN authentication_flow f
  ON (f.realm_id IS NULL OR f.realm_id = r.id)
WHERE r.name = 'master'
  AND f.alias = 'browser';

fix the flow (e.g. set the flow browser_flow (normal login) to the flow named browser (built-in standart, not mutable) for realm master):

UPDATE realm r
SET browser_flow = f.id
FROM authentication_flow f
WHERE r.name = 'master'
  AND f.alias = 'browser'
  AND (f.realm_id IS NULL OR f.realm_id = r.id);

raw access to (login) events

do:

SELECT * FROM public.event_entity
ORDER BY id DESC LIMIT 100

SSO Logins by Identity Provider

for a small statistic about logins per Identity Provicer in the last 30 days:

SELECT count(1) as logins, coalesce (details_json_long_value::jsonb ->> 'identity_provider', 'no sso') AS identity_provider
FROM event_entity
WHERE event_time >= extract(epoch from now() - interval '30 days') * 1000
AND type = 'LOGIN'
group by identity_provider
order by logins desc;

Hinweis: dieser Blog wiederspiegelt meine persönliche Meinung und hat nichts mit meiner Anstellung als Dozent der zhaw noch mit anderen Anstellungen zu tun.


zurück zum Seitenanfang