Join the #CodeGeneration Movement

Building on Microsoft’s recent announcement to invest $75 million in community programs to increase access to computer science education for all youth worldwide, Microsoft Canada is launching the #codegeneration movement – to inspire Canadian youth (13 -18 year olds) to learn more about coding. #codegeneration will run from now until Computer Science Education Week (December 7-13). 

Join the Movement!

Help us spread the word and teach Canadian youth to create with technology. Anyone can code, it’s simple and easy.

  • Coding Challenges: For the next five weeks, Microsoft will be issuing coding challenges at www.CodeGeneration.ca. Students who complete these weekly challenges will have the chance to win points towards prizes while learning the basics of coding; and parents and teachers can find resources to help them lead students in these challenges themselves.
  • “Hour of Code” Sessions: As a founding corporate supporter of Code.org, Microsoft is offering free Preparation Webinars with live chat for questions and answers on November 24 and December 1.  Ready to hold your own Hour of Code with your students – download your toolkit today and lead them through a Minecraft tutorial.  Or schedule a field trip to a local Microsoft Retail Stores during Computer Science Education Week to give young developers the opportunity to learn coding. For more info, please visit the In-Store event section at a store near you.

Spread the word!

Store Office 365 User Credentials in Windows Credential Manager

I was recently tooling up to build a WinForm’s application that uploads documents from the end users desktop to their Office 365 SharePoint team site. I found a great set of building blocks to model off of with the awesome SharePoint Client Browser for SharePoint 2010 and 2013 code base.

SPCB2013 - Main Screen - v1_3

In a nutshell, it’s a treeview inside of a split panel, that enumerates pretty much all the elements that constitute SharePoint at the site collection level. It includes the Microsoft.SharePoint.Client DLL’s which take care of the bulk of operations for communicating with the remote SharePoint, be it on-prem or Office 365. It also includes tooling to be able to execute PowerShell against the remote SharePoint instance.

So we now we have a desktop platform to build custom functionality against. Any good App should be easy to use and minimize interaction required – to that end, I wasn’t quite happy with the “stickiness” of the login on the SharePoint Client Browser project. I wanted a way to securely stash the username and password so that the user wouldn’t have to input the password every time.

Where’s the place where Outlook, Lync, Internet Explorer and more store user credentials? It’s the Windows Credential Manager – accessible from the Windows Control Panel, this system provides a secure persistent store for username + passwords.

“Credential Manager allows you to store credentials, such as user names and passwords that you use to log on to websites or other computers on a network. By storing your credentials, Windows can automatically log you on to websites or other computers. Credentials are saved in special folders on your computer called vaults. Windows and programs (such as web browsers) can securely give the credentials in the vaults to other computers and websites.”

Once again, Codeplex makin’ me look good – after a fair chunk of research I wound up back at Codeplex with the following project: Credential Management. CredentialManagement is a free, open source library that can be utilized to help the application manage storing and retrieving of user credentials using the Windows Credential Management API.

The main problem this project solves is that the handles to get into the Windows Credential Manager are C++. Ouch.. so, it take’s care of this little friction point for us by wiring in some Windows Interop stuff, the guts of which can be seen in the NativeMethods.cs file in that project.

So, let’s get into mashing this sucker into our Office 365 desktop client app.

Part 1 – Build CredentialManagement.dll and add it to your SharePoint Client Browser

1. Download the SharePoint Client Browser project source code, garnish to taste. Customize freely to suit your use but try not to mess with the authentication steps too much or it will be harder to use the following steps to integrate the CredentialManager code.
2. Download the CredentialManager project source code
3. Open the CredentialManager project in Visual Studio and make sure it’s in Release mode instead of Debug (you always check this before publishing anyhow, right?) and Build it:
1
4. Go to the /Bin/Release folder for the project and grab the CredentialManager.dll. Transplant it into your active SharePoint Client Browser visual studio project and add it as a Reference:
23
4

Now it’s time to get out the wrench and do some plumbing.

Part 2 – Add CredentialManagement functions into the SharePoint Client Browser

