>
Blog
Book
Portfolio
Search

9/1/2010

11202 Views // 0 Comments // Not Rated

Configuring Custom Providers Using SharePoint 2010 Claims Based Authentication

Introduction

For those of you who have been with me since the beginning, you'll remember the first major accomplishment I made in the SharePoint space: The Hybrid Provider. This little puppy is a custom authentication provider for SharePoint 2007 that allows simultaneous authentication, authorization, and profiles for both Active Directory and Forms (SQL) users against the same web application. This made a big splash, as not only was the ASP.NET provider infrastructure new in the 2.0 timeframe, but making it work with SharePoint was a very difficult challenge.

And as we all migrate over to 2010, we explore the familiar paradigm of transitioning our expertise from the old tried-and-true techniques to the new and exciting ones. I am always interested to see functionality that used to require a ton of customization to work the way you wanted it to now magically working out of the box. Would custom authentication be gobbled up by SharePoint 2010, thus rendering the Hybrid Provider retired?

Well the answer is...sort of. There's this new "Claims" thing, replacing, at least semantically, "Forms" authentication, and bringing with it a new architecture for authentication. Gone are the days of having to extent your web app to another zone if you wanted to implement an out of the box extranet. What happens now is a "pre-login" page that gives you a drop down to select the authentication mechanism (namely, Windows or Forms), and based on that selection, the AutoPostBack on the drop down will either pop up the Windows NTML dialog or redirect you to the login page.

Although it's cool to see "first class citizen" support for dual authentication, this extra step is still a kludge, and therefore there's still room for the Hybrid Provider. However, this post isn't about the Hybrid Provider, mainly since the MembershipProvider abstract class hasn't changed in .NET 4.0; the old code will still work in SharePoint 2010. The difference, however, is in the configuration and architecture that a custom authentication has to adhere to in the new environment. Therefore, I instead want to talk about how to get this stuff working in general, weather you're using the out of the box SqlMembershipProvider, the Hybrid Provider, or your own creation.

This gives us two topics to discuss. First, we need to understand the new Claims-based Authentication at a high level, and then dig into the nitty-gritty details of what you need to do to get your provider all wired up.

SharePoint 2010 Claims Authentication

Following the paradigm shift from SSPs to Service Applications, authentication has been "offloaded" to the "Security Token Service Application." The "STS" (as it's known) is one of those service applications that has no configurable properties. (When you select it in Central Admin, the "Properties" and other Ribbon options are disabled.) This is, as far as I'm concerned, both good and bad: good because there's nothing extra there to break; bad because there's nowhere to go to fix it when it indeed is broken.

Behind these ominous scenes, the STS is just a WCF service, hanging out in "14\WebServices\SecurityToken." They way this works is that SharePoint routes all authentication through this service. Whenever anyone logs into anything, STS is the mechanism giving users the nod. Now, the web applications are still operating as normal ASP.NET sites; authentication, authorization, forms, etc. (in terms of configuration) don't change. It's just that instead of code running the web app to do the work, a service call is made instead.

So architecturally, this is really the only big change. In 2007, each web app (Central Admin included) did its own thing for auth. 2010 has now integrated this into its service application layer, with all web apps plug into.

However there is one caveat that will lead us into the second part of this post which covers implementation. Even though the STS handles authentication, web apps are still on their own to implement all other user-centric functionality. The best example is the PeoplePicker. Despite the PeoplePicker depending on the very same mechanics as the STS' authentication and authorization do, it's not actually doing authentication or authorization; it's simply querying into these interfaces against our user store (weather it's AD, SQL, etc.).

What does this mean to us? Basically, when implementing custom authentication or authorization, the STS is what needs to be configured to talk to the ASP.NET MembershipProvider. However, any web app that needs to interact with these users, be it searching within a PeoplePicker, adding users to a group, or granting people Site Collection Administrator permissions in Central Admin, needs to be configured to use the authentication provider as well.

Just not for authentication.

