How to set Custom Security Attributes with Java on Entra Graph API

Christoph Filnkößl 25 Reputation points
2025-04-17T16:26:28.8+00:00

Hi,

I'm currently working on implementing a Java based application that uses Graph API to access Entra users. There, the goal is to store values in the Custom Security Attributes.

The examples for Java on this page are broken however and I can't find out how to do this properly

https://learn.microsoft.com/en-us/graph/custom-security-attributes-examples?tabs=java

example:

User user = new User();
CustomSecurityAttributeValue customSecurityAttributes = new CustomSecurityAttributeValue();
HashMap<String, Object> additionalData = new HashMap<String, Object>();
 engineering = new ();
engineering.setOdataType("#Microsoft.DirectoryServices.CustomSecurityAttributeValue");
engineering.setProjectDate("2022-10-01");
additionalData.put("Engineering", engineering);
customSecurityAttributes.setAdditionalData(additionalData);
user.setCustomSecurityAttributes(customSecurityAttributes);
User result = graphClient.users().byUserId("{user-id}").patch(user);

It's unclear, what the type of "engineering" is.

Does anybody have an idea how to solve this?

Thanks, Christoph

Microsoft Entra ID
Microsoft Entra ID
A Microsoft Entra identity service that provides identity management and access control capabilities. Replaces Azure Active Directory.
24,526 questions
{count} votes

Accepted answer
  1. SrideviM 3,490 Reputation points Microsoft External Staff Moderator
    2025-04-23T13:05:40.2266667+00:00

    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:

    enter image description here

    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:

    enter image description here

    I already have one custom security attribute named ProjectDate created in Engineering attribute set:

    enter image description here

    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:

    enter image description here

    To confirm that, I checked the same in Portal where custom security attribute value assigned to user successfully as below:

    enter image description here

    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.

    User's image

    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.

    1 person found this answer helpful.

0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.