Skip to content

June 24, 2007

Hints for Membership Providers (Authentication Providers) with SharePoint

I’ve done work with membership providers more than a few times now and I have developed a love-hate relationship with them within the context of SharePoint.  It’s not that membership providers don’t work.  They do.  You can absolutely make them work.  However, it’s also true that there are a lot of landmines in the way.  I wanted to provide a few of my experiences with Membership providers that may be helpful for you…

  1. Don’t start with SharePoint – If you’re going to work with Membership Providers in SharePoint – don’t start there.  Build a simple ASP.NET application that has a secure home page.  Make a login page.  Test your membership provider and its configuration settings in ASP.NET first.  Why?  There are less moving parts.  You can run an ASP.NET web site in debug mode by pressing F5.  You don’t have to deal with all of the other things that are going on inside SharePoint.  The fact that first chance exceptions work in ASP.NET (they don’t in SharePoint) you can try to capture the exceptions as they happen.  (If you don’t know about First Chance Exceptions you can go here.)
  2. Build a Shell – Even if you’ve tested the membership provider in ASP.NET there are reasons why SharePoint is different.  Instead of running with the local account you’re running within the context of the application pool.  Because of this you need to be able to see what’s happening between SharePoint and the Membership Provider.  You may need to see all of the call parameters and the return values – and even the exceptions.  So build yourself a passthrough provider which will log the calls, the responses, and the exceptions.  It will make figuring out what’s happening much easier.  (I have a version.  If you want a copy send me an email and I’ll send you a copy of it.  Better yet, if you’re willing to help review it and get it up on CodePlex let me know.)
  3. People Picker is Evil – The people picker is evil.  You’re supposed to be able to specify the provider to use when selecting a user (myProvider:TheUser).  Sometimes that actually works.  It works if you’re in the zone where the provider is the default, but doesn’t always work outside of that.  Add to the problems with the People Picker that you need to remember to add the search wildcard to the entry in the web.config.  So if you are getting stuck adding permissions… start with adding a Policy for the Web application (see Steve Peschka’s post on the SharePoint Products and Technologies team blog titled “Configuring Multiple Authentication Providers for SharePoint 2007”)
  4. Don’t ask everything of the membership provider – One of my clients wanted to login via email address in active directory – and not their UniquePrincipalName.  Although this is technically possible by using the LDAP provider, that may not be the best answer.  It may make more sense to modify the login page rather than trying to get the membership provider to log in on a field other than the ones that it’s used to logging in with.  In fact, on a scale of difficulty modifying the login page is must easier than mucking with membership providers.  I’ve got a forthcoming article on how to create a custom login page for SharePoint. I’ll add a link here when the article goes live.

 

Good luck on your work with membership providers…

System.DirectoryServices.Protocols (a.k.a. LDAP is your friend)

I’ve had the displeasure of trying to do some work with LDAP in .NET lately.  The interfaces are all there but the documentation and error handling isn’t.  (Read: The lights are on but no one is home.)  Because of this I was pleased to find there was a book out on the subject The .NET Developers Guide to Directory Services by Joe Kaplan and Ryan Dunn.

I also had the pleasure of sharing an email conversation with Joe.  I initiated a conversation with him slightly before I was able to pickup the book – because of his activity in the newsgroups.  I quickly figured out I needed to pick up the book and did.  I highly recommend it because the information that is contained in it is both unique — because it doesn’t exist elsewhere — and is easy to understand.  LDAP may be common but it’s not something that most developers do every day.  Back to my point, there were some interesting things that came out of that conversation.  I wanted to highlight them in part to document them and in part to thank Joe for his help.

1) System.DirectoryServices vs. System.DirectoryServices.Protocols – What I was trying to do was to develop a high performance LDAP ASP.NET 2.0 Membership Provider for a project.  In order to do that, I was going to be using LDAP to authenticate a large number of users.  One of the issues with System.DirectoryServices is cleaning up all of the connections quick enough in a high load environment.  The net of the conversation with Joe – which I agreed with wholeheartedly as I began to understand the underlying characteristics of System.DirectoryServices – was if you need to control cleanup of connections use System.DirectoryServices.Protocols.  The end I came to was that I think of System.DirectoryServices as a façade over System.DirectoryServices.Protocols.  Façade is a pattern that makes using something easier.

2) SSL is not your friend – There are lots of things to think about when trying to use SSL to encrypt your LDAP communications.  First, if you are using clients all in a domain, add an Enterprise Certification Authority to the domain.  If you do that the domain controllers will enroll themselves and start accepting SSL connections for LDAP – that’s cool.  If you don’t have all internal clients, you can refer to this KB article to add a third party certificate.  Even with it working (and tested via LDP) you may have a problem when you try to set SecureSocketLayer support.  You may receive a less than helpful DirectoryOperationException(“The server cannot handle directory requests.”) what isn’t quite so amusing about this is that it didn’t even try to communicate with the server.  The solution was to add the port number to the server.  So instead of passing “Server” to open the LdapConnection, I passed “server:636”.  By the way, LDAPS is port 636 – rather than the 389 port used by LDAP.

3) Fast Concurrent Bind isn’t really a bind – In LDAP you bind to associate credentials to your connection so that it can use those credentials to validate your operations.  One of the things that S.DS.P supports is the idea of a Fast Concurrent Bind.  Basically, check my credentials to make sure that they’re OK – and don’t do anything else.  I tried using Fast Concurrent Bind (because it is the fastest way to validate a user) to bind to a connection and then do a search.  So I did my bind and then did my search.  When I tried the search I got an exception – DirectoryOperationException(“An operation error occurred”) when I dug into the network capture I found a deeper message: “LdapErr: DSID-0C090627, comment: In order to perform this operation a successful bind must be completed on the connection., data 0, vece”  It was funny because message 5 was a bind with a success response and message ID 6 – the one I got the error on was a search.  The issue at the end of the day I was I was using fast concurrent bind.  So I wasn’t really doing a full bind at all.  I was just authenticating the user.

With Joe’s help I was able to figure out what the issues were … and create a working solution.

Recent Posts

Public Speaking