Where in CSLA do I go to circumvent the Active Directory role checking?
If I'm programming disconnected from an Active Directory server, I would like to be able to go into just one function and tell it to return "sure, you've got the role" instead of having to disable the security checking in all the classes I'm working with.
I tried to find it but just plain got lost in the code...
MyBusinessIdentity.IsInRole?
Couldn't find that with a search on the CSLA Library code.
If you mean in each business object that I code, no way! This is just so I can work at home without having to alter a bunch of code just to get basic functionality up and running, then having to undo the changes before I check the code back in...
But I didn't create an identity class!
I'm just using the standard apply authorization rules code in the business objects using (I assume) the default CSLA features that implement that.
If I already knew how to do all that, I would agree with you. :)
But I don't, and my learning curve time is already over-allocated for this phase of the project.
Regardless, I would need to know what class/method in CSLA to delegate to, and that was my original question:
Exactly what piece of code in CSLA makes that active directory verification call?
CSLA doesn't do any Active Directory authentication. It defines a BusinessPrincipalBase class that you sub-class and implement your own authentication mechanism (either via a DB, Active Directory, etc).
If your application is doing Active Directory authentication, it's because someone (you or someone else) wrote the code to do so. Look for a class that is subclassed from BusinessPrincipalBase or that implements the IIdentity interface.
What I've done in several projects is create an SSPI wrapper that allows me to authenticate either against a domain or against my local machine for when I'm on the road. Once I authenticate, I load the user permissions from the DB.
Exactly. There has to be a principal defined somewhere in the project that is handling the active directory authentication and user roles. That's not supplied "out-of-the-box".
Overriding the IsInRole via conditional compilations statements will not necessarily solve the problem, though. It does eliminate any run-time role checking concerns but doesn't address the authentication problem.
If the code is truly authenticating against active directory, modify the Login() method in the principal object.
public static bool Login(string username, string password)
{
#IF DEBUG
Csla.ApplicationContext.User = <CREATE YOUR OWN CUSTOM PRINCIPAL>;
return true;
#ELSE
MyIdentity identity = MyIdentity.GetIdentity(username, password); //assumes this hitting an AD server
if (identity.IsAuthenticated)
{
MyPrincipal principal = new MyPrincipal(identity);
Csla.ApplicationContext.User = principal;
}
return identity.IsAuthenticated;
#ENDIF
}
We're working on putting in a custom principal and identity object.
But I have to tell you, I'm confused about all this!
When I work with my laptop connected to the network (and thus active directory), the code ran.
When I work with my laptop disconnected, all the IsInRole checks built into the business objects raise an error because ActiveDirectory isn't available.
So, silly me, I assumed it was working with ActiveDirectory by default.
It's not, because it's not disabling the editing buttons on the screen when I take away the necessary active directory role (and log in fresh afterwards).
So, by default, it doesn't appear to USE active directory, but it won't run without active directory!
That doesn't make a lick of sense to me... What's going on that I'm missing?
You need to look at your code. Do you have a Login() method that's called somewhere? If so, jump into that method to find how/where you're being authenticated. If it's against a SQL database on a remote server (not on your laptop), you will obviously have problems when you're disconnected from the network. If it's truly against an Active Directory or LDAP server (possible, but unlikely), we can look at that as well.
As I mentioned in a previous message, you need to search *your* project for a class that inherits from BusinessPrincipalBase. That's where the relevant authorization code will likely be found. If you can post the code here, we can help you diagnose your authentication issues.
There is no custom class in my project that inherited from BusinessPrincipalBase.
I didn't create one, and no one else did either. Really. :)
And, no, I didn't do a "login" to the application either. I just login to windows in the normal way and compile and run the application from visual studio.
The code is just like this:
protected override void AddAuthorizationRules()
{
AuthorizationRules.AllowWrite("Id", "ApplicationWriteRole");
}
and like this:
public static bool CanAddObject()
{
return Csla.ApplicationContext.User.IsInRole("ApplicationWriteRole");
}
When disconnected from the ActiveDirectory domain, the application runs fine until these code units are run, at which time it blows up.
When connected to the ActiveDirectory domain, the application runs fine and the objects act appropriately based upon whether I have the role or not.
We started writing a custom principle today, but I still don't understand why I get the behaviour I do unless it actually does support ActiveDirectory out of the box.
Ok - I looked a bit closer at the code in CSLA - ApplicationContext. If you're not calling your own login method and assigning a CustomPrincipal, it looks when you make a caller that access ApplicationContext.User, it will return whatever is sitting in Thread.CurrentPrincipal.
If you happen to be on a domain, Thread.CurrentPrincipal would probably be your domain-level account. Calling IsInRole() on that principal would return a list of security roles that you've been granted on the domain (I think).
Now - I wouldn't call this supporting Active Directory out of the box. You simply get that behavior because your machine happens to be part of a domain. My laptop isn't part of a domain, so Thread.CurrentPrincipal would return a local machine account.
Anyway - to get the behavior you want, you need to implement a custom principal object, and check if you're on the domain or not when logging in.
Mark:If you happen to be on a domain, Thread.CurrentPrincipal would probably be your domain-level account.
Mark:Now - I wouldn't call this supporting Active Directory out of the box. You simply get that behavior because your machine happens to be part of a domain. My laptop isn't part of a domain, so Thread.CurrentPrincipal would return a local machine account.
Csla returns Thread.CurrentPrincipal from within ApplicationContext.cs
System.Thread.Threading.CurrentPrincipal.IsInRole("DOMAIN\\MY_SECURITY_GROUP") returns false. Possibly because of some changes in the 2.0 framework? 2003 Server domain...
Oddly enough, the 2.0 framework no longer seems to allow casting a WindowsPrincipal out of the CurrentPrincipal which is really an IPrincipal type.
I was able to get functionality by doing the following:
//Security/ApplicationContext.cs
public static IPrincipal User
{
get
{
if (HttpContext.Current == null)
{
//Substitution ***
WindowsPrincipal wp = new WindowsPrincipal(WindowsIdentity.GetCurrent());
return wp;
}
//return Thread.CurrentPrincipal; //IsInRole() Returns false, always
else
return HttpContext.Current.User;
}
WindowsPrincipal MyPrincipal = (WindowsPrincipal) Thread.CurrentPrincipal;
from http://msdn2.microsoft.com/en-us/library/t6547wf1.aspx
This used to work,I believe they may have increased the level of type checking in .NET 2.0.The type of CurrentPrincipal should be IPrincipal. * EDITED * It turns out it'sa GenericPrincipal.Side Note: I belive the reason I need to use Domain\Security_Group is because thegroup scope is Domain.Local.
It was stated on the msdn page I previously posted
I should be able to add that to the csla framework and get the original code to work.
Thanks.
L8r
Copyright (c) Marimer LLC