Save used client as user property in Register flow

Hi, my use case is this:

I have Keycloak set up to secure 4 apps (Android free, Android paid, iOS free, iOS paid) with OIDC protocol. I’ve created a client for each of them, so 4 in total, all copies of “account”. I want to add multiple realms in the future (for now I have one besides master, let’s call it “client1-realm”).

Users create their own account, using the default “register.ftl” template.

I’ve attempted in various ways to add the referring app to the user info, but none have been successful so far. Best case scenario would be a solution that requires no coding changes to Keycloak to not further complicate future updates to this great, be it rather complex tool.

  • I’ve tried adding a server role to each client with the client name hardcoded, but this isn’t added to the created user if I query the database.
  • I’ve tried adding a client role to each client, but this isn’t added to the user. It seems roles are only added to a user after the user is already created.
  • I’ve noticed there already is a default mapper named “Client ID”. I’ve tried locating the value of this property in the database, but haven’t found it (table USER_SESSION _NOTE seems to be empty every time I check)
  • I’ve tried adding a mapper myself (I’ve tried different types, including hardcoded claim. The USER_ATTRIBUTE table does not contain the property)
  • Adding properties after the user is created seems to work, but this would have to be done programmatically, thus requiring an update to all 4 apps
  • The Keycloak Server Administration manual has a chapter on “SPI’s”. If I understood it correctly, this could be done if I supply the value from my client code as an URL parameter, then create an extra SPI module and deploy it in Keycloak, then change the register template to include it by somehow capturing the value from the URL (how to do this is not in the manual).

I came across a troubleshooting query, but strangely enough, all my users seem linked to the default “account” client. Although I think the query is faulty for what I want to find out.

SELECT kr_role.REALM_ID ‘Realm’, cl.CLIENT_ID ‘Realm Client’,
kr_role.NAME ‘Role Name’,
kr_role.DESCRIPTION ‘Role Description’,
user_ent.USERNAME ‘Domain ID’, user_ent.EMAIL ‘Email’
FROM KEYCLOAK_ROLE kr_role, USER_ROLE_MAPPING role_map,
USER_ENTITY user_ent, CLIENT cl
WHERE role_map.USER_ID = user_ent.ID
AND kr_role.ID = role_map.ROLE_ID
AND kr_role.CLIENT = cl.ID
AND cl.REALM_ID = ‘client1-realm’
ORDER BY 1, 2, 3;

I’m at a loss here… is this really this complex?

Regards,

Sabrina

I’ve found the answer, in case anyone else comes across this. I’ve implemented this stackoverflow suggestion: stackoverflow suggestion

At first, it didn’t work, because the profile.properties file entries didn’t work. You need both scripts and scripts_upload features and you have to pass them by command line:
standalone.sh -Dkeycloak.profile.feature.scripts=enabled -Dkeycloak.profile.feature.upload_scripts=enabled

Any solution I’ve tried using client scopes, groups, realm roles or client roles didn’t work. They can only be linked to a user after creation, so I would have to do that manually after the user is created.