Microsoft 365 – Governance implementation – Exporting External Users from SharePoint site Using .NET Core and Microsoft Graph APIs

Exporting External Users in SharePoint Using .NET Core and Microsoft Graph APIs

“It is better to fail in originality than to succeed in imitation.”

Greetings SharePoint Enthusiasts,

In this article, we extend a warm welcome as we embark on a journey deep into the intricacies of exporting all external users within SharePoint sites in our Microsoft 365 tenant. Through the lens of a powerful .NET Core application and the capabilities of Microsoft Graph APIs, we’ll unveil a strategic approach that empowers us to gain valuable insights into our SharePoint collaboration landscape.

Key Takeaways from this article

  • Learn to use a .NET Core application and Microsoft Graph APIs to export external users in SharePoint.
  • Step-by-step guide covers authentication, fetching external users, iterating through sites, and identifying external users.
  • Real-world scenario focuses on global enterprise collaboration with external agencies.
  • Challenges addressed include managing diverse SharePoint sites, time-sensitive collaboration, and security compliance.
  • Benefits highlighted: efficient onboarding/offboarding, granular access control, and improved auditing/reporting.
  • Graph API permissions discussed for secure interaction with Microsoft Graph and SharePoint.
  • Detailed code walkthrough provided for a deeper understanding of the implementation process.

But before we dive into the details, let’s ensure we are well-prepared for this enlightening expedition. Here are the prerequisites we need to have in place:

Prerequisites:

Before embarking on this journey, ensure we have the following prerequisites in place:

Microsoft 365 Account: A valid Microsoft 365 account with the necessary permissions.
Microsoft Entra ID Access: Access to Microsoft Entra AD for application registration and obtaining authentication credentials.
.NET Core SDK: Install the latest version of the .NET Core SDK on your development machine.

Real-World Example: Streamlining External User Management in a Global Enterprise

Imagine you work for a global enterprise with offices in multiple countries, each relying heavily on SharePoint for collaboration and document management. External contributors, often partners, vendors, or clients, regularly access SharePoint sites to collaborate on projects. Efficiently managing these external users becomes paramount for security, compliance, and streamlined user administration.

Scenario:

Your organization collaborates with external marketing agencies to create promotional materials for global campaigns. These external agencies need access to specific SharePoint sites containing campaign assets, timelines, and collaboration spaces. As campaigns run concurrently across various regions, managing external users efficiently becomes a complex but essential task.

Challenges:

Diverse SharePoint Sites:

  • Multiple SharePoint sites dedicated to various campaigns, each with its own set of external users.

Time-Sensitive Collaboration:

  • External agencies require timely access to project-specific SharePoint sites during campaign planning and execution.

Security and Compliance:

  • Adherence to security and compliance policies is crucial, ensuring that external users have the necessary access without compromising sensitive data.

How Our .NET Core Application Helps:

Identifying External Users:

  • Our .NET Core application, utilizing Microsoft Graph APIs, identifies external users within SharePoint sites based on the ‘Guest’ user type or specific markers in their usernames.

Centralized User Administration:

  • By fetching and consolidating information about external users across all SharePoint sites, our application provides a centralized list, simplifying user administration.

Proactive Security Oversight:

  • Regular exports of external user data enable security teams to proactively identify and address potential security risks associated with external access to SharePoint resources.

Step-by-Step Implementation:

Authentication:

  • Authenticate the application using Microsoft Graph, ensuring secure access to SharePoint data.

Fetch External Users:

  • Utilize Microsoft Graph APIs to fetch external users, applying filters to retrieve only the relevant user information.

Iterate Through SharePoint Sites:

  • Iterate through all SharePoint sites, fetching user data from the User Information List for each site.

Identify External Users:

  • Identify external users based on predefined criteria, such as user type or specific markers in usernames.

Consolidate User Information:

  • Consolidate relevant user information into a structured format for centralized administration.

Export to Excel:

  • Export the compiled external user data to an Excel file for easy accessibility and review.

Benefits in Action:

Efficient Onboarding and Offboarding:

  • During a new campaign, external agencies gain quick access to relevant SharePoint sites, streamlining onboarding. Similarly, when a campaign concludes, offboarding is equally swift.

Granular Access Control:

  • Security teams can review and modify external user access at a granular level, ensuring compliance with data access policies.

Auditing and Reporting:

  • Security audits and compliance reviews become more manageable with regularly exported reports on external user activities.

In this real-world example, our .NET Core application, powered by Microsoft Graph APIs, plays a pivotal role in enhancing collaboration with external entities while maintaining a robust security posture within the dynamic landscape of global campaigns. This scenario demonstrates the practical application and benefits of our solution in a complex, real-world business environment.

