Single Sign-On Across .Net Web Apps Using Forms Based Authentication

     <foreword>Please read this explanation of Forms Based Authentication (FBA) first if you are unfamiliar with how FBA works or is implemented. </foreword>

    Achieving single sign-on capabilities using Forms Based Authentication is much easier than I had initially expected, yet it took awhile to find the exact settings required.  To get FBA working in SharePoint click here for a good starter from the SharePoint team blog.  I also used this article from MSDN as a reference for ultimately determining what settings were necessary in our environment.

    Small back story for what we are doing.  We have a SharePoint farm that has split authentication: Windows Integrated for users on the network at the office and FBA for users out in the field on the extranet.  Separate from our SharePoint farm is a .Net web application to assist with password reset and registration.  When the user logs in to SharePoint via FBA they are redirected to the external application if there is any problem with their account.  We wanted to implement single sign-on between the applications so that a user wasn’t re-prompted for credentials after the redirect.

     The general solution involved the following main items:

  • Changes to both applications’ web.config files
  • Configuring host headers for each app to be in the same domain lookup
  • 1 line of code to read authentication cookie

 

    So let’s review what was added to get this working starting with the web.config entries.

<system.web>
   <authentication mode="Forms">
      <forms name="nameOfCookie"
         loginUrl="loginPage.aspx"
         path="/"
         domain="mydomain.com"
         protection="All"/>
   </authentication>
   <machineKey validationKey="value" decryptionKey="value"
       validation="value" decryption="value" />
</system.web>

    For the web.config entries you’ll need to ensure that both apps are set to Forms authentication.  Next specify a “name” value which will be used to identify your authentication cookie on the receiving application.  By default this value is “.ASPXAUTH”.  Specify the domain that each web application will be run under.  Using host headers your site URLs might look like “site1.mydomain.com” and “site2.mydomain.com”.  Specify protection=”All” so that the authentication cookie is encrypted using the machineKey value that you specify.  Lastly provide identical machineKey entries on each web application so that both can read the authentication cookie provided by each other.  I used a free random machine key generator in my development environment, but you’ll probably want your security team to handle generating and keeping track of keys for non-development environments.

    The next step involved configuring each site to use host headers assigned to the same domain.  This article from TechNet gives a brief intro to get you started.  As stated just above, I configured the web app URLs to appear as “site1.mydomain.com” and “site2.mydomain.com” to match my entries in the web.config.
    Lastly is the code required to read the authentication cookie.  If you read the explanation article linked in the foreword above you’ll read that after logging in using forms authentication, the authentication cookie containing the currently authenticated user (along with other data) is passed along with responses back to the server.  Due to this fact, on the receiving page in the other web application we can decrypt the cookie and read who is currently authentication even though they never logged in again to the the other application.  Here is the code to explicitly reference that cookie.
string loggedInUser = FormsAuthentication.Decrypt(Request.Cookies.Get("cookieName").Value).Name
    And that wraps up the changes to my web apps to allow single sign-on for forms based authentication.  If your web applications are SSL enabled I believe there are a few additional settings you’ll need, but they should be covered in the links I provided.  I hope this helps you or at least gives you some good resources to refer to for FBA.  If you have any questions, comments, or other feedback feel free to leave it below.
 
    -Frog Out

Enumerating SharePoint Site Templates for Site Collection with PowerShell

As part of my automated deployment post last week, one step of my deployment script called for creating a SharePoint site collection using the “STSADM –o createsite” command with the –sitetemplate option used for a specific site template.  If you have never had to create a site collection from a template at the command line you may not know what to put (or know what is available to you) for the –sitetemplate option.  To remedy this I created a very simple PowerShell script that opens a site collection and enumerates the usable site templates.

EnumerateSiteTemplates1

Note: The results listed will be specific to the site collection queried and will most likely be different from the templates in the global site template catalog listed when running STSADM –o enumtemplates.  Also note that some results (ex. STS and MPS) have multiple listings with a different # following them.  These are the same site template just with different build configurations specified.  Using this knowledge we can see that for instance the blank site and team site use the same template just with different components added or activated.  You can use this same capability in your own custom site templates if you are making multiple variations of a template.

Code Snippet:

$url = "http://hq.devone.local"

