1,343 words, 7 minutes read time.
Introduction – Why This Code Matters
If you’ve ever tried to wrestle with SharePoint through raw API calls, you know the experience can feel like stripping a rusty bolt with a cheap wrench—frustrating, time-consuming, and likely to leave you questioning life choices. Yet, for enterprise developers who live and breathe C# and .NET, integrating directly with SharePoint data is no longer optional—it’s essential.
Whether you’re automating workflows, building document dashboards, or simply pulling down a list of files for an internal tool, Microsoft Graph is now the standard doorway into SharePoint and the rest of Microsoft 365. Forget the older SOAP or REST endpoints—Graph provides a unified, modern, and secure way to interact with almost everything in the Microsoft cloud.
But Graph isn’t a plug-and-play tool—you’ve got to know how to authenticate, discover resources, and pull the right data without grinding through endless documentation. That’s where this guide—and the Program.cs code sample—comes in. We’re not just showing code; we’re showing how to use Device Code Flow authentication to interact with SharePoint via Graph in a way that’s secure, fast, and practical for real-world use.
Grab a coffee, lean back in that chair that’s molded perfectly to your back after years of late-night debugging, and let’s break this thing down.
Understanding the Core Technologies
Microsoft Graph: The Central Hub for Microsoft 365 Data
At its core, Microsoft Graph is an API gateway to nearly everything in the Microsoft 365 ecosystem: Teams, OneDrive, SharePoint, Planner, Outlook—you name it. Instead of juggling separate APIs for each service, Graph offers a single endpoint (https://graph.microsoft.com) and a consistent model to access data across multiple services.
For SharePoint developers, Graph removes the hassle of crafting different service-specific authentication flows. Instead, you call into Graph with proper permissions, specify the resource path, and let the SDK handle the details.
Device Code Flow: Perfect for Console Applications
Device Code Flow is an authentication method designed for apps that can’t host a web browser or handle complex redirect URIs—like a console application. Here’s how it works:
- The app requests a device code and displays a URL and user code.
- The user visits the URL, enters the code, and logs in through a standard Microsoft sign-in page.
- The app polls for authorization until the user completes sign-in, then obtains a token.
No browser embedded in your app, no messy callback URLs. Just a quick handshake between developer and Azure AD, and you’re in.
It’s like borrowing your buddy’s shop key for one job—you don’t need permanent access, just enough to get your hands on the tools.
Preparing Your Development Environment
Before you can run the provided Program.cs code, you need three things locked and loaded:
.NET 8 SDK Installed
Head to the .NET Download Page and grab the latest SDK. Confirm installation with:
dotnet –version
- If it prints out a version starting with
8, you’re good. - Azure App Registration Configured
- Go to the Azure Portal.
- Navigate to Azure Active Directory → App Registrations → New Registration.
- Name your app something descriptive, like GraphFileLister.
- No need for redirect URIs—Device Code Flow doesn’t require them.
- Once created, note your Client ID and Tenant ID.
- Under API Permissions, add Microsoft Graph → Delegated → Sites.Read.All.
- Click Grant Admin Consent to approve the permission.
- SharePoint Site and Library Ready
- You’ll need the URL of the SharePoint site you’re accessing, e.g.,
https://bksdevsite.sharepoint.com/ - And the display name of the library you want to read, often just
"Documents"for the default library.
- You’ll need the URL of the SharePoint site you’re accessing, e.g.,
Deep Dive Into the Code
Let’s walk through the Program.cs code like we’re doing a pit stop teardown—every bolt, every line, every reason.
Program.cs Overview
At its heart, this program does four things:
- Authenticates with Microsoft Graph using Device Code Flow.
- Resolves a SharePoint site URL into a Graph site ID.
- Locates a specific document library within that site.
- Lists the files contained in the library’s root folder.
Authentication – The First Gate to Pass
var deviceCodeCredential = new DeviceCodeCredential(new DeviceCodeCredentialOptions
{
ClientId = clientId,
TenantId = tenantId,
DeviceCodeCallback = (deviceCodeInfo, cancellationToken) =>
{
Console.WriteLine("\nTo sign in, use a web browser to open the page:");
Console.WriteLine(deviceCodeInfo.VerificationUri);
Console.WriteLine("Then, enter the code to authenticate:");
Console.WriteLine(deviceCodeInfo.UserCode);
Console.WriteLine();
return Task.CompletedTask;
},
});
This block handles authentication by prompting the user to visit a Microsoft URL and enter a code displayed on the console. The DeviceCodeCredential is part of Azure.Identity, making authentication feel like a handshake rather than a wrestling match.
The scopes array:
var scopes = new[] { "Sites.Read.All" };
ensures we only request the bare minimum permission needed to read SharePoint files.
Graph Client Initialization
_graphClient = new GraphServiceClient(deviceCodeCredential, scopes);
This single line turns your credential into a fully capable GraphServiceClient, the SDK’s gateway to every Microsoft 365 resource you can imagine.
Resolving the SharePoint Site ID
Here’s where things get interesting:
var sitePath = new Uri(sharePointSiteUrl).PathAndQuery;
var siteResponse = await _graphClient.Sites[$"{new Uri(sharePointSiteUrl).Host}:/{sitePath}"].GetAsync();
Graph doesn’t work directly with raw SharePoint URLs—it wants a site ID. The above lines convert a human-readable URL into the format Graph understands.
Locating the Document Library
Once the site ID is known, we filter the site’s lists by display name:
var lists = await _graphClient.Sites[siteId].Lists.GetAsync(config =>
{
config.QueryParameters.Filter = $"displayName eq '{documentLibraryName}'";
config.QueryParameters.Expand = new string[] { "drive" };
});
The Expand parameter pulls in the drive object, because in Graph terms, a document library is essentially a special kind of drive.
Pulling the Files
Finally, we fetch items in the root of the library:
var root = await _graphClient.Drives[driveId].Root.GetAsync();
var driveItems = await _graphClient.Drives[driveId].Items[root.Id].Children.GetAsync();
This call gets every file and folder at the top level. You could extend this by recursively iterating through subfolders, but for this first pass, we’re just getting the basics.
Error Handling and Defensive Programming
Developers know that smooth demos are the exception, not the rule. Real-world apps throw exceptions when credentials expire, site paths are wrong, or libraries are empty. The code anticipates these issues:
if (lists?.Value == null || !lists.Value.Any())
{
Console.WriteLine($"Could not find the document library '{documentLibraryName}' in the specified site.");
return;
}
This prevents the program from failing silently or throwing vague runtime errors.
Conclusion – Wrapping It Up Like a Pro
Working with SharePoint through Microsoft Graph isn’t just about writing a quick script—it’s about building a reliable bridge between your application and the Microsoft 365 ecosystem. The code we’ve explored proves that with .NET 8, Device Code Flow authentication, and a little patience, you can securely list files from a SharePoint document library without losing your sanity or sacrificing security.
This approach strips away the clunky, outdated methods and replaces them with a modern pipeline that feels as solid as a freshly tightened torque wrench. And the best part? Once you’ve mastered this, the same techniques can be expanded to manage folders, upload files, trigger workflows, and build enterprise-grade solutions that actually earn their keep.
If you’ve been hesitant to integrate directly with SharePoint, now’s the time to take the plunge. Fire up your IDE, tweak the sample, and make it yours. The gritty reality of being a developer is this: the tools will always evolve, the APIs will always change, but the determination to build something rock solid is what separates pros from hobbyists.
Ready to dive deeper? Subscribe to my newsletter for more code breakdowns, best practices, and battle-tested advice from the trenches. Got questions or a better way to tackle this? Drop a comment below and join the conversation—I want to hear how you’d take this code to the next level.
Sources
- Microsoft Graph Overview
- Microsoft Graph Authentication Methods
- Azure Active Directory Developer Documentation
- SharePoint Development Documentation
- .NET Core & .NET 8 Introduction
- Microsoft Graph .NET SDK GitHub Repository
- DriveItem Resource in Microsoft Graph
- List Children in a Drive (Graph API)
- Site Resource in Microsoft Graph
- Microsoft Graph Throttling Guidance
- Microsoft DevSecOps Best Practices
- Microsoft Developer Blog (.NET)
- Best Practices for Microsoft Graph
- Azure App Service Documentation
- GitHub Actions for DevOps & CI/CD
Disclaimer:
The views and opinions expressed in this post are solely those of the author. The information provided is based on personal research, experience, and understanding of the subject matter at the time of writing. Readers should consult relevant experts or authorities for specific guidance related to their unique situations.
