From bd6d4572e090ee213ad2c83855ff422523b7adcf Mon Sep 17 00:00:00 2001 From: Sharang Parnerkar <30073382+mighty840@users.noreply.github.com> Date: Wed, 20 May 2026 17:21:04 +0200 Subject: [PATCH] feat(keycloak): add tenant-context client scope + M7.1 test users Adds the breakpilot platform multi-tenancy claims to the dev realm so M7.x products (starting with compliance-scanner-agent) can authenticate against the local CERTifAI stack end-to-end. New tenant-context client scope, included by default on all three clients, with six protocol mappers backed by user attributes: tenant_id, tenant_slug, tenant_status, plan (strings) org_roles, products (multi-valued) Five test users cover every tenant_status branch: admin@certifai.local (acme, active, IT_ADMIN + CXO) user@certifai.local (acme, active, USER) trial@acme.local (trialco, trial) frozen@acme.local (frozenco, frozen) -> 402 on writes archived@acme.local (archiveco, archived) -> 410 always Enables Direct Access Grants on certifai-dashboard so password- grant requests work for local API testing. This is the dev realm only (KC_DB: dev-mem); prod realms inherit nothing from this file. Co-Authored-By: Claude Opus 4.7 (1M context) --- keycloak/realm-export.json | 208 +++++++++++++++++++++++++++++++++++-- 1 file changed, 202 insertions(+), 6 deletions(-) diff --git a/keycloak/realm-export.json b/keycloak/realm-export.json index 001dbf1..1f1ff19 100644 --- a/keycloak/realm-export.json +++ b/keycloak/realm-export.json @@ -53,7 +53,7 @@ "description": "CERTifAI administration dashboard", "enabled": true, "publicClient": true, - "directAccessGrantsEnabled": false, + "directAccessGrantsEnabled": true, "standardFlowEnabled": true, "implicitFlowEnabled": false, "serviceAccountsEnabled": false, @@ -73,7 +73,8 @@ "defaultClientScopes": [ "openid", "profile", - "email" + "email", + "tenant-context" ], "optionalClientScopes": [ "offline_access" @@ -106,7 +107,8 @@ "defaultClientScopes": [ "openid", "profile", - "email" + "email", + "tenant-context" ], "optionalClientScopes": [ "offline_access" @@ -139,7 +141,8 @@ "defaultClientScopes": [ "openid", "profile", - "email" + "email", + "tenant-context" ], "optionalClientScopes": [ "offline_access" @@ -269,6 +272,105 @@ } } ] + }, + { + "name": "tenant-context", + "description": "Breakpilot platform tenant + org claims (M7.1)", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "false" + }, + "protocolMappers": [ + { + "name": "tenant_id", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "user.attribute": "tenant_id", + "claim.name": "tenant_id", + "id.token.claim": "true", + "access.token.claim": "true", + "userinfo.token.claim": "true", + "jsonType.label": "String" + } + }, + { + "name": "tenant_slug", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "user.attribute": "tenant_slug", + "claim.name": "tenant_slug", + "id.token.claim": "true", + "access.token.claim": "true", + "userinfo.token.claim": "true", + "jsonType.label": "String" + } + }, + { + "name": "tenant_status", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "user.attribute": "tenant_status", + "claim.name": "tenant_status", + "id.token.claim": "true", + "access.token.claim": "true", + "userinfo.token.claim": "true", + "jsonType.label": "String" + } + }, + { + "name": "plan", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "user.attribute": "plan", + "claim.name": "plan", + "id.token.claim": "true", + "access.token.claim": "true", + "userinfo.token.claim": "true", + "jsonType.label": "String" + } + }, + { + "name": "org_roles", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "user.attribute": "org_roles", + "claim.name": "org_roles", + "id.token.claim": "true", + "access.token.claim": "true", + "userinfo.token.claim": "true", + "jsonType.label": "String", + "multivalued": "true", + "aggregate.attrs": "true" + } + }, + { + "name": "products", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "user.attribute": "products", + "claim.name": "products", + "id.token.claim": "true", + "access.token.claim": "true", + "userinfo.token.claim": "true", + "jsonType.label": "String", + "multivalued": "true", + "aggregate.attrs": "true" + } + } + ] } ], "users": [ @@ -289,7 +391,15 @@ "realmRoles": [ "admin", "user" - ] + ], + "attributes": { + "tenant_id": ["00000000-0000-0000-0000-000000000001"], + "tenant_slug": ["acme"], + "tenant_status": ["active"], + "plan": ["professional"], + "org_roles": ["IT_ADMIN", "CXO"], + "products": ["compliance", "certifai"] + } }, { "username": "user@certifai.local", @@ -307,7 +417,93 @@ ], "realmRoles": [ "user" - ] + ], + "attributes": { + "tenant_id": ["00000000-0000-0000-0000-000000000001"], + "tenant_slug": ["acme"], + "tenant_status": ["active"], + "plan": ["professional"], + "org_roles": ["USER"], + "products": ["compliance"] + } + }, + { + "username": "frozen@acme.local", + "email": "frozen@acme.local", + "firstName": "Frozen", + "lastName": "Tenant", + "enabled": true, + "emailVerified": true, + "credentials": [ + { + "type": "password", + "value": "frozen", + "temporary": false + } + ], + "realmRoles": [ + "user" + ], + "attributes": { + "tenant_id": ["00000000-0000-0000-0000-000000000002"], + "tenant_slug": ["frozenco"], + "tenant_status": ["frozen"], + "plan": ["starter"], + "org_roles": ["IT_ADMIN"], + "products": ["compliance"] + } + }, + { + "username": "archived@acme.local", + "email": "archived@acme.local", + "firstName": "Archived", + "lastName": "Tenant", + "enabled": true, + "emailVerified": true, + "credentials": [ + { + "type": "password", + "value": "archived", + "temporary": false + } + ], + "realmRoles": [ + "user" + ], + "attributes": { + "tenant_id": ["00000000-0000-0000-0000-000000000003"], + "tenant_slug": ["archiveco"], + "tenant_status": ["archived"], + "plan": ["starter"], + "org_roles": ["IT_ADMIN"], + "products": ["compliance"] + } + }, + { + "username": "trial@acme.local", + "email": "trial@acme.local", + "firstName": "Trial", + "lastName": "Tenant", + "enabled": true, + "emailVerified": true, + "credentials": [ + { + "type": "password", + "value": "trial", + "temporary": false + } + ], + "realmRoles": [ + "user" + ], + "attributes": { + "tenant_id": ["00000000-0000-0000-0000-000000000004"], + "tenant_slug": ["trialco"], + "tenant_status": ["trial"], + "plan": ["starter"], + "org_roles": ["IT_ADMIN"], + "products": ["compliance"] + } } ] }