While the SharePoint Client Browser has some discussions and collateral on the Codeplex pages, the CredentialManagement project is bare bones and not documented in any form. The following sections should serve to give you enough insight into it’s workings so that you can save some time integrating it into this or any other project where you’d like to be able to store and retrieve user credentials from the Windows Credential Manager.

1. In the SharePoint Client Browser project, open the SiteAuth.cs file, ensure you have the correct Using’s, and add the following four functions:

  
using Microsoft.SharePoint.Client;
using SPBrowser.Extentions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Security;
using System.Text;
using System.Xml.Serialization;
using SPClient = Microsoft.SharePoint.Client;
using CredentialManagement;

//Begin Credential Manager functions
        public static string GetUsername(string strUrlAsString)
        {
            var cm = new Credential { Target = strUrlAsString };
            if (!cm.Exists())
                return null;

            cm.Load();
            string un = cm.Username.ToString();
            return un;
        }

        public static string GetPassword(string strUrlAsString)
        {
            var cm = new Credential { Target = strUrlAsString };
            if (!cm.Exists())
                return null;

            cm.Load();
            string up = cm.Password.ToString();
            return up;
        }

        public static bool SetCredentials(string strUrlAsString, string strUsername, string strPassword)
        {
            var cm = new Credential { Target = strUrlAsString, PersistanceType = PersistanceType.Enterprise, Username = strUsername, Password = strPassword };
            return cm.Save();
        }

        public static void RemoveCredentials(string strUrlAsString)
        {
            var cm = new Credential { Target = strUrlAsString };
            cm.Delete();
        }
        //End Credential Manager functions

2. That’s it for that portion – you can choose the details around how you want to store the credentials. In my case, I added a checkbox for “Save my credentials” and that triggers whether to fire the SetCredentials function based on the user login prompt info filled in. After that, the user credentials are visible in the Windows Credential Manager:
7

Part 3 – Open and populate the Login Form when the App opens

We want to pre-populate the login form with the recently saved credentials when the program opens.

1. To this end, go to MainBrowser.cs in the SharePoint Client Browser project, and modify the relevant functions to match below (note I stripped out the program update checking stuff that was present):

  
        private void MainBrowser_Shown(object sender, EventArgs e)
        {
            // try to login via via recent sites
            this.LoadRecentSites();
        }
  
        private void LoadRecentSites()
        {
            try
            {
                var cm = new Credential { Target = Constants.ROOT_SITE_COLLECTION };
                if (cm.Exists())
                {
                    ClearSavedAccountToolStripMenuItem.Enabled = true;
                    AddSite();
                }
            }
            catch (System.Exception ex)
            {
                MessageBox.Show(ex.Message, this.Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
                LogUtil.LogException(ex);
                richTextBoxLog.Text = string.Format("{0}{1} {2}", richTextBoxLog.Text, Environment.NewLine, ex.Message);
                radLabelElementStatus.Text = ex.Message;
            }
        }

2. In the SharePoint Client Browser file AddSite.cs, add/modify the following to achieve the effect of pre-populating the Username & Password fields from the Windows Credential Manager cred’s stored for that URL:

  
public AddSite(SiteAuth site)
        {
            try
            {
                InitializeComponent();
                tbSiteUrl.Text = site.UrlAsString;
                var cm = new CredentialManagement.Credential { Target = tbSiteUrl.Text };
                if (cm.Exists())
                {
                    string strUsername = SPBrowser.SiteAuth.GetUsername(tbSiteUrl.Text);
                    tbUsername.Text = strUsername;
                    string strPassword = SPBrowser.SiteAuth.GetPassword(tbSiteUrl.Text);
                    tbPassword.Text = strPassword;
                }

                tbSiteUrl.Enabled = false;
                cbAuthentication.Enabled = false;
                cbAuthentication.SelectedIndex = (int)site.Authentication;

                if (tbUsername.Text.Length > 0)
                    tbPassword.Select();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, this.Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
                LogUtil.LogException(ex);
            }
        }

Part 4 – Give the user the ability to clear their credentials from the App

Finally, you may want to give users the ability to proactively clear their credentials from the Windows Credential store with a push button or such. In my case, I added a “Clear Saved Account” menu option.
5

Here is what I made up for that click function:

 
private void ClearSavedAccountToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                SiteAuth.RemoveCredentials(Constants.ROOT_SITE_COLLECTION);
                // Remove from global site collection list
                SiteAuth site = Globals.SiteCollections.SingleOrDefault(s => s.Url.OriginalString.Equals(((SPClient.Site)_selectedContextMenuNode.Tag).Url, StringComparison.InvariantCultureIgnoreCase));
                Globals.SiteCollections.Remove(site);
            }
            catch (System.Exception ex)
            {
                LogUtil.LogException(ex);
                richTextBoxLog.Text = ex.Message;
            }
            finally
            {
                RefreshCollection();
                MessageBox.Show(this, "Saved Account Credentials have been cleared from Windows Credential Manager", "Clear Saved Account", MessageBoxButtons.OK, MessageIcon.None);
                ClearSavedAccountToolStripMenuItem.Enabled = false;
                lblElementStatus.Text = "Saved Account Credentials have been cleared from Windows Credential Manager";
            }
        }

