Product: SDP

Version: Self-Hosted 1.3.0+ or SaaS

Author: Hélène Zosym


Need

In some situations the customer might want to control creation of users and roles assignements directly on the SDP side instead of using an IDP-based integration. To avoid doing manual operations through UI it is recommended to use API for it.


However when creating a user through the Platform API (POST .../platform/users) with a roles array in the request body, the call returns 201 Created, but the role assignment is not persisted due to a known product issue.

This article covers two working solutions to assign platform (and downstream DM) roles to a user created through the API, until the bug is fixed.


Summarized Solution

  • Solution 1. Direct role-mappings API: create the user first, then call the dedicated realm role-mappings endpoints to look up available roles and assign them to the user.
  • Solution 2.Pre-defined Platform Groups: create Platform Groups pre-configured with the desired access level (DM User, DM Admin, DPC Admin, or any combination), create the user via API, then add the user to the relevant group. The Platform automatically synchronizes the group's authorization with the DM component.


Both solutions avoid relying on the roles array of the Create/Update User endpoint, which does not work until the bug is fixed.


Detailed Solution


References

https://docs.semarchy.com/saas/reference/api/platform/get-roles

https://docs.semarchy.com/saas/reference/api/platform/create-user

https://docs.semarchy.com/saas/reference/api/platform/update-user



Prerequisites

  • Self-hosted SDP or SDP SaaS tenant
  • A REST API client (Postman, curl etc.)
  • A client ID/client secret for SDP with Platform Administrator access rights.


Solution 1. Assign Roles via the role-mappings API


Step 1. Create the user without relying on the roles array

POST https://<your global domain>/auth/realms/<your realm name>/platform/users
{
  "username": "<USERNAME>",
  "email": "<EMAIL>",
  "emailVerified": true,
  "firstName": "<FIRST_NAME>",
  "lastName": "<LAST_NAME>",
  "enabled": true,
  "status": "ACTIVE"
}

Response: 201 Created

  • <your global domain> - is the DNS used for SDP IAM installation. Typically you access the SDP UI through <your realm name>.<your global domain>/welcome
  • <your realm name> - in a default installation it is "selfhosted". If you've customized the site_id/site_name in the installation, you can retrieve the value for this parameter from your usual SDP UI URL: <your realm name>.<your global domain>/welcome


Step 2. Retrieve the user ID

GET https://<your global domain>/auth/realms/<your realm name>/platform/users

Locate the created user in the list and note its id.


Step 3. Retrieve the roles available for this user

GET https://<your global domain>/auth/realms/<your realm name>/platform/users/<user ID>/role-mappings/realm/available


Note: this call returns the same list as GET https://<your global domain>/auth/realms/<your realm name>/platform/roles so if you execute a batch on several users, you might prefer calling the get roles API preliminary to get the role IDs rather than calling realm-mappings on each user.



Step 4. Assign the realm role-mappings that are relevant to the user

POST https://<your global domain>/auth/realms/<your realm name>/platform/users/<user ID>/role-mappings/realm

[
  {
    "id": "<ROLE_ID>",
    "name": "xDM User"
  },
  {
    "id": "<ROLE_ID>",
    "name": "xDM Admin"
  }
]

Response: 204 No Content. The roles are now visible on the user, both via the API and in the Platform Administration UI. 


Example automation script (Solution 1)

The script below is written for bulk/multiple user creation: it resolves the realm roles once, up front, via GET .../platform/roles (rather than per user via .../role-mappings/realm/available), then loops over the list of users to create, applying the same pre-fetched role IDs to each one. Adapt HOST, REALM, CLIENT_ID/CLIENT_SECRET, the USERS list and ROLE_NAMES to your environment.


#!/usr/bin/env bash
set -euo pipefail

HOST="<your global domain>"
REALM="<your realm name>"
CLIENT_ID="<api-client-id>"
CLIENT_SECRET="<api-client-secret>"

# Users to create: "username,firstName,lastName"
USERS=(
  "test.user1@example.com,Test,UserOne"
  "test.user2@example.com,Test,UserTwo"
)

# Realm roles to assign to every created user
ROLE_NAMES=("xDM User" "xDM Admin")

# 1. Get an access token
TOKEN=$(curl -s -X POST "https://${HOST}/auth/realms/${REALM}/protocol/openid-connect/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials" \
  -d "client_id=${CLIENT_ID}" \
  -d "client_secret=${CLIENT_SECRET}" | jq -r '.access_token')

# 2. Retrieve all realm roles once, ahead of any user creation
ALL_ROLES=$(curl -s -X GET "https://${HOST}/auth/realms/${REALM}/platform/roles" \
  -H "Authorization: Bearer ${TOKEN}")

