Seems like I haven't had a chance to write a good SharePoint / SAML claims kind of article in a while. I was happily plugging away on some code this weekend for a scenario I haven't done before so I thought I would go ahead and post it here for the search engines. The whole topic in general has kind of reached a point where I'm not really sure if anyone even needs these kinds of postings anymore, but ultimately I decided it's worth jotting down because there will probably be someone, somewhere that needs to do this in a hurry so perhaps this post will help.
So the topic today is changing the configuration of a web application zone so that it uses an SPTrustedIdentityTokenIssuer – i.e. I want to configure my web app to use SAML claims.
The first challenge I typically face with folks is getting them to restate the problem – more precisely, in this case we're not configuring a web app to use SAML, we're configuring a zone in the web app to use SAML. This is a key to remember because you need to know that as you start plugging through the object model to find and change these settings. So let's start working through some code.
The first step of course is going to be to get a reference to the web application you want to work with. You can use the ContentService to do that, or I frequently just use a site. Here's an example:
using (SPSite s = new SPSite(https://foo))
SPWebApplication wa = s.WebApplication;
Okay, so now that I have my web application, I need to get the IIS settings for the zone. In this case I'm just going to hard-code it to look in the default zone:
Dictionary<SPUrlZone, SPIisSettings> allSettings = wa.IisSettings;
SPUrlZone z = SPUrlZone.Default;
SPIisSettings settings = allSettings[z];
As you can probably tell from the code, you can get the settings for any zone, but we're grabbing them for the default zone. Once I have that, I can look at what authentication providers the zone is using with this:
List<SPAuthenticationProvider> providers = settings.ClaimsAuthenticationProviders.ToList<SPAuthenticationProvider>();
So for example if you wanted to see if your provider was being used before trying to add it, this is where you would look. In our case we'll just assume it's not being used by this zone yet, so next we need to get the SPTrustedClaimProvider that represents our SPTrustedIdentityTokenIssuer. We'll use this code to do that:
//get the local claim provider manager, which tracks all providers and get all trusted claim providers into a list
SPClaimProviderManager cpm = SPClaimProviderManager.Local;
List<SPTrustedClaimProvider> claimProviders = cpm.TrustedClaimProviders.ToList<SPTrustedClaimProvider>();
//look to see if ours exists
const string ISSUER_NAME = "MyTokenIssuer";
var cp = from SPTrustedClaimProvider pd in claimProviders
where pd.DisplayName == ISSUERI_NAME
SPTrustedClaimProvider ceProvider = null;
ceProvider = cp.First<SPTrustedClaimProvider>();
//it will throw an exception if it doesn't exist
Okay, so at this point our provider should be in the ceProvider variable. Once we have that, we have a couple of different options to configure the zone to use it. If you just want to add it to the collection of authentication providers the zone is using, use the AddClaimsAuthenticationProvider method of the IisSettings instance. If you want to replace the list of authentication providers so it only uses your SAML provider (which also means it can't be crawled, since that requires NTLM), use the ReplaceClaimsAuthenticationProviders method. Here's some code that demonstrates both methods, you would obviously only use one of them:
if (ceProvider != null)
SPAuthenticationProvider newProvider = new SPTrustedAuthenticationProvider(ceProvider.Name);
//this works to add it to the collection of claims providers
//this can be used to replace it so you only have the trusted provider
providers = new List<SPAuthenticationProvider>();
//update the web application to save the authentication provider settings
So there you have it, hopefully if you ever need to do this now you can grab this code and run with it.