$site= new-Object Microsoft.SharePoint.SPSite($url )
$loc= [System.Int32]::Parse(1033)
$templates= $site.GetWebTemplates($loc)

foreach ($child in $templates)
{
    write-host $child.Name "  " $child.Title
}
$site.Dispose()

Enjoy the script and happy SharePointing adventures.

-Frog Out

Lessons Learned from Automating a SharePoint Deployment

Now this is a topic that really excites me.  It combines two things I love: automation and SharePoint.  At my current client we are in the process of moving our custom SharePoint applications to the production environment.  As we are moving to production, that means that we develops have less handle on the implementations be they databases, code migration, etc.  To ease the load on the infrastructure team who is implementing our custom application I took the liberty of automating as much of the process as possible.  The goal I set for myself was to take a base SharePoint farm (bits installed and Central Administration site running) all the way to a fully functioning production farm in less than 1 hour.  Here are a few numbers to give you an idea of the scope of this endeavor.

  • 5 distinct custom applications
  • 1 web application with additional extension for forms based authentication
  • 15+ custom and 3rd party WSPs
  • 1 root site collection
  • 4 subsites (all with unique security settings)

Additionally we have some custom databases, stored procedures, and database related pieces that are also deployed, but since that is technically outside of the standard SharePoint realm I won’t be touching on that.  Ok, now that you have any idea of the scope of this implementation let’s get down to what all this entails, why you would consider automating your deployment, and some of the lessons learned from my experience.

First, what can you use to automate your deployment?  There are a number of tools available each having their own pros and cons.  Here are a few options and brief analysis.

  1. STSADM.exe – this is an out of the box provided command line tool for performing certain administrative tasks.  STSADM can perform a number of operations that aren’t available through the SharePoint UI, but additionally since it is a command line tool can be put into batch scripts for running multiple commands consistently.  I typically script commands into either a .bat file or a PowerShell script (our next focus.)
  2. PowerShell – I’ll say this now and I’ll say it again as many times as needed: If you are a Windows/SharePoint admin/developer/power user and haven’t begun to learn to use PowerShell, make this a high priority.  In a previous post I talked about how important PowerShell is going to be going forward with any Microsoft technology.  Just look at the fact that it is built-in (re: can’t be uninstalled) from Windows 7 and Server 2008 R2.  That aside, PowerShell let’s you run STSADM commands, SharePoint API calls, or even SharePoint web service calls.  In v2 you’ll be able to run remote commands, debug scripts, and have access to a host of other new functionality bits.
  3. Team Foundation Server – I have not personally had much of a chance to look into this process aside from reading a few articles.  Essentially what you can do is have automated builds run from your Team Foundation Server and be able to track and analyze deployments in one integrated environment.  For very large or well disciplined organizations this seems like a good progression step.
  4. 3rd party product – this could range anywhere from a workflow product able to run command line calls to a task scheduler product able to schedule batch scripts.  Again these would most likely rely on STSADM or one of the SharePoint APIs.  The ability to schedule scripts or have them fire according to workflow logic may be something useful in your organization depending on size and needs.

Second, why automate deployments?  Won’t you spend as much time developing the deployment scripts as manually clicking the buttons or typing the commands?  This is a conversation best discussed with the team doing the development and the team doing the deployment.  If both happen to be the same team or your organization is very small perhaps the benefit of automation won’t be worthwhile (in the short term.)  For larger organizations (and in the long term) I would always recommend automated deployments.  There are a number of reasons including having a repeatable process, reducing “fat fingered” commands, reducing deployment time per environment, and reducing need for developer to be on hand during implementation among others.  On the flipside there is the added time for developing the scripts and added difficulty debugging scripts.  Taken together your organization should decide what works best for you.

