paupdb posted on Thursday, August 14, 2008
I've had some fun whilst working on the above topic.
Basically I have an existing ASP.Net Forms authentication setup that I wanted to integrate with a Silverlight application which uses CslaLight + CSLA3.6.
I set the WcfPortal service to run with ASPNetCompatibility mode (was relieved to see the ASPNetCompatibility attribute on the WcfPortal class btw), and then attempted to access HttpContext.Current.User from within one of my BOs on the server.
What was interesting was that I kept getting a Csla.Security.UnauthenticatedPrincipal back when debugging the HttpContext.Current.User - clearly not my FormsIdentity.
After trying a whole bunch of different configuration options in the ServiceReferences.clientconfig and the web.config, I then stumbled upon some of the code in the DataPortal client implementation where a ApplicationContext.User is serialised automatically in the BeginFetch routines.
I realised that every call to the WcfPortal would send the ApplicationContext.User too,
and when there isnt a ApplicationContext.User set, then a blank one (UnauthenticatedPrincipal) is sent.
Now this causes me a problem, because I am relying on the server to initially provide the SL client back with an authenticated principal following a "start-up" BO call through the DataPortal (the server code would access the Forms authenticated principal and then load a CSLA principal for that Forms authed user), rather than the usual case of the SL client providing the server with their username and password through a login screen in the SL app.
After getting back the CSLA principal once, then that would be kept in the SL client and I would use that principal going forward.
The CSLA client behaviour isnt necessarily an issue on its own, however when combined with the fact that on the server side the ApplicationContext.User is set to the deserialised one just received over the wire, then I immediately saw my issue.
This is because in Csla.ApplicationContext, the following code exists:
public static IPrincipal User
{
get
{
if (HttpContext.Current == null)
return Thread.CurrentPrincipal;
else
return HttpContext.Current.User;
}
set
{
if (HttpContext.Current != null)
HttpContext.Current.User = value;
Thread.CurrentPrincipal = value;
}
}
So yeah, because a ApplicationContext.User is always sent over the wire from the SL client to the server, I lose my FormsIdentity.
Now I know this CSLA behaviour is by design, so I'm not looking for a framework change.
I have found a way around this by using a custom IAuthorizationPolicy
with the WcfPortal service, using
this excellent blog post as my guide. By creating a HttpContextIdentityPolicy of my own, I am able to intercept the HttpContext.Current before CSLA gets its hands on it, and thus the policy is able to copy the HttpContext.Current.User into ServiceSecurityContext.Current.PrimaryIdentity.
I can then access my Forms authenticated user through ServiceSecurityContext.Current.PrimaryIdentity in my BO :)
Whew!
Anyway this is just for people's interest and maybe someone has found a better way to do this?
Also Rocky, you may want to be aware of this admittedly small side effect of having the CSLALight client serialise a blank ApplicationContext.User when one has not been explicitly set by the UI code.