FBA Configuration Manager for SharePoint 2013

Nothing really earth shattering here – the previous version of FBA Configuration Manager for SharePoint 2010 (http://blogs.technet.com/b/speschka/archive/2010/07/28/sharepoint-2010-forms-based-authentication-configuration-manager.aspx) won’t deploy directly to SharePoint 2013 so the attachment to this post includes a new version compiled the latest version of SharePoint.  It also includes the late breaking fix for random errors about the Xml node belonging to a different parent.  The process for configuring FBA in SharePoint 2013 is the same as it was in 2010, so this tool still has a purpose in life.

You can download the attachment here:

 

Advertisements

FBA Sites with Office Hub in Windows Phone 7

Hey all, just wanted to give a quick but important update to the post on integrating SharePoint 2010 with Windows Phone 7 (http://blogs.technet.com/b/speschka/archive/2010/11/21/some-windows-phone-7-and-sharepoint-2010-tips.aspx).  After playing around with this some more and reviewing some of the tips left in the comments by our friend Tomislav, I got the right combination of things to get the Office Hub in Windows Phone 7 to open an FBA site. 

There were two keys to making this work as it turns out:

  1. You must secure your FBA site with SSL.  If you don’t have SSL then you won’t have joy.
  2. You must use a fully-qualified domain name for the zone.  For example, https://foo will NOT work.  However, https://foo.contoso.com WILL work.  This was the important distinction I found in my testing.

Hope this clears up some of the ongoing confusion around Office Hub support for FBA sites in SharePoint 2010.  Thanks to all the folks who commented on the previous thread; I think it’s been very helpful to everyone that’s trying to figure this all out right now.

Writing A Custom Forms Login Page for SharePoint 2010 Part 1

In SharePoint 2007 writing a custom login page for a forms based authentication (FBA) site was not too terribly hard.  There were a few things to know, most of which weren’t SharePoint specific, and some tips to have your login form take on the look and feel of a standard SharePoint layouts page.  Overall though, if you knew ASP.NET and the FormsAuthentication class you were good to go.  As luck would have it, things get somewhat more complicated in SharePoint 2010. 

In this post we’ll walk through one scenario of a custom login page.  In this example we decide that we need an entirely custom login page – we’re not just changing the look and feel, we require an entirely different UI.  For example, maybe we need to grab the Membership credentials that are used to log in, and then maybe we need someone to enter a secondary authentication ID, like you might have with SecurID.  In that case we’re going to have a couple of text boxes on an ASP.NET page for username and password and we’ll need to take those and programmatically log our user in.

The most important point to remember here is that your old friend, the FormsAuthentication class, will no longer be used.  The reason for that is because in SharePoint 2010, FBA users are actually claims users.  So while you may think you’re working with a standard ASP.NET Membership user and Role provider, under the covers those objects have a shiny claims authentication shell.  Because of that, we need to use some of the SharePoint claims classes to work through the FBA login process.

I need to add one caveat here!  Normally through one way or another, before I post something on my blog I either know or validate as best I can with someone that yeah, this is the right / blessed / supported way of doing something.  In this case, I tried repeatedly to get this approach vetted but was unable to do so.  I have used this code for a project I was working on and it does work, but I don’t want someone going into cardiac arrest if the code police tell you at a later date that you need to modify it to meet some other better / more appropriate way of doing things.  So enough with the CYA, let’s just look at some code.

Before we get started there’s a couple of references we’re going to need that you probably haven’t used before.  The first one is Microsoft.SharePoint.Security.dll, and it’s in the 14 hive in the ISAPI folder.  The other one is trickier, and primarily why I gave my caveat above.  You need a reference to Microsoft.SharePoint.IdentityModel.dll.  However, if you go to add references you won’t readily find this assembly, and thus my source of being slightly embarrassed and wary at the same time.  As I described in another post, the best thing I found to do is find it on the file system, copy it to an easy to find location, and add your reference to the copied version.  The way I usually do that, ‘cause I’m old school I guess, is I go to a command prompt, change to the root of the drive and do a “dir Microsoft.SharePoint.IdentityModel.dll /s” and find it that way.   Once you have that, you’ll probably want to add a little gaggle of using statements:

using System.Web.Security;

using System.IdentityModel.Tokens;

using Microsoft.SharePoint;

using Microsoft.SharePoint.IdentityModel;

So now that we have that bit of awkwardness out of the way, when I call into the claims class to validate the FBA user credentials the user typed in I need to tell it what Membership and Role provider it should use.  It just needs a name is all.  In my particular case I had written a custom Membership and Role provider for what I was doing, so I just enumerated through all the providers my web application knew about until I found mine:

//get the provider names for our type

string userProviderName = string.Empty;

string roleProviderName = string.Empty;

 

//get the membership provider name

foreach (MembershipProvider p in Membership.Providers)

{

if (p.GetType().Equals(typeof(Microsoft.SE.AnonProvider.Users)))

       {

       userProviderName = p.Name;

              break;

       }

}

 

//get the role provider name

foreach (RoleProvider rp in System.Web.Security.Roles.Providers)

{

if (rp.GetType().Equals(typeof(Microsoft.SE.AnonProvider.Roles)))

       {

              roleProviderName = rp.Name;

              break;

       }

}

 

Okay, great, I got my provider names.  Now we need to take the username and password and get back a SecurityToken.  In order to do that, we’re going to use the SPSecurityContext class.  It has a method designed just to do this forms based auth login for us; if it’s successful it returns a SecurityToken – if not it returns null.  Here’s what it looks like when we authenticate the user credentials:

SecurityToken tk = SPSecurityContext.SecurityTokenForFormsAuthentication(

new Uri(SPContext.Current.Web.Url), userProviderName, roleProviderName,

              UserNameTxt.Text, PasswordTxt.Text);

 

So I’ve passed in a Uri for the site I’m trying to authenticate against, I’ve told it the name of my membership and role providers, and I’m passing in the username and password values that were typed in the textboxes in my login page.   Now I need to check to make sure that my SecurityToken is not null, and if it isn’t I need to write a session token.  That is done with the SPFederationAuthenticationModule.  Once I’ve written my session token then I can go ahead and redirect the user to whatever page or resource it was that they requested.  Here’s the rest of the code that does that:

if (tk != null)

{

//try setting the authentication cookie

SPFederationAuthenticationModule fam = SPFederationAuthenticationModule.Current;

fam.SetPrincipalAndWriteSessionToken(tk);

 

       //look for the Source query string parameter and use that as the redirection

       string src = Request.QueryString[“Source”];

       if (!string.IsNullOrEmpty(src))

       Response.Redirect(src);

}

else

{

StatusLbl.Text = “The credentials weren’t valid or didn’t work or something.”;

}

 

Now you see when I’ve successfully done everything then I just grab the Source query string parameter because it tells us where the user was originally headed.  Once I have that I just send them on their way.

Hopefully this helps you get going.  I know it was a real struggle to find the documentation on how best to do this when I was looking for it.  In part 2 we’ll look at doing this a different way for a different scenario.  In that well want to have someone sign an “I agree to the terms of use for this website” thing before they use the site the first time.  To do that we’ll look at extending the base login page and adding a handler at login time. 

SharePoint 2010 Forms Based Authentication Configuration Manager

I found myself getting really tired of constantly modifying configuration files when setting up forms based auth (FBA) in SharePoint 2010.  There’s even more work now then there was in the previous release, because now we have an additional web.config file to modify – for the STS.  It was also a constant hassle when you fat finger some random part of a web.config change.  So, rather than continuing to complain about it, I wrote this little tool to help manage it for you.  You should read through the complete HowToUseIt.txt file that’s included in the zip attached to this posting, but basically it allows you to create the entries for membership provider, role provider, wildcard search and connection string and push it out to all of the servers in your farm.  You can also read in the configuration settings from a web application and modify them, then push it back out to the same server, or use it as the basis of settings for a brand new server.  To get you started, I also include several sample membership and role provider configuration entries.  Just select the samples drop down and pick the item you want to create an entry for.  Modify the entry to suite your environment, provide the Url to the web application where the configuration changes should be made, and click the Apply Config button.  Under the covers it creates a custom SharePoint timer job that runs on each web front end and modifies the appropriate web.config file with the appropriate entries.  The timer job is part of a solution (wsp) that’s included in the attachment – make sure you deploy it to the farm first before doing anything else.

I STRONGLY encourage you to make a backup of your central admin, STS, and web application web.config files before pushing out changes in case something happens you don’t like.  I’ve tested this on quite a few web applications and in single server and multi-server farms so far without problems, but you never know.

It’s already saved me a lot of time and hassle, hope it provides some value for you too.

 

UPDATE 6/15/2012:  I finally reproduced the error about node belonging to a different document context, and have fixed that.  A new build with that fix is attached.  Thanks for those of you that reported it.

You can download the attachment here:

Using the Client Object Model with a Forms Based Auth Site in SharePoint 2010

One of the questions I’ve seen a few times since my “mega-posting” on the client object model, is how to use it with a SharePoint site that is secured with forms based authentication.  There are actually a couple of ways you could do this.  The more complicated approach that I won’t describe in great detail here is to use the Authentication web service, similar to how I described for SharePoint 2007 in my Forms Based Authentication whitepaper part 2.  Fortunately though, the folks designing the client OM baked in a much simpler way to do this.  The ClientContext class includes an AuthenticationMode and FormsAuthenticationLoginInfo properties to help you manage this.

Here’s an example of using them to get a list of all the lists in the site.  Note this doesn’t follow the advice that I gave in one of the other client OM posts about specifying the properties you want returned, but I just wanted a quick and simple example to demonstrate:

ClientContext ctx = new ClientContext(someSiteUrl);
ctx.AuthenticationMode = ClientAuthenticationMode.FormsAuthentication;
ctx.FormsAuthenticationLoginInfo = new
                    FormsAuthenticationLoginInfo(myUserName, myUserPwd);

//get the web
Web w = ctx.Web;

//LOAD LISTS WITH ALL PROPERTIES
var lists = ctx.LoadQuery(w.Lists);

//execute the query
ctx.ExecuteQuery();

foreach (List theList in lists)
{
        //do something here

}

P.S. As a side note, are you all noticing how much the formatting in these posts STINKS since they upgraded the site?  How unpleasant…