Third, what’s the catch?  No one gets a free lunch (unless you somehow do get free lunches regularly, then give me a call and share your secret) so there must be something that manual has an advantage over automated.  Due to the very complex nature of our current deployment there are a few items that automation actually produces unintended results.  Here are a few to note.

  • Deploying site definition as a subsite does not inherit top link bar properly.  See the pictures below.  Essentially we are seeing the top link bar fill with links to the subsite home page (first picture) instead of using the parent site’s top link bar (second picture.)  As a result we are forced to manually create our subsites.  Luckily using custom site definitions handles the heavy lifting of this process.2 3
  • In a farm that has multiple web front ends, activating features that have multiple updates to the web.config (read this article, excellent background) can cause issues.  The requests to update the web.config on each web front end will be sent out, but only one request can be fulfilled at a time.  As we have about 5+ features that fall into this category they back up and do not complete.  We have not found a good mechanism for delaying sending requests until the previous has completed.  In time with more practice we may find a way to fine tune this so that is no longer an issue.
  • When deploying sites/subsites from a site definition, any web part connections (one web part sending data to another web part) must be manually configured.  So far that I have seen web part connections cannot be contained in the onet.xml site definition (instantiation vs. declaration assuming) but I have a hunch that you could create a simple feature that’s sole purpose is to contact the web part manager and create web part connections.  I have not had the time to test this out, but it sounds plausible.  If anyone has thoughts or suggestions on this topic please leave feedback below.
  • Also when deploying sites/subsites from a site definition, some features cannot be properly activated during site creation time.  A good example is a custom feature that creates additional SharePoint groups on your site.  This is a tough one to describe, but visualize a chicken and an egg (yes, chosen for comedic sake.)  The chicken is your new site and the egg is a SharePoint group created by a feature activated on (born from) your site (your chicken).  When you create your new site (chicken) you are calling for features to also be activated (group created/egg born).  Since the egg comes from the chicken, it can’t possibly be called while the chicken itself is being born.  This leads to an error and the egg never gets born then.  Instead you must manually (or in a later script step) activate the feature that creates this group.  I hope this one didn’t thoroughly confuse you.  Just know that some features might not be able to be activated at site creation time.

If you were paying attention at the beginning you may be asking yourself “great overview on automating your install Brian, but how close did you get to your goal of a 1 hour deployment?”  We don’t have accurate measurements of the deployment time previously as our development environments grew organically at first and were slowly added to.  I would estimate that rebuilding from scratch by hand would take at least 3+ hours and constant babysitting by the implementer.  With the new process we are able to deploy the entire base farm as described above in roughly 30-45 mins.  On top of that, about 70% of that time is spent just waiting for the WSP files to be deployed to the farm.  As an added bonus, the number of clicks and lines typed is drastically reduced (I would rough estimate by 70% and 90% respectively.)

So there you have it, a quick intro/lessons learned for automating a SharePoint deployment.  For a much more example-based and in depth article please read this Automate Web App Deployment with SharePoint API.  I have referenced it many times when doing deployments and it covers just about everything from deploying lists to updating web.config to installing SharePoint.  If you have any questions, comments, or suggestions please feel free to leave them.  If there are any requests I can give a basic outline of what goes into my deployment scripts or how to architect them.  Thanks for reading.

-Frog Out