So in SharePoint 2010 Claims-based Authentication, there are now three places you need to go to configure a custom authentication provider (verses just two in 2007): the web application itself (to allow permission and security functionality to work), Central Admin (to implement the provisioning of Site Collection Administrators and other more global user management tasks), and STS (which, again, is doing the actual authentication).

Before we move on to the implementation, I want to briefly discuss some semantics. As it stands, offloading authentication across the farm to the STS does not constitute "claims" authentication all the way. In claims (with a lower-case "C") auth, you provide your credentials to a third party "issuer" who authenticates you and gives you (or your session) a token. It is this token that you give to the actual site or application.

So STS is the first "half" of this paradigm. What about the token? That is abstracted to us, and SharePoint wires up its own "claims" provider that does this work for us. We're using claims auth without having to worry about anything beyond forms auth!

To summarize:

  1. Forms authentication is configured for the web app, so it knows to provide a login page to you.
  2. The login page passes your credentials to STS.
  3. STS uses our custom provider to authenticate you and issues back a token.
  4. This token is sent to the web app, which uses the SPClaimsAuthMembershipProvider and SPClaimsAuthRoleProvider to process the token and use it for final authentication and authorization respectively.
  5. The web app then uses the custom provider directly to power user-centric functionality, such as the PeoplePicker.

Implementing a Custom Claims Authentication Provider

So what do we have to do? Here's the good news: not much, from a technical perspective, has actually changed! Like I said in the previous section, the code is identical, so if you're migrating from 2007, just GAC your DLLs. As far as Central Admin is concerned, configuring the Authentication Provider for your web app basically mirrors what you had to do in SharePoint 2007. In fact, other than having to deal with a third web.config file, you still wire up your custom provider in pretty much the same way.

So the only new task we have is dealing with some of the nuances of what SharePoint 2010 needs. In 2007, once you got one web.config wired, you could copy-and-paste it around. The major difference here is that each web.config file (STS, Central Admin, and each web app) varies slightly in what you have to do. So let's dive into that.

<Important Note>

Take very careful notice of the usage of <clear /> in the following web.config snippits. This is very important, and SharePoint 2010 requires it in certain scenarios.

</Important Note>

Web.config for Web Applications (In virtual directory)

  • Membership
    • Clear
    • Add SPClaimsAuthMembershipProvider
    • Add Custom Membership Provider
    • Set SPClaimsAuthMembershipProvider as the default
  • Role Manager
    • Clear
    • Add SPClaimsAuthRoleProvider
    • Add Custom Role Provider
    • Set SPClaimsAuthRoleProvider as the default

Code Listing 1

  1. <membership defaultProvider="i">
  2. <providers>
  3. <clear />
  4. <add name="i" type="Microsoft.SharePoint.Administration.Claims.SPClaimsAuthMembershipProvider, Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
  5. <add connectionStringName="AspNetSqlProvider" passwordAttemptWindow="10" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="true" applicationName="/" requiresUniqueEmail="false" passwordFormat="Hashed" description="Stores and retrieves membership data from the Microsoft SQL Server database" name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
  6. </providers>
  7. </membership>
  8. <roleManager defaultProvider="c" enabled="true" cacheRolesInCookie="false" cookieName=".ASPROLES" cookieTimeout="30" cookiePath="/" cookieRequireSSL="false" cookieSlidingExpiration="true" cookieProtection="All">
  9. <providers>
  10. <clear />
  11. <add name="c" type="Microsoft.SharePoint.Administration.Claims.SPClaimsAuthRoleProvider, Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
  12. <add name="AspNetSqlRoleProvider" type="System.Web.Security.SqlRoleProvider" connectionStringName="AspNetSqlProvider" applicationName="/" />
  13. </providers>
  14. </roleManager>
  15. <connectionStrings>
  16. <add name="AspNetSqlProvider" connectionString="Data Source=SHAREPOINT2010;Initial Catalog=TestProvider;Integrated Security=True" providerName="System.Data.SqlClient" />
  17. </connectionStrings>

