Integrating Custom Authentication into WCSF

Topics: User Forum
Aug 23, 2007 at 3:16 PM
I need help in wrapping my head around how to integrate the Web Client Software Factory with a custom Authentication provider.

The company I work for has implemented a web single sign on for all their internal web sites. When I need to authenticate a user, I redirect the request to another server, and once authentication has completed, the request comes back with a token in the querystring. I validate that token by posting back to the authentication server. For all the applications I've written prior to looking at the WCSF, I've used an HttpModule that I wrote that integrates this single sign on concept nicely into ASP.NET.

It would not be too hard to muck around in the web.config of a WCSF generated site and shoehorn my authentication module in. But that does not sound like the best answer. I'd like to refactor my code to better fit the architecture of WCSF.

Does anyone have some suggestions for me? Is this just a foundational module? Or since this needs to be an HttpModule, is this not so simple?
Aug 24, 2007 at 5:46 PM
Edited Sep 1, 2007 at 11:08 PM
I think the HTTP Module is a great approach, if it works don’t fix it. The web.config generated by WCSF is standard config stuff. It may look intimidating at first, but you should feel free to plug in your own http modules, providers, ent lib config etc.

Another approach to look at may be implementing your own asp.net membership provider, then call out to your SSO service. Here is a quick and dirty example.

http://www.15seconds.com/issue/050216.htm

One thing I like about this article is that he notes the two real important methods to implement are Initialize and ValidateUser. So if you go down this path, don’t feel like you have to implement the whole provider, create a MembershipUser etc, just to authenticate with your service.

I would use the HTTP module ;) Do you have to authenticate every request? Are you using forms auth? Are you putting a custom principal on the thread?

Jarod Ferguson

Dec 13, 2007 at 4:36 PM
Hi.

A possible solution could be create a custom AuthorizationService provider (inheriting from Microsoft.Practices.CompositeWeb.Interfaces.IAuthorizationService interface).

Here, you must implement the IsAuthorized method to manage your own authorization rules.

This custom AuthorizationProvider replaces the one registered in the ShellModuleInitializer class:

protected virtual void AddGlobalServices(IServiceCollection globalServices)
{
   globalServices.AddNew<CustomAuthorizationService, IAuthorizationService>();
 
   // globalServices.AddNew<EnterpriseLibraryAuthorizationService, IAuthorizationService>();
   // …
}

Also, you can read the following post from WC-SF Documentation:
  • Authorization (Inspecting the Software Factory Assets->Application Blocks->Composite Web Application Block->Design->Authorization)
  • ModuleSiteMapProvider (Inspecting the Software Factory Assets->Application Blocks->Composite Web Application Block->Design-> ModuleSiteMapProvider)

And, you can see in the CompositeWeb solution (WC-SF source code), in the WebClientAuthorizationModule class how to WC-SF handles the AuthorizeRequest event:

public void Init(HttpApplication httpApplication)
{
   ICompositionContainer rootContainer = httpApplication.Application[ApplicationConstants.RootContainer] as ICompositionContainer;
   if (rootContainer != null)
   {
      httpApplication.AuthorizeRequest += delegate(object sender, EventArgs e)
      {
         IHttpContext context = new Microsoft.Practices.CompositeWeb.Web.HttpContext(httpApplication.Context);
         HandleAuthorization(rootContainer, context);
      };
   }
}
 
protected virtual void HandleAuthorization(ICompositionContainer rootContainer, IHttpContext context)
{
   if (context.SkipAuthorization) return;
   IAuthorizationRulesService authorizationRulesService = rootContainer.Services.Get<IAuthorizationRulesService>();
   IVirtualPathUtilityService virtualPathUtility = rootContainer.Services.Get<IVirtualPathUtilityService>();
   if (authorizationRulesService == null) return;
   string[] rules = authorizationRulesService.GetAuthorizationRules(virtualPathUtility.ToAppRelative(context.Request.Path));
   if (rules == null || rules.Length == 0) return;
 
   IAuthorizationService authorizationService = rootContainer.Services.Get<IAuthorizationService>(true);
   foreach (string rule in rules)
   {
      if (!authorizationService.IsAuthorized(rule))
         {
            throw new HttpException(403, Properties.Resources.UserDoesntHaveAccessToTheRequestedResource);
         }
   }
}

Thanks.

Sebastian Iacomuzzi
http://staff.southworks.net/blogs/siacomuzzi