Exporting A SharePoint Site Into A Feature: Part 5 – Wrap Up

  • Part 1 – The Tools
  • Part 2  – Exporting the Site
  • Part 3 – Exporting the Lists
  • Part 4 – Exporting the Site Columns and Content Types
  • Part 5 – Wrap Up    Before I begin with the wrap up portion of this post, I want to make a correction to this series.  I was doing a bit of research today (quick comparisons, Joel Oleson’s take, deeper look at site definitions) on site templates, features, and site definitions and it struck me that the title of this series (Exporting a SharePoint Site into a Feature) isn’t quite accurate.  In reality, what I have been doing with my provided steps is creating a base site definition (simple few pages with web parts associated) and then stapled a number of features to the site definition.  There has been quite a bit of debate (see Joel Oleson’s post above) on which site provisioning method to use, each having it’s own pros and cons.  I’m not trying to tell you to choose one over the other, but do your research when deciding and find the method that best suits your (or your company’s) needs.  I hope this clears up some confusion I may have caused with the title.With that let’s continue on and walk through some of the steps for deployment and little quirks I’ve noticed.  For deployment, I use WSPBuilder to build and deploy my WSP files to the development farm.  What this ends up doing is copy my site definition files into a 12 Hive folder and deploy my features to the farm.  Site definitions stored in the 12 Hive (compared to stored in the database when customized through the UI or site templates) gives a performance gain.  On the downside site definitions are not (easily) updateable once deployed.  I say that because you technically can update your site definition, but it requires deleting and recreating your site if it has been provisioned anywhere.  With my current project we are only deploying one instance of each site definition to each environment and have backup software to facilitate easy migration of data from the old to new instance.  Hopefully your site definition remains fairly static and you only add functionality or modifications through new or updated features (which can be easily upgraded.)Once you have your WSP deployed, you can provision an instance of your site definition by creating a new site (or site collection) from your site settings page (or central admin for site collection.)  In your site definition onet.xml file, any features that you have placed in the <SiteFeatures> or <WebFeatures> elements will be “stapled” or automatically added and activated upon provisioning.  Below is a reduced list, but I have features to add web parts, lists, and content types among other things.

    ExportSharePointSite12

    One thing to note about my features.  The feature “Messaging Security Groups” is commented out.  The reason for that is that that feature creates a number of SharePoint groups (composers, approvers, etc) and assigns them permissions to the site being created.  However, the owner of these groups happens to be the Site Owners group.  Because I am not inheriting security from the parent site, new Site Owner, Member, and Reader groups are created.  This is an issue because those new groups are created after my features have been stapled.  This means that I must manually activate this feature after the site provisions process has occurred.  If anyone knows a good way around this please let me know.

    A few other things I’ve noticed during development.  When using the methods described in this series to export an instance of this site definition you will get some duplicate entries in the site definition files, particularly when it comes to web parts assigned to pages in the onet.xml.  I would recommend updating the original site definition (by hand or copying over only the changes from a new export) as a workaround.  Also, I have a few web parts that provide and consume connections to each other on various pages.  I haven’t found an easy way to configure those connections in code.  Some suggestions were found, but I was unable to get them working.  Instead I manually assign the connections once the page has been provisioned.  Again if any know of a way around that please let me know.

    And so I draw to a close this series.  Thanks for reading along.  Hopefully it gives you some pointers and insight into creating, exporting, and maintaining a site definition and associated features.  Drop me a comment if you have any questions, suggestions, or input.

    – Frog Out

Exporting A SharePoint Site Into A Feature: Part 4 – Exporting Site Columns and Content Types

If nothing else, this blog post will win the award for longest title that I’ve written yet.  Joking aside, It’s time to put one of the finishing stones in place for this series.  So far we’ve exported the site and lists, now it’s time for the site columns and content types.  The tool we’ll be using this go around is the Imtech Fields Explorer.  The process is fairly straight forward so let’s dive in.

Launching the field explorer tool, you’ll first be prompted to specify your SharePoint site URL and click Open.  You’ll see entries for this site’s content types, site columns, and lists.  Strangely (at least in the v1.3.0.0 version I’m using) I am not able to export lists.  Not sure if this is intended functionality or just features yet to be implemented.  Either way, select the content types and site columns to be exported.  You can also view detailed information about the individual entries, similar to other products such as SharePoint Manager.

ExportSharePointSite2     Click Export once you’ve selected your items.  If you’ve selected both content types and site columns, the export will occur in two phases starting with content types.

ExportSharePointSite2a     Select the destination file location for the “Content Types.xml” output.  I typically go with the desktop for convenience of loading into Visual Studio (or favorite text editor) when complete.

ExportSharePointSite2b     You’ll receive a success screen when that completes.

ExportSharePointSite2c     Follow the same procedure for site columns.

ExportSharePointSite2dExportSharePointSite2eExportSharePointSite2f     Now that you’ve got your output files, open them alongside your WSPBuilder solution.  The Columns.xml file is fairly simplistic.  It will detail all of the properties and metadata used to define a site column.  Copy all of the <Field> elements into the elements.xml file of a feature for deploying your content types (a blank feature in WSPBuilder will suffice.)  I’ve only chosen one column for the example below, but you’ll more than likely have many more.

ExportSharePointSite10a     Next open the Content Types.xml file.  For content types, so far I’ve found only the <Content Type> elements to be necessary while the <XmlDocuments> elements can be left out.  If anyone knows the <XmlDocuments> to be required for some reason let me know.  Copy the <Content Type> elements and their child elements into the same elements.xml file as above.  The <FieldRef> elements will link to the <Field> elements via the GUID.