Application:

The .NET Core application provided here extends its capabilities to focus on SharePoint sites. It utilizes Microsoft Graph APIs to fetch and export all external users within SharePoint, offering a holistic approach to user management.

Graph API Permissions: A Strategic Approach

  • Before your .NET Core application can seamlessly interact with Microsoft Graph API, it needs the appropriate permissions.
  • This ensures that your application can access the required resources and perform specific actions. Grant the following permissions in the Azure portal to enable comprehensive functionality:

Grant Permissions

Granting the appropriate permissions to our application is crucial for accessing Microsoft Graph resources securely. In the context of SharePoint and Microsoft Graph, we’ll need to configure specific permissions to ensure our .NET Core application can interact with SharePoint sites effectively.

  • Sites.Read.All:
    • Permission Type: Application
    • Description: This permission allows our application to read items in all site collections without requiring a signed-in user. It’s necessary for fetching SharePoint site information.
  • Sites.ReadWrite.All:
    • Permission Type: Application
    • Description: This permission is more powerful, granting our application the ability to read and write items in all site collections without a signed-in user. It’s useful for scenarios involving the modification of SharePoint data.

Why are these Permissions Necessary?

Access to SharePoint Data:

  • These permissions enable our application to retrieve information from SharePoint sites, including details about users, lists, and other relevant data.

Effective User Management:

  • With the right permissions, our application can efficiently manage external users within SharePoint, contributing to streamlined user administration.

Security and Compliance:

  • By granting minimum necessary permissions, we adhere to the principle of least privilege, ensuring that our application accesses only the required data and functionalities.

In conclusion, ensuring that our .NET Core application has the appropriate Graph API permissions is fundamental to its success in interacting with Microsoft Graph and SharePoint. By following the permissions guidelines outlined above, we strike a balance between functionality and security, empowering our application to perform tasks effectively while adhering to security best practices.

Code Walkthrough: Fetching and Exporting External Users in SharePoint using Microsoft Graph

Certainly! Let’s break down the code and explain each part:

private async void OnExportExternalUsersToExcelClicks(object sender, RoutedEventArgs e)
{
try
{
// Get the authenticated Graph client
var graphClient = await _graphService.GetAuthenticatedGraphClient();

    // Fetch external/guest users from Azure AD
    var externalUsersResponse = await graphClient.Users
        .GetAsync((requestConfiguration) =>
        {
            // Filter to get the User Information List
            requestConfiguration.QueryParameters.Filter = "userType eq 'Guest'";
        });

    var externalUsers = externalUsersResponse.Value;

    // Fetch all sites in the tenant
    int top = 978;
    List<Microsoft.Graph.Models.Site>? siteCollections;

    List<ExternalUserSiteDto> externalUserSites = new List<ExternalUserSiteDto>();

    // Fetch all sites with a specified 'Top' parameter
    var siteCollection = await graphClient.Sites.GetAsync((requestConfiguration) =>
    {
        requestConfiguration.QueryParameters.Top = top;
    });
    siteCollections = siteCollection?.Value;

    if (siteCollections != null)
    {
        // Fetch User Information List ID and users in batches
        var tasks = siteCollections.Select(async site =>
        {
            // Extract the site ID from the full site URL
            var siteId = site.Id.Split(',')[1];

            // Fetch the User Information List ID for the current site
            var userListIdResponse = await graphClient.Sites[siteId].Lists
                 .GetAsync((requestConfiguration) =>
                 {
                     // Filter to get the User Information List
                     requestConfiguration.QueryParameters.Filter = "DisplayName eq 'User Information List'";
                 });

            var userListId = userListIdResponse.Value?.FirstOrDefault()?.Id;

            if (userListId != null)
            {
                // Fetch users from the User Information List for the current site
                var users = await graphClient.Sites[siteId].Lists[userListId].Items
                    .GetAsync((requestConfiguration) =>
                    {
                        // Expand the fields to include 'id' and 'UserName'
                        requestConfiguration.QueryParameters.Expand = new string[] { "fields($select=id,UserName)" };
                    });

                foreach (var listItem in users.Value)
                {
                    var userId = listItem.Id;
                    var fields = listItem.Fields;

                    if (fields != null && fields.AdditionalData != null && fields.AdditionalData.TryGetValue("UserName", out var userNameValue))
                    {
                        var userName = userNameValue?.ToString();

                        if (!string.IsNullOrEmpty(userName))
                        {
                            // Check if the user is an external user or has a specific marker in the username
                            var isExternalUser = externalUsers.Any(externalUser =>
                                externalUser.UserPrincipalName.Equals(userName, StringComparison.OrdinalIgnoreCase));

                            if (isExternalUser || (userName.Contains("#EXT#")))
                            {
                                // Add the user information to the list
                                externalUserSites.Add(new ExternalUserSiteDto
                                {
                                    UserId = userId,
                                    UserName = userName,
                                    Site = site.DisplayName
                                });
                            }
                        }
                    }
                }
            }
        });

        // Wait for all tasks to complete
        await Task.WhenAll(tasks);
    }

    // Export external user sites to Excel
    ExportToExcel(externalUserSites, "ExternalUserSites");
}
catch (Exception ex)
{
    ResultTextBox.Text += $"Error: {ex.Message}\n";
}

}

