How can I look up a user's manager with the MSGraph Java SDK (unattended)?

Brad Ellis 0 Reputation points
2024-05-09T19:50:18.4666667+00:00

For a bit of background, I am writing a Java app to run as a module in an older, legacy java application that was set up to use LDAP for directory services.

I've registered an application in Entra and provided the least privileges so it can read the directory, users, groups and group members. I have been able to successfully synchronize the directory and groups using MS graph so LDAP is not needed.

I run into the issue now where for some workflows in the larger legacy app, it needs to know who a user's manager is. I believed this to be simple, but I'm hitting issues. I believe the request should be something like this:

// Get a collection of users that match the UPN (Should only be one)
UserCollectionRequest usersRequest = graphClient.users().buildRequest()
                .filter("userPrincipalName eq '" + userPrincipalName + "'")
                .expand("manager");

// Get the user
User user = usersRequest.get().getCurrentPage().get(0);

// How do I get and use user.manager?

// Get the manager as a user?
User manager = user.manager;
// Nope: user.manager is of type DirectoryObject

// Get the manager's ID and look them up in their own call?
String managerID = user.manager.id;
// Nope: user.manager is null


I expected user.manager to be a User object but instead it's a DirectoryObject. Ok. I suppose I could get user.manager.id and look up the manager from that. However the user.manager DirectoryObject returned is null.

From further digging I think this is due to List manager not supporting application permissions:
https://learn.microsoft.com/en-us/graph/api/user-list-manager?view=graph-rest-1.0&tabs=java#permissions

This I find very annoying. I need this app to be able to run unattended.

Is there any path forward? I am unfortunately not a developer and struggle with Java being strongly typed and requiring such strict structure. I'd appreciate code samples if possible.

Microsoft Graph
Microsoft Graph
A Microsoft programmability model that exposes REST APIs and client libraries to access data on Microsoft 365 services.
10,821 questions
0 comments No comments
{count} votes

2 answers

Sort by: Most helpful
  1. Yakun Huang-MSFT 625 Reputation points Microsoft Vendor
    2024-05-10T06:36:03.5833333+00:00

    Hi @Brad Ellis

    You can use $expand to get the user manager, after my test, I found that some users did not add manager, so the manager value returned after query is null, so please make sure that the user has manager.

    This is the result of my query, some users are assigned a manager, and some are not, and those who are not assigned a manager will return null.

    1

    Hope this helps.

    If the reply is helpful, please click Accept Answer and kindly upvote it. If you have additional questions about this answer, please click Comment.


  2. Brad Ellis 0 Reputation points
    2024-05-10T14:28:18.2933333+00:00

    While creating a quick bit of code to show @Yakun Huang-MSFT that I had already tried the proposed solution I found where my issue was actually stemming from.

    Here is a correct way to retrieve the user's manager:

    String clientId = "<client ID>";
    String tenantId = "<tenant ID>";
    // Scopes not set. App will use its app permissions (Not delegated)
    String clientSecret = System.getenv("APP_SECRET");
    
    // Create the credential object
    ClientSecretCredential clientSecretCredential = null;
    clientSecretCredential = new ClientSecretCredentialBuilder().clientId(clientId).clientSecret(clientSecret)
            .tenantId(tenantId).build();
    
    // Create the token object
    final TokenCredentialAuthProvider tokenCredentialAuthProvider = new TokenCredentialAuthProvider(
            clientSecretCredential);
    
    // Create and return the graphClient object
    final GraphServiceClient<?> graphClient = GraphServiceClient.builder()
            .authenticationProvider(tokenCredentialAuthProvider).buildClient();
    
    // Get user
    UserCollectionRequest usersRequest = graphClient.users().buildRequest()
            //.filter("userPrincipalName eq '" + username + "'") //Get all users for this example
            .expand("manager");
    
    User manager; // Create a User object to expand user.manager.
    List<String> managerLess = new ArrayList<String>();
    List<String> managerFull = new ArrayList<String>();
    
    for (User user : usersRequest.get().getCurrentPage()) {
        // CRITICAL: If user.manager is null, do not attempt any action on user.manager. In my environment it will silently stop the program
        if (user.manager == null) {
            managerLess.add(user.displayName);
        } else {
        	manager = (User) user.manager;
        	managerFull.add(user.displayName + "  :  " + manager.displayName);
    	}
    }
    
    System.out.println("############## No manager ##############");
    managerLess.forEach(System.out::println);
    System.out.println("############## Yes manager ##############");
    managerFull.forEach(System.out::println);
    
    

    Yakun was correct in that the user.manager DirectoryObject will be null if no manager is set. What I didn't expect to happen was for my program to silently stop if I tried to reference an attribute of that null object.

    My first user had no manager, my program stopped, and I incorrectly assumed I had looped through all my users and found no managers at all.

    The solution for me was to check if the manager was null first and if so, continue in the loop.