ExportSharePointSite10b     Now if you remember from the end of part 3 of this series we talked about needing to add in the content type and site column definitions to our list definition’s schema.xml file as well.  So while we’re copying these definitions into the elements.xml file above, also add them to the appropriate schema.xml files for your lists.  Only the content types and site columns belonging to that list definition will need to be copied over.  In the end you’ll have something similar to the below example for the list schema.xml file.

ExportSharePointSite10c

And with that we’ve reached the final step of our exporting process.  I’ll be putting together a wrap up post on some caveats that I’ve run into thus far and other things to look out for along the way.  I’ll also do a quick bit on actually deploying the site template for use.  Thanks for reading along so far.  Post any comments or questions you have.  Until next time.

-Frog Out

Exporting A SharePoint Site Into A Feature: Part 3 – Exporting the Lists

So let’s recap where we’re at with this series.  Part 1 was about the tools I’ve been using to export a SharePoint site to a  feature, part 2 exported the base (pages, web part settings on pages, etc) of the site template, and now part 3 will be exporting SharePoint lists into our feature.  The tool we’ll be using time around is the MOSS Feature Generator (previously called CT Feature Creator among other names.)

As I stated in part 2, I prefer the output from the MOSS Feature Generator to that of the SharePoint Solution Generator 2008 because it required less modifications to fit into my WSPBuilder solution.  When you launch the tool, click File > New > ListTemplate Feature.  Next specify your site collection Url, the individual site that contains the lists to be exported, and the list itself.

ExportSharePointSite11a     The next screen contains a whole host of boxes, but we’ll only touch on a few of the more important ones.  Obviously you’ll want to specify a Name and Description for starters.  Next take a look at the Type (first red box below) box.  The value will typically be the base list template id that your list is already inheriting from.  Read this post for a little explanation on each template id.  As you’ll see, 100 is the generic list template id.  Since we’re trying to create a new list template, you’ll want to create a unique id.  I typically choose values above 10000 since the out of the box list template id’s don’t currently go that high.  Feel free to come up with your own system.

The other box I’ll highlight is DisallowContentTypes.  If you’re using content types on your list (and I recommend doing so for organization and consistency sake,) then you’ll want to pay attention to this later on.  I haven’t found a way to set this during the export process, so we’ll take care of that after placing it into our feature later on. ExportSharePointSite11b

Referring to our picture from part 2 on the solution layout, you’ll want to take your output files and place them into your solution as seen below.

ExportSharePointSite8c    Next, open the elements.xml file.  First thing to notice is that I have added some additional markup that you won’t find in the output from our list template creator.  I’ve added <ListInstance> and <Module> nodes so that my list template is instantiated within my feature.  Feel free to model your file similarly, but not necessary.  Lastly, make sure the Type (and TemplateType if you add the list instance) value is a unique value.

ExportSharePointSite11c

Next, open your feature.xml file.  The only modification I have done here is make the feature scoped to the web since a list lives on an individual site (web) instead of at the site collection (site) level.

ExportSharePointSite11d     The last (and probably most important) file is the schema.xml one which defines the infrastructure of our list.  As you’ll see below, I’ve outlined the addition of two key pieces.  First is the EnableContentTypes attribute of the <List> element which has been set to True so that we can have custom content types.  The second highlighted piece is the definition code for our custom content type.  Don’t worry if you don’t have (or know how to get) that XML snippet.  I’ll be covering that in part 4 of this series.  For now though, you have a rough sketch of your list template.

ExportSharePointSite11e     As a quick aside, I’ve noticed one thing by working with the schema.xml (and onet.xml from the site template in part 1) file very frequently.  When I need to make a change to these files (add a fieldref, change view query, etc) I’ve become faster and more efficient at editing the raw file versus updating through the UI and exporting a new copy.  Reminds me of my time working with Unix and VI at a previous job.

So there we have it, second piece of our site template exported into our feature.  Part 4 will be focusing on exporting site columns and content types.  In the past that used to be a very complex and hard to manage portion of the process, but with new tools that is not the case anymore.  Stayed tuned for that installment and in the meantime post and comments or questions you may have.  Thanks for tuning in.

-Frog Out