Explanation:

Authentication and Graph Client Initialization:

var graphClient = await _graphService.GetAuthenticatedGraphClient();

  • This code initializes the Microsoft Graph client using the _graphService object. The await keyword ensures that the authentication process is completed before proceeding.

Fetching External Users:

var externalUsersResponse = await graphClient.Users
.GetAsync((requestConfiguration) =>
{
// Filter to get the User Information List
requestConfiguration.QueryParameters.Filter = "userType eq 'Guest'";
});
var externalUsers = externalUsersResponse.Value;

  • It uses the Microsoft Graph API to fetch external/guest users from Azure AD. The Filter parameter is used to retrieve only guest users.

Fetching Sites:

int top = 978;
List? siteCollections;
var siteCollection = await graphClient.Sites.GetAsync((requestConfiguration) =>
{
requestConfiguration.QueryParameters.Top = top;
});
siteCollections = siteCollection?.Value;

  • This section fetches all sites in the tenant with a specified ‘Top’ parameter. It limits the number of sites to be retrieved.

Iterating Through Sites and Lists:

var tasks = siteCollections.Select(async site =>
{
// Extract the site ID from the full site URL
var siteId = site.Id.Split(',')[1]; // Fetch the User Information List ID for the current site
var userListIdResponse = await graphClient.Sites[siteId].Lists
.GetAsync((requestConfiguration) =>
{
// Filter to get the User Information List
requestConfiguration.QueryParameters.Filter = "DisplayName eq 'User Information List'";
}); var userListId = userListIdResponse.Value?.FirstOrDefault()?.Id; if (userListId != null)
{
// Fetch users from the User Information List for the current site
var users = await graphClient.Sites[siteId].Lists[userListId].Items
.GetAsync((requestConfiguration) =>
{
// Expand the fields to include 'id' and 'UserName'
requestConfiguration.QueryParameters.Expand = new string[] { "fields($select=id,UserName)" };
}); foreach (var listItem in users.Value) { // Extract user information and perform actions // ... } }
}); // Wait for all tasks to complete
await Task.WhenAll(tasks);

  • This part iterates through the fetched sites and, for each site, fetches the User Information List ID. Then, it fetches users from the User Information List for that site in batches.

User Information Processing:

foreach (var listItem in users.Value)
{
// Extract user information and perform actions
// …
}

  • Inside the nested loop, it processes each user’s information, checks if they are external users or have a specific marker in the username, and adds relevant information to the externalUserSites list.

Export to Excel:

// Export external user sites to Excel
ExportToExcel(externalUserSites, "ExternalUserSites");

  • Finally, it exports the collected external user sites information to an Excel file using the ExportToExcel method.

Error Handling:

} catch (Exception ex) {
ResultTextBox.Text += $"Error: {ex.Message}\n";
}

  • Any errors that occur during the process are caught, and an error message is appended to the ResultTextBox.

This code fetches external/guest users from Azure AD, retrieves all sites in the tenant, iterates through each site and its associated lists to fetch user information, filters out external users, and exports the information to an Excel file.

We have very good / detailed articles on Microsoft Graph. Kindly please have a look. – https://knowledge-junction.in/category/technology-articles/m365/microsoft-graph/

Conclusion:

Exporting all external users within SharePoint using a .NET Core application and Microsoft Graph APIs provides a robust solution for enhanced user management, security, and compliance. By following this guide, you’ve gained insights into the strategic approach of obtaining and exporting valuable data from your SharePoint collaboration environment.

Also get my article updates on my social media handles.

Twitter – https://twitter.com/PrajyotYawalkar?t=oovP0r9FnDtz5nNSJGKO0Q&s=09

LinkedIn – https://www.linkedin.com/in/prajyot-yawalkar-093716224/

Have a wonderful day.

Thanks for reading.

You may also like...

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Discover more from Microsoft 365

Subscribe now to keep reading and get access to the full archive.

Continue reading