Hello Christoph Filnkößl,
I understand you're trying to set Custom Security Attributes using the Microsoft Graph Java SDK and are encountering a serialization error: Dangling name: customSecurityAttributes
.
I faced the same issue initially while using Microsoft Graph Java SDK version 6:
The example from the documentation doesn't work because the SDK now uses the Kiota code generator. As a result, using HashMap<String, Object>
leads to serialization issues for complex objects like custom attributes.
For the app registration, make sure the following API permissions are granted (type: Application) with admin consent:
I already have one custom security attribute named ProjectDate created in Engineering
attribute set:
Here’s the working setup with the correct dependencies and implementation to assign value to user:
pom.xml:
<dependencies>
<dependency>
<groupId>com.microsoft.graph</groupId>
<artifactId>microsoft-graph</artifactId>
<version>6.36.0</version>
</dependency>
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-identity</artifactId>
<version>1.11.0</version>
</dependency>
<dependency>
<groupId>com.microsoft.kiota</groupId>
<artifactId>microsoft-kiota-serialization-json</artifactId>
<version>1.8.4</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.4.14</version>
</dependency>
</dependencies>
Main.java:
package com.example.azureauth;
import com.azure.identity.ClientSecretCredential;
import com.azure.identity.ClientSecretCredentialBuilder;
import com.microsoft.graph.models.User;
import com.microsoft.graph.serviceclient.GraphServiceClient;
import com.microsoft.kiota.serialization.UntypedNode;
import com.microsoft.kiota.serialization.UntypedObject;
import com.microsoft.kiota.serialization.UntypedString;
import java.util.HashMap;
import java.util.Map;
public class Main {
public static void main(String[] args) {
final String clientId = "appId";
final String tenantId = "tenantId";
final String clientSecret = "secret";
final String userId = "******@xxxxxxxxx.onmicrosoft.com";
final String attributeSetId = "Engineering";
final String attributeName = "ProjectDate";
final String attributeValue = "2025-12-31";
ClientSecretCredential credential = new ClientSecretCredentialBuilder()
.clientId(clientId)
.tenantId(tenantId)
.clientSecret(clientSecret)
.build();
GraphServiceClient graphClient = new GraphServiceClient(credential, "https://graph.microsoft.com/.default");
try {
Map<String, UntypedNode> valueMap = new HashMap<>();
valueMap.put("@odata.type", new UntypedString("#Microsoft.DirectoryServices.CustomSecurityAttributeValue"));
valueMap.put(attributeName, new UntypedString(attributeValue));
Map<String, UntypedNode> setMap = new HashMap<>();
setMap.put(attributeSetId, new UntypedObject(valueMap));
User user = new User();
user.setAdditionalData(Map.of("customSecurityAttributes", new UntypedObject(setMap)));
graphClient.users().byUserId(userId).patch(user);
System.out.println("Attribute value successfully assigned.");
} catch (Exception e) {
System.out.println("Failed to assign attribute to user: " + e.getMessage());
}
}
}
Response:
To confirm that, I checked the same in Portal where custom security attribute value assigned to user successfully as below:
This workaround uses UntypedObject
and UntypedString
to ensure proper serialization. It’s necessary due to changes in SDK v6 that rely on the Kiota generator.
For further reference, check the v6 SDK upgrade guide.
Hope this helps!
If this answer was helpful, please click "Accept the answer" and mark Yes
, as this can help other community members.
If you have any other questions or are still experiencing issues, feel free to ask in the "comments" section, and I'd be happy to help.