In this last post in my Office365/SharePoint Online + Windows Azure + Authorization blog series, I want to introduce a little helper project I am using. To make life easier I created a little O365 authorization helper library that does a lot of the heavy lifting for you. It covers two of the three things I outlined in my series as workarounds.
Code samples I show in this post were taken from a code sample CPT’s Office365/SharePoint Online Claims Authentication Helper Library… you can get the code from the Critical Path Training site’s Members section**…** look in the Code Samples section.
Introducing the Claims Auth Friendly ClientContext: ClaimsClientContext
First it creates a special Client Site Object Model (CSOM) ClientContext
object. This object has a few properties needed for authenticating with Microsoft Online (MSO) to obtain the SAML token. It then rewrites the ClientContext
so that every request includes the SAML token:
namespace CriticalPathTraining.Office365.AuthLibrary {
public class ClaimsClientContext : ClientContext {
public string MsoUsername { get; set; }
public string MsoPassword { get; set; }
public string MsoRootSiteCollectionUrl { get; set; }
public ClaimsClientContext(string webFullUrl) : base(webFullUrl) { }
public ClaimsClientContext(Uri webFullUrl) : base(webFullUrl) { }
private MsOnlineClaimsHelper _claimsHelper;
///
/// Microsoft Online claims helper used to authenticate to SharePoint Online.
///
private MsOnlineClaimsHelper MsftOnlineClaimsHelper {
get {
if (_claimsHelper == null) {
_claimsHelper = new MsOnlineClaimsHelper(MsoUsername,
MsoPassword,
MsoRootSiteCollectionUrl);
}
return _claimsHelper;
}
}
///
/// Rewire event for client context so that every request includes
/// authenticated cookies.
///
protected override void OnExecutingWebRequest(WebRequestEventArgs args) {
args.WebRequestExecutor.WebRequest.CookieContainer
= MsftOnlineClaimsHelper.CookieContainer;
}
}
}
Usage is very simple… the downloadable library includes a test project that shows the usage:
[TestMethod]
public void CliamsClientContextTest() {
using (var context = new ClaimsClientContext(MSO_SPSITE_URL) {
MsoUsername = MSO_USERNAME,
MsoPassword = MSO_PASSWORD,
MsoRootSiteCollectionUrl = MSO_ROOT_SPSITE_URL
}) {
// get the web
var web = context.Web;
context.Load(web, w => w.Title);
context.ExecuteQuery();
Assert.IsNotNull(web.Title);
Assert.IsTrue(web.Title.Length > 0);
Console.WriteLine("Retrieved site title:" + web.Title);
}
}
Introducing the Claims Friendly Web Client: ClaimsWebClient
The other thing I give you is a special version of the WebClient
class that’s makes working with claims a bit easier. It has a single property where you specify the CookieContainer
that will contain the SAML token. The library exposes the samples Wictor Wilen provided on to do the authentication for you and generate the CookieContainer
:
namespace CriticalPathTraining.Office365.AuthLibrary {
public class ClaimsWebClient : WebClient {
///
/// Cookies that should be included on every Web request.
///
public CookieContainer CookieContainer { get; set; }
///
/// Override base GetWebRequest() method to always include cookies if
/// they were specified.
///
protected override WebRequest GetWebRequest(Uri address) {
var request = base.GetWebRequest(address);
if (request is HttpWebRequest && CookieContainer != null)
((HttpWebRequest)request).CookieContainer = CookieContainer;
return request;
}
}
}
In the associated test project you’ll also find the usage for this as well:
[TestMethod]
public void ClaimsWebClientTest() {
// file to download
string fileToDownload = "/_layouts/images/siteIcon.png";
var claimsHelper = new MsOnlineClaimsHelper(MSO_USERNAME,
MSO_PASSWORD,
MSO_ROOT_SPSITE_URL);
using (var webClient = new ClaimsWebClient() {
CookieContainer = claimsHelper.CookieContainer
}) {
// get the file
var fileStream = ((ClaimsWebClient)webClient).OpenRead(
string.Format("{0}{1}", MSO_SPSITE_URL, fileToDownload)
);
// download & write local
string tempFilePath = Path.GetTempFileName();
var tempFile = File.Open(tempFilePath, FileMode.OpenOrCreate);
fileStream.CopyTo(tempFile);
fileStream.Close();
tempFile.Close();
Console.WriteLine("Downloaded file to:" + tempFilePath);
// make sure file exists & bigger than 0 bytes
Assert.IsTrue(File.Exists(tempFilePath));
var fileInfo = new FileInfo(tempFilePath);
Assert.IsTrue(fileInfo.Length > 0);
}
}
Last but not least, for completeness I threw in a test for working with any of the SharePoint *.ASMX
or *.SVC
Web services. You don’t need any special helpers here as they include a CookieContainer
class already:
[TestMethod]
public void WebServiceTest() {
XmlNode results;
var claimsHelper = new MsOnlineClaimsHelper(MSO_USERNAME,
MSO_PASSWORD,
MSO_ROOT_SPSITE_URL);
using (var client = new Lists() {
Url = string.Format("{0}_vti_bin/Lists.asmx", MSO_SPSITE_URL),
UseDefaultCredentials=true,
CookieContainer = claimsHelper.CookieContainer
}) {
results = client.GetList("Shared Documents");
}
Assert.IsNotNull(results);
}