Chris is a Senior Software Engineer at ThreeWill. His area of focus is consulting in the development of Microsoft .NET and SharePoint technologies. His primary role has been development lead in recent projects. Project roles have ranged from Development/Technical Lead to Development Resource.
I was recently tasked with working on a proof-of-concept (POC) that required the use of SharePoint hosted in Azure. This particular SharePoint environment was configured exclusively with claimed-based authentication. My task was to leverage the client-side object model (CSOM) to update the AlternateCSSUrl property on the target Web (in this case a Microsoft.SharePoint.Client.Web object).
Side Note: Setting this AlternateCSSUrl property to point to a custom “.css” file that resides in the local Site Assets library is a nice-and-simple way to augment some of the SharePoint styling. In this case, my goal was to improve the user experience for mobile users (basically… introduce some “responsive” behavior).
Setting the AlternateCSSUrl property is super simple, assuming you can successfully authenticate to your target SharePoint environment. However, simply setting up a NetworkCredential object or relying on DefaultCredentials does not cut it with claimed-based authentication. Claims-based authentication requires a separate hop to an ADFS server, and the use of using a FedAuth cookie issued from the target SharePoint environment.
I did a search for “CSOM and claimed-based authentication” and found a couple of interesting links…both of which focus on SharePoint 2010 (I was targeting SharePoint 2013), and offer an understanding of the problem and respective solution.
Both of these are worth a read to get a better understanding of what needs to be done.
Since I was very limited on time, I started digging a bit more and decided to have a look at the wealth of samples from the Patterns and Practices (PnP) folks. Low and behold, I found this…. https://github.com/OfficeDev/PnP-Sites-Core/blob/master/Core/SAML%20authentication.md
Basically, the PnP AuthManager class has support for exactly what I needed. Thanks PnP team!
The PnP AuthManager makes this very simple. Here is an example of what this might look like. The code has been simplified to show the essence.
[sourcecode lang=”csharp”]
static void Main(string[] args)
{
string webUrl = "https://portal.contoso.com";
string userName = "user1";
string password = "password1";
string domain = "contoso.com";
string sts = "adfs.contoso.com";
string idpld = "urn:sharepoint:sp-contoso";
string cssRelativePath = "/SiteAssets/responsive-option1.css";
SetAlternateCSSUrl(webUrl, userName, password, domain, sts, idpld, cssRelativePath);
}
private static void SetAlternateCSSUrl(string webUrl, string userName, string password, string domain, string sts, string idpld, string cssRelativePath)
{
OfficeDevPnP.Core.AuthenticationManager am = new OfficeDevPnP.Core.AuthenticationManager();
using (var ctx = am.GetADFSUserNameMixedAuthenticatedContext(webUrl, userName, password, domain, sts, idpld))
{
ctx.RequestTimeout = Timeout.Infinite;
// Just to output the site details
Web web = ctx.Web;
ctx.Load(web, w => w.Title, w => w.ServerRelativeUrl, w => w.AlternateCssUrl);
ctx.ExecuteQueryRetry();
web.AlternateCssUrl = web.ServerRelativeUrl + cssRelativePath;
web.Update();
web.Context.ExecuteQuery();
}
}
[/sourcecode]