# Build the {id, name} payload for the roles we want to assign, reused for every user
NAMES_JSON=$(printf '%s\n' "${ROLE_NAMES[@]}" | jq -R . | jq -s .)
ROLES_PAYLOAD=$(echo "${ALL_ROLES}" | jq -c --argjson names "${NAMES_JSON}" \
  '[.[] | select(.name as $n | $names | index($n) != null) | {id, name}]')

echo "Roles resolved once for this batch: ${ROLES_PAYLOAD}"

# 3. Loop over all users: create each one, then assign the same pre-fetched roles
for USER_ENTRY in "${USERS[@]}"; do
  IFS=',' read -r USERNAME FIRST LAST <<< "${USER_ENTRY}"

  curl -s -X POST "https://${HOST}/auth/realms/${REALM}/platform/users" \
    -H "Authorization: Bearer ${TOKEN}" \
    -H "Content-Type: application/json" \
    -d "{
          \"username\": \"${USERNAME}\",
          \"email\": \"${USERNAME}\",
          \"emailVerified\": true,
          \"firstName\": \"${FIRST}\",
          \"lastName\": \"${LAST}\",
          \"enabled\": true,
          \"status\": \"ACTIVE\"
        }" > /dev/null

  USER_ID=$(curl -s -X GET "https://${HOST}/auth/realms/${REALM}/platform/users" \
    -H "Authorization: Bearer ${TOKEN}" \
    | jq -r --arg u "${USERNAME}" '.[] | select(.username==$u) | .id')

  curl -s -X POST "https://${HOST}/auth/realms/${REALM}/platform/users/${USER_ID}/role-mappings/realm" \
    -H "Authorization: Bearer ${TOKEN}" \
    -H "Content-Type: application/json" \
    -d "${ROLES_PAYLOAD}" > /dev/null

  echo "User ${USERNAME} (${USER_ID}) created and roles assigned."
done


Solution 2. Assign Roles via the role-mappings API

This approach trades a bit of per-user flexibility for fewer API calls, since the role-to-group mapping is configured once and reused for every user.


Step 1. Create Platform Groups with the desired access level

In the Platform Administration UI (or via the Groups API), create one group per access profile needed, for example DM User, DM Admin, DPC Admin, or any combination of those.


Step 2. Create the user via API

POST https://<your global domain>/auth/realms/<your realm name>/platform/users

The roles array can be omitted; it is not used by this approach. 


Step 3. Add the user to the relevant group 

PUT https://<your global domain>/auth/realms/<your realm name>/platform/users/<user ID>/groups/<group ID>


Step 4. Let the Platform synchronize authorization to DM

The Platform automatically synchronizes the group's authorization with the DM component. The DM-specific roles configured on the group are applied to the user without any additional API call.


Example automation script (Solution 2)

Adapt HOST, REALM, CLIENT_ID/CLIENT_SECRET and GROUP_ID (the ID of the pre-created group, e.g. "DM Admin") to your environment.


#!/usr/bin/env bash
set -euo pipefail

HOST="<your global domain>"
REALM="<your realm name>"
CLIENT_ID="<api-client-id>"
CLIENT_SECRET="<api-client-secret>"
GROUP_ID="<pre-created group id>"
USERNAME="test.user@example.com"

# 1. Get an access token
TOKEN=$(curl -s -X POST "https://${HOST}/auth/realms/${REALM}/protocol/openid-connect/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials" \
  -d "client_id=${CLIENT_ID}" \
  -d "client_secret=${CLIENT_SECRET}" | jq -r '.access_token')

# 2. Create the user (roles array omitted, not used by this approach)
curl -s -X POST "https://${HOST}/auth/realms/${REALM}/platform/users" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Content-Type: application/json" \
  -d "{
        \"username\": \"${USERNAME}\",
        \"email\": \"${USERNAME}\",
        \"emailVerified\": true,
        \"firstName\": \"Test\",
        \"lastName\": \"User\",
        \"enabled\": true,
        \"status\": \"ACTIVE\"
      }" > /dev/null

# 3. Retrieve the created user's ID
USER_ID=$(curl -s -X GET "https://${HOST}/auth/realms/${REALM}/platform/users" \
  -H "Authorization: Bearer ${TOKEN}" \
  | jq -r --arg u "${USERNAME}" '.[] | select(.username==$u) | .id')

# 4. Add the user to the pre-defined group (its DM roles are inherited via sync)
curl -s -X PUT "https://${HOST}/auth/realms/${REALM}/platform/users/${USER_ID}/groups/${GROUP_ID}" \
  -H "Authorization: Bearer ${TOKEN}"

echo "User ${USER_ID} created and added to group ${GROUP_ID}."



How to assign DM-only roles directly

If only the DM (application-level) role is needed - rather than the Platform-level role - it can be assigned directly within DM, independently of the two solutions above:

POST /dm/api/rest/admin/users/<user>/assign


Note: user must first have at least DM User platform role assigned to be able to get the DM roles.