I am investigating how to do custom authentication in my CSLA application. I understand that the Principal object is passed from client to server (and back) on every request. What I don't understand is, assuming a login has taken place and the Principal/Identity is marked as authenticated, why the server trusts the Principal object on all subsequent requests. Wouldn't it be easy for someone to write a 'fake' client where it sets the Principal as authenticated and pass that in? What am I missing?
If you decide to go for "mobile objects" pattern - this implies that you trust your clients to do authorization.If you do not trust your clients you should use WCF, RIA Services of OData to expose your data and do your own authorization there.
And to protect your app you should use signed assemblies and not allow modifications to your custom identity/principal objects.
I'm using CSLA over WCF. Are you saying that I should be implementing some type of WCF authentication rather than the CSLA custom authentication, and that the latter is only for trusted clients? I'm wondering how any server software can trust its clients (even inside the firewall someone could write a program to access it). But I guess if I check on each call that my principal/identity is of my custom class, and I don't allow instantiation of that class unless it has been authenticated, then no one should be able to spoof it.
Perhaps that's what you meant about not allowing mods to the identity/principal object.
I think there are some things that you can do incrementally to raise the bar for potential hackers.
I think we'll see more and more of this discussion as Silverlight apps pick up in terms of securing an application.
I guess there are two aspects:
1) keeping the source away from non-clients or non-trusted people.
For XAP files, it might be putting it within an ASP.Net site with forms authentication such that a user must be authenticated prior to even getting to your XAP.
One can also use Obfuscation to provide an extra layer of defense to simply make it harder for the casual pest. DeepSea was pretty intuitive. .NET Reactor wasn't as clear to me. I was under time pressure and just tried another tool (DeepSea) as a result.
Sign your assemblies.
2) mitigating clients who have your code and have malicious intent. (I suppose this is where the compromised principal object comes into play)
I think if one were to basically encrypt/hash a token on the principal/identity that includes the identity of the user, it would seem to me that you know that the principal is one you created (at least the portions which you include as a check in your encrypted token).
If permissions are being serialized within your object, I guess there are two ways to do this - take your principal (that you can verify the identity through a token) and reload the permissions. Another possibility might be to create a salted hash of the permissions and verify that the permissions validate against that salted value when dataportal requests are made.
I would love to hear other ways people are going about securing their applications without dismantling the single application approach. If anything I've stated is flat-out wrong, please correct me.
First, if you don't trust your clients then you should use SOA. You should be creating two completely separate apps - one on the server and one on the client. You should assume all aspects of the client app have been compromised, and construct the server app to be exceedingly paranoid. The best way to accomplish this is to hire a game developer from one of the major MMORPG firms (Sony, etc), because they are the global experts on this problem space. The problem space, btw, is extremely complex and is nearly impossible for normal people to comprehend, much less resolve. We're talking low level byte hacks, replay attacks on the network, man-in-the-middle scenarios. All sorts of nasty stuff. Bad guys are very determined and very smart and (assuming you are a valuable target) they have nearly unlimited budgets.
Second, if you really look at this in any detail you must do THREAT analysis. It is nearly impossible for normal business apps to justify the expense of the sort of security required by online games, game consoles or the military. Defeating the threat posed by actual hackers is insanely expensive.
Third, defeating the threat posed by non-hackers isn't so bad. Most business apps can actually afford that cost - but again, THREAT analysis is required to determine your cost threshold. And if you don't trust your client you shouldn't be doing n-tier architecture, you should be doing SOA. Yes, SOA is much more complex and expensive than n-tier, but it is the architecture that addresses the untrusted client.
Fourth, there are middle ground solutions. If you "sort of don't trust" your client, and don't want to incur the expense of SOA, you can strengthen your principal object (for example). That's a low-hanging fruit solution. Just have the server create an encrypted token that includes the hash signature (SHA256 probably, as SHA1 has been cracked) with a sliding expriry period and put that into Csla.ApplicationContext.GlobalContext. This is encrypted using a symmetric key known only to the server.
You can create an implementation of IAuthorizeDataPortal that runs before any other server code. This can decrypt the token, and can calculate a signature for the principal that came with the request. If the two signatures match (the new one and the recorded one from the token) and the token hasn't expired, then all is still good. Update the timestamp and re-encrypt the token so the expiry window slides.
It is a little complex, but not too bad. And there's a little perf hit, but probably not too bad (symmetric encryption and signing isn't terribly slow).
The cool thing is that you can also implement (if you want) additional functionality in the token to prevent replay attacks. That requires more work yet, as the server needs to keep track (in some manner) which tokens it has seen, so it can reject any token it has already seen. I am not an expert on that, so there may be other options, but the one I know if requires (sadly) maintaining some server-side state with the expected inbound value for the next token. Of course server-side state is hard to manage efficiently, but this is a decent solution to prevent replay scenarios.
Man-in-the-middle is best prevented by using SSL. Other techniques exist too, but SSL is already there and already does it correctly (assuming you have a real cert issued by a real CA), so it is by far the best answer.
Copyright (c) Marimer LLC