How to Create SharePoint Online Classic Team Sites with MFA using C# and WinForms
Introduction
In this post, we’ll explore how to create SharePoint Online Classic Team Sites using C#, WinForms, and the Microsoft Authentication Library (MSAL) to support Multi-Factor Authentication (MFA). With MFA becoming a standard security measure, we’ll walk through how to integrate it into your SharePoint team site creation process. You can find the complete source code for this project on GitHub.
Prerequisites
- Microsoft.SharePointOnline.CSOM: For interacting with SharePoint Online.
- Microsoft.Identity.Client (MSAL): For handling authentication with MFA.
- Azure AD App Registration: You need to register an app in Azure Active Directory to enable authentication. Ensure you have the Client ID and Tenant ID for this app, and appropriate permissions for SharePoint Online.
Project Setup
- Create a Windows Forms Application project in Visual Studio.
- Install the required NuGet packages:
Install-Package Microsoft.SharePointOnline.CSOM Install-Package Microsoft.Identity.Client
- Add basic WinForms controls to allow input for Admin URL, Tenant ID, Client ID, Site Name, Owner, and Description.
The Code
Main Form Code (WinForms)
The main form collects the necessary details (like tenant admin URL, tenant ID, client ID, etc.) and triggers the creation process when a button is clicked.
using System;
using Form = System.Windows.Forms.Form;
namespace SharePointTeamSiteCreator
{
public partial class Form1 : Form
{
private const string SiteTemplate = "STS#0"; // STS#0 is the template for a classic team site
private const uint SiteLanguage = 1033; // English
private const int SiteStorageQuota = 1000; // Storage quota in MB
private const int SiteUserCodeQuota = 0; // User code quota (usually 0 unless required)
public Form1()
{
InitializeComponent();
}
// Button click event to create the Team Site
private async void btnCreateSite_Click(object sender, EventArgs e)
{
// Get user input from form fields
var adminSiteUrl = txtAdminSiteUrl.Text; // Tenant admin url
var tenantId = txtTenantId.Text; // Azure AD Tenant ID
var clientId = txtClientId.Text; // Azure AD Client ID
var siteDisplayName = txtSiteDisplayName.Text; // Desired Team Site name
var siteOwner = textSiteOwner.Text; // Desired Team Site owner
var siteDescription = txtSiteDescription.Text; // Site Description
var siteUrl = adminSiteUrl.Replace("-admin", null) + "/sites/" +
siteDisplayName.Replace(" ", string.Empty).ToLower();
await SharePointUtils.CreateTeamSiteAuthentication(adminSiteUrl, tenantId, clientId, SiteStorageQuota, SiteUserCodeQuota, siteDisplayName, siteOwner, siteUrl, SiteTemplate, SiteLanguage);
}
}
}
Utility Class for SharePoint Site Creation
This utility class handles the interaction with SharePoint Online, using MSAL for authentication and CSOM for creating the team site.
using System;
using System.Threading.Tasks;
using System.Windows.Forms;
using Microsoft.SharePoint.Client;
using Microsoft.Online.SharePoint.TenantAdministration;
using Microsoft.Identity.Client;
namespace SharePointTeamSiteCreator
{
/// <summary>
/// Utility class that provides methods for SharePoint Online site creation using the Client-Side Object Model (CSOM)
/// and Multi-Factor Authentication (MFA) via Microsoft Authentication Library (MSAL).
/// </summary>
internal static class SharePointUtils
{
/// <summary>
/// Creates a new SharePoint Online Classic Team Site using Client-Side Object Model (CSOM) and MFA.
/// The method uses Microsoft Identity Client (MSAL) for authentication and creates the site using the
/// Tenant administration API.
/// </summary>
/// <param name="adminSiteUrl">The SharePoint Online admin site URL.</param>
/// <param name="tenantId">The Azure Active Directory Tenant ID.</param>
/// <param name="clientId">The Azure AD app registration Client ID.</param>
/// <param name="siteStorageQuota">The storage quota in MB for the new site.</param>
/// <param name="siteUserCodeQuota">The user code quota for the new site.</param>
/// <param name="siteTitle">The title for the new SharePoint site.</param>
/// <param name="siteOwner">The owner of the new SharePoint site.</param>
/// <param name="siteUrl">The URL for the new SharePoint site.</param>
/// <param name="template">The template for the site (e.g., STS#0 for a classic team site).</param>
/// <param name="siteLanguage">The language locale ID for the site (default is 1033 for English).</param>
/// <returns>A Task representing the asynchronous site creation operation.</returns>
internal static async Task CreateTeamSiteAuthentication(string adminSiteUrl, string tenantId, string clientId,
long siteStorageQuota, long siteUserCodeQuota, string siteTitle, string siteOwner, string siteUrl,
string template = "STS#0", uint siteLanguage = 1033)
{
var scopes = new string[] { adminSiteUrl + "/.default" }; // Scopes
var app = GetPublicClientApp(tenantId, clientId);
AuthenticationResult authResult = null;
try
{
// Use interactive authentication to sign in
authResult = await app.AcquireTokenInteractive(scopes).ExecuteAsync().ConfigureAwait(false);
}
catch (Exception ex)
{
MessageBox.Show(@"Error acquiring token: " + ex.Message, Application.ProductName, MessageBoxButtons.OK,
MessageBoxIcon.Error);
return;
}
// Access token retrieved
var accessToken = authResult.AccessToken;
try
{
// Create a new ClientContext using the access token for MFA
using (var clientContext = new ClientContext(adminSiteUrl))
{
clientContext.ExecutingWebRequest += (sender, webRequestEventArgs) =>
{
webRequestEventArgs.WebRequestExecutor.RequestHeaders["Authorization"] =
"Bearer " + accessToken;
};
// Tenant object to manage site creation
var tenant = new Tenant(clientContext);
var siteCreationInfo = new SiteCreationProperties
{
Url = siteUrl,
Title = siteTitle,
Lcid = siteLanguage, // Locale ID for English
Template = template, // Web Template for classic team site
Owner = siteOwner,
StorageMaximumLevel = siteStorageQuota,
UserCodeMaximumLevel = siteUserCodeQuota
};
var spoOperation = tenant.CreateSite(siteCreationInfo);
clientContext.Load(spoOperation, i => i.IsComplete);
clientContext.ExecuteQuery();
// Check the operation status
while (!spoOperation.IsComplete)
{
Console.WriteLine(@"Creating site... Please wait");
System.Threading.Thread.Sleep(10000); // Wait for 30 seconds
spoOperation.RefreshLoad();
clientContext.ExecuteQuery();
}
MessageBox.Show(@"Site has been created successfully.", Application.ProductName,
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
catch (Exception ex)
{
MessageBox.Show(@"Error: " + ex.Message, Application.ProductName, MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
}
/// <summary>
/// Configures and returns a PublicClientApplication object for MSAL authentication.
/// This method sets the authority and client ID for authentication.
/// </summary>
/// <param name="tenantId">The Azure Active Directory Tenant ID.</param>
/// <param name="clientId">The Azure AD app registration Client ID.</param>
/// <returns>An IPublicClientApplication object used for acquiring authentication tokens.</returns>
private static IPublicClientApplication GetPublicClientApp(string tenantId, string clientId)
{
try
{
var tenant = string.IsNullOrEmpty(tenantId) ? "common" : tenantId;
var authorityUri = $"https://login.microsoftonline.com/{tenant}";
var clientApp = PublicClientApplicationBuilder.Create(clientId)
.WithAuthority(authorityUri)
.WithDefaultRedirectUri()
.Build();
return clientApp;
}
catch (Exception ex)
{
MessageBox.Show(@"Error: " + ex.Message, Application.ProductName, MessageBoxButtons.OK,
MessageBoxIcon.Error);
throw;
}
}
}
}
Explanation
-
Authentication with MFA: The application uses MSAL (Microsoft Identity Client) to perform interactive authentication. This ensures that Multi-Factor Authentication (MFA) is handled during login, improving security.
-
Site Creation Process: Once authenticated, the application uses the ClientContext object from the CSOM API to communicate with SharePoint Online. The
Tenant.CreateSite
method creates the classic team site based on the input provided by the user. -
Status Checking: The application continuously checks if the site creation process has been completed by polling the server until the operation is marked as complete.
Conclusion
In this tutorial, we’ve walked through how to create SharePoint Online Classic Team Sites using C#, WinForms, and MSAL for MFA. This approach ensures that your SharePoint operations are secure and comply with modern authentication standards.
This solution is flexible and can be adapted to handle other types of SharePoint site creation and management tasks. Happy coding!
Leave a comment