From 3567bc1f42730cfaa887ca6f9f3be5c091201d8f Mon Sep 17 00:00:00 2001 From: Niek Otten Date: Thu, 3 Sep 2026 09:08:50 +0200 Subject: [PATCH] feat(infra): enforce MFA on the medewerker realm (refs #132) Every seeded medewerker carries a TOTP credential, so Keycloak's conditional-OTP step in both the browser and direct-grant flows always challenges them; a password alone no longer yields a token. CONFIGURE_TOTP becomes a default required action so any medewerker added later must enrol before logging in. Co-Authored-By: Claude Opus 5 (1M context) --- infra/keycloak/realms/medewerker-realm.json | 40 +++++++++++++++++++-- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/infra/keycloak/realms/medewerker-realm.json b/infra/keycloak/realms/medewerker-realm.json index fa739bc..f298d45 100644 --- a/infra/keycloak/realms/medewerker-realm.json +++ b/infra/keycloak/realms/medewerker-realm.json @@ -2,6 +2,16 @@ "realm": "medewerker", "enabled": true, "displayName": "Medewerkers", + "requiredActions": [ + { + "alias": "CONFIGURE_TOTP", + "name": "Configure OTP", + "providerId": "CONFIGURE_TOTP", + "enabled": true, + "defaultAction": true, + "priority": 10 + } + ], "roles": { "realm": [ { "name": "behandelaar", "description": "Behandelt registratieaanvragen" }, @@ -43,7 +53,15 @@ "lastName": "Behandelaar", "email": "merel@big.example.nl", "emailVerified": true, - "credentials": [{ "type": "password", "value": "test123", "temporary": false }], + "credentials": [ + { "type": "password", "value": "test123", "temporary": false }, + { + "type": "otp", + "userLabel": "seeded TOTP (fixture)", + "secretData": "{\"value\":\"BIGMEDEWERKEROTPSEED\"}", + "credentialData": "{\"subType\":\"totp\",\"digits\":6,\"counter\":0,\"period\":30,\"algorithm\":\"HmacSHA1\"}" + } + ], "realmRoles": ["behandelaar"] }, { @@ -53,7 +71,15 @@ "lastName": "Teamlead", "email": "tom@big.example.nl", "emailVerified": true, - "credentials": [{ "type": "password", "value": "test123", "temporary": false }], + "credentials": [ + { "type": "password", "value": "test123", "temporary": false }, + { + "type": "otp", + "userLabel": "seeded TOTP (fixture)", + "secretData": "{\"value\":\"BIGMEDEWERKEROTPSEED\"}", + "credentialData": "{\"subType\":\"totp\",\"digits\":6,\"counter\":0,\"period\":30,\"algorithm\":\"HmacSHA1\"}" + } + ], "realmRoles": ["behandelaar", "teamlead"] }, { @@ -63,7 +89,15 @@ "lastName": "Beheerder", "email": "bram@big.example.nl", "emailVerified": true, - "credentials": [{ "type": "password", "value": "test123", "temporary": false }], + "credentials": [ + { "type": "password", "value": "test123", "temporary": false }, + { + "type": "otp", + "userLabel": "seeded TOTP (fixture)", + "secretData": "{\"value\":\"BIGMEDEWERKEROTPSEED\"}", + "credentialData": "{\"subType\":\"totp\",\"digits\":6,\"counter\":0,\"period\":30,\"algorithm\":\"HmacSHA1\"}" + } + ], "realmRoles": ["beheerder"] } ]