Create a Realm User profile attribute using keycloak-python

I’m trying to create a Realm user profile attribute via the python-keycloak client library, as shown in the UI here:

I know from monitoring the network calls made by the web application that I need to be PUT-ing the updated attributes against the endpoint: PUT /admin/realms/{realm}/users/profile but I can’t find the relevant method in the python-keycloak library.

Does that library not support this functionality? Or is there another way?

chatGPT suggests adding it via update_realm sending in attributes that include a userProfile section with the new attribute in it. This seems to be incorrect (as usual!).

Any/all help appreciated!

Looking in url_patterns.py used by the library I can’t see the endpoint being declared anywhere.

Is there another way to set a user profile attribute on a realm via python-keycloak?

Looks like the author suggests filing issues here Issues · marcospereirampj/python-keycloak · GitHub

In the end I took the auth token from the admin client and did a PUT request via the python requests library:

# Add Organization as a custom user profile attribute against the realm
headers = {
    'accept': 'application/json, text/plain, */*',
    'authorization': f'Bearer {admin.connection.token["access_token"]}',
    'content-type': 'application/json'
}
url = f'http://keycloak:8080/admin/realms/{REALM_NAME}/users/profile'
data = {
    'attributes': [
        {
            'name': 'username',
            'displayName': '${username}',
            'validations': {
                'length': {
                    'min': 3,
                    'max': 255,
                },
                'username-prohibited-characters': {},
                'up-username-not-idn-homograph': {},
            },
            'permissions': {
                'view': ['admin', 'user'],
                'edit': ['admin', 'user'],
            },
            'multivalued': False,
        },
        {
            'name': 'email',
            'displayName': '${email}',
            'validations': {
                'email': {},
                'length': {
                    'max': 255,
                },
            },
            'required': {
                'roles': ['user'],
            },
            'permissions': {
                'view': ['admin', 'user'],
                'edit': ['admin', 'user'],
            },
            'multivalued': False,
        }, {
            'name': 'firstName',
            'displayName': '${firstName}',
            'validations': {
                'length': {
                    'max': 255,
                },
                'person-name-prohibited-characters': {},
            },
            'required': {
                'roles': ['user'],
            },
            'permissions': {
                'view': ['admin', 'user'],
                'edit': ['admin', 'user'],
            },
            'multivalued': False,
        },
        {
            'name': 'lastName',
            'displayName': '${lastName}',
            'validations': {
                'length': {
                    'max': 255,
                },
                'person-name-prohibited-characters': {},
            },
            'required': {
                'roles': ['user'],
            },
            'permissions': {
                'view': ['admin', 'user'],
                'edit': ['admin', 'user'],
            },
            'multivalued': False},
        {
            'name': 'organization',
            'displayName': 'Organization',
            'required': {
                'roles': ['admin', 'user'],
            },
            'permissions': {
                'edit': ['admin'],
                'view': ['user', 'admin'],
            },
            'multivalued': False,
            'annotations': {},
            'validations': {
                'length': {
                    'min': '1',
                    'max': '255',
                },
            },
        },
    ],
    'groups': [
        {
            'name': 'user-metadata',
            'displayHeader': 'User metadata',
            'displayDescription': 'Attributes, which refer to user metadata',
        },
    ],
}
response = requests.put(url, headers=headers, json=data)
if response.status_code != 200:
    print('Could not update user profile attributes', response.status_code)
else:
    print('Updated user profile attributes')