Web.config for Central Administration (In virtual directory)

  • Membership
    • Clear
    • Add Custom Membership Provider
    • Set Custom Membership Provider as the default
  • (NO Role Manager)

Code Listing 2

  1. <membership defaultProvider="AspNetSqlMembershipProvider">
  2. <providers>
  3. <clear />
  4. <add connectionStringName="AspNetSqlProvider" passwordAttemptWindow="10" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="true" applicationName="/" requiresUniqueEmail="false" passwordFormat="Hashed" description="Stores and retrieves membership data from the Microsoft SQL Server database" name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
  5. </providers>
  6. </membership>
  7. <connectionStrings>
  8. <add name="AspNetSqlProvider" connectionString="Data Source=SHAREPOINT2010;Initial Catalog=TestProvider;Integrated Security=True" providerName="System.Data.SqlClient" />
  9. </connectionStrings>

Why no Role Manager in Central Admin? Well, because it doesn't work. The behavior I've seen is that, when you have a role provider configured in Central Admin, although you can log in to the site, certain links to interior pages challenge you for credentials, which then always fail. Take the role provider out and everything works again.

I don't have any good technical reasons why this is the case, but the only thing I can think of at all is that the role manager interferes somehow with the Windows auth. In the custom provider scenario, Central Admin is the only web app actually using OOTB authentication, so at least that makes sense given it's the only web app with no role manager configured.

Either way, this isn't a big deal, since we are not using a custom provider to log into Central Admin, and all user-centric functionality you'd do there doesn't really need a role manager. Personally, I only use Central Admin to grant the first SQL user Site Collection Administration permissions, so I can log into the actual web app as that user, and go all my group stuff there.

Web.config for STS (In 14\WebServices\SecurityToken)

  • Membership
    • Clear
    • Add Custom Membership Provider
    • Set Custom Membership Provider as the default
  • Role Manager
    • Clear
    • Add Custom Role Provider
    • Set Custom Role Provider as the default

Code Listing 3

  1. <membership defaultProvider="AspNetSqlMembershipProvider">
  2. <providers>
  3. <clear />
  4. <add connectionStringName="AspNetSqlProvider" passwordAttemptWindow="10" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="true" applicationName="/" requiresUniqueEmail="false" passwordFormat="Hashed" description="Stores and retrieves membership data from the Microsoft SQL Server database" name="AspNetSqlMembershipProvider" type="YMCAProvider.YMCAMembershipProvider, YMCAProvider, Version=1.0.0.0, Culture=neutral, PublicKeyToken=bf6b2d725b284803" />
  5. </providers>
  6. </membership>
  7. <roleManager defaultProvider="c" enabled="true" cacheRolesInCookie="false" cookieName=".ASPROLES" cookieTimeout="30" cookiePath="/" cookieRequireSSL="false" cookieSlidingExpiration="true" cookieProtection="All">
  8. <providers>
  9. <clear />
  10. <add name="AspNetSqlRoleProvider" type="System.Web.Security.SqlRoleProvider" connectionStringName="AspNetSqlProvider" applicationName="/" />
  11. </providers>
  12. </roleManager>
  13. <connectionStrings>
  14. <add name="AspNetSqlProvider" connectionString="Data Source=SHAREPOINT2010;Initial Catalog=TestProvider;Integrated Security=True" providerName="System.Data.SqlClient" />
  15. </connectionStrings>

Note that the connection strings are added for reference only; they do not belong in the System.Web section of course. Also, I used the SQL Membership Provider here as an example. You can do whatever is necessary to wire up your own provider. But that's about it! Hopefully this helps demystify not only one of the most intense configurations involved in a custom SharePoint component, but Claims authentication in general.

Have fun!

3 Tags

No Files

No Thoughts

Your Thoughts?

You need to login with Twitter to share a Thought on this post.


Loading...