Part 5 – Reference Windows Credentials to pull up the SharePoint Client Context

You will probably be wanting to execute calls with the SharePoint Client to accomplish different tasks. In the example below, we are looking up a list named “Contacts” in the Office 365 project site, binding it as datasource and wiring up the datasource to a datagrid (in this case, a Telerik RadGrid, but any old .NET datagrid would work too):

  
Microsoft.SharePoint.Client.ClientContext clientContext = new Microsoft.SharePoint.Client.ClientContext(siteUrl);
                string strSecPassword = SiteAuth.GetPassword(Constants.ROOT_SITE_COLLECTION);

                System.Security.SecureString passWord = new System.Security.SecureString();
                foreach (char c in strSecPassword.ToCharArray()) passWord.AppendChar(c);

                Microsoft.SharePoint.Client.SharePointOnlineCredentials Creds = new Microsoft.SharePoint.Client.SharePointOnlineCredentials(SiteAuth.GetUsername(Constants.ROOT_SITE_COLLECTION), passWord);
                clientContext.Credentials = Creds;

                Microsoft.SharePoint.Client.List oList = clientContext.Web.Lists.GetByTitle("Contacts");

                Microsoft.SharePoint.Client.CamlQuery camlQuery = new Microsoft.SharePoint.Client.CamlQuery();
                camlQuery.ViewXml = "<View><RowLimit>100</RowLimit></View>";
                Microsoft.SharePoint.Client.ListItemCollection collListItem = oList.GetItems(camlQuery);

                clientContext.Load(collListItem);

                clientContext.ExecuteQuery();

                System.Data.DataTable table;
                table = new System.Data.DataTable();
                table.Columns.Add("Select", typeof(bool));
                table.Columns.Add("Email Address", typeof(string));
                table.Columns.Add("First Name", typeof(string));
                table.Columns.Add("Last Name", typeof(string));
                System.Data.DataRow row;

                foreach (Microsoft.SharePoint.Client.ListItem oListItem in collListItem)
                {
                    row = table.Rows.Add();
                    row["Select"] = oListItem["IsDefault"];
                    row["Email Address"] = oListItem["Email"];
                    row["First Name"] = oListItem["FirstName"];
                    row["Last Name"] = oListItem["Title"];
                }

                radGridViewContacts.DataSource = table.DefaultView; 

The result of this one, a grid bound to your SharePoint list (with a select checkbox column added):
6

Conclusion

The Windows Credential Manager is the central store for desktop creds. As more and more people get on board with Office 365, desktop Apps that use functionality like the SharePoint Client Browser will become more and more in demand. WinForm’s are going to be around for a while yet – but next generation of this would be of course be to leverage the Windows Credential Manager in a Windows 8 App. To this end, you can use the much simpler WinRT Password Vault functionality that’s available in Windows 8.