2

I have a WPF client/server application using WCF on the server side. It is presently unsecured and I'm wishing to secure it for a userbase on my Active Directory. The application should host it's own Role/Permissions database which can be attached to the user's profile via a reference to their active directory account - SID, SAM whatever.

I need to understand some steps to implement the security and then the roles/permissions that my user has within my application:

  1. How do I get my WPF application to only allow identities that have been authorized by my Active Directory? If someone logs into their local computer using some local user account, they still obviously have access to run the WPF executable - so how do I make sure that the login is indeed an Active Directory login, and not a local one? Is this a configuration option in the app.config the same as in asp.net web.config where all I do is set Authentication to Windows and the rest is just handled?
  2. Once the user is proven to be a valid active directory user, what is the best approach to tie the user's WindowsIdentity to the roles in the tables in my database? Is this something that is best approached using a custom RoleProvider?

Is there any good documentation that will help connect these dots? Because of all the WIF documentation I've read and all the tutorials I've watched, these are the only bits that don't make sense to me and don't appear to be explained anywhere.

I know I need to secure the WCF, but it's my understanding that this is relatively simple as in ASP.NET where it's really just a matter of configuring it correctly and the rest just happens.

BobTheBuilder
  • 2,455
  • 2
  • 27
  • 39
  • Have you looked at permissions for access to the web server? You can always use LDAP to verify the user account accessing your application is in the AD. – Bob. Apr 16 '13 at 18:42
  • Bob: I was under the impression that I could somehow validate the WindowsIdentity token to figure out who issued it and validate the signature to verify its authenticity, thus avoiding that whole round trip to the active directory server myself. – BobTheBuilder Apr 16 '13 at 19:16
  • What would you use to validate? And what would you use to guarantee the integrity of the signature if you're doing that all on the user? – Bob. Apr 16 '13 at 19:22
  • Well - I would assume like Public/Private key encryption, your token is signed by the issuing authority. This signature serves as validation of the source of and the authenticity of the token. – BobTheBuilder Apr 16 '13 at 19:28
  • What about checking if the `Environment.UserDomainName` variable has the correct domain name? It'll determine if its a local user or network user. See this [question](http://stackoverflow.com/a/310190/1466627). – Bob. Apr 16 '13 at 19:35
  • @BobTheBuilder Did the answer below help at all? Also, could I get clarification on the second part of your question? – CodeWarrior Apr 22 '13 at 14:40

1 Answers1

1

As to question 1:

You can use the PrincipalPermissionAttribute on your exposed WCF methods:

    [PrincipalPermission(SecurityAction.Demand, Role = "ProjectManagers")]
    [PrincipalPermission(SecurityAction.Demand, Role = "Developers")]
    [PrincipalPermission(SecurityAction.Demand, Role = "Operations")]
    [PrincipalPermission(SecurityAction.Demand, Role = "Clients OU Admins")]
    public string CreateUser(string strFName, string strLName, string strPassword, string strOUName)
    {
        return CreateADAccount(strFName, strLName, strPassword, strOUName);
    }

This will authorize only the users who are members of one of the four groups above to execute the method.

For question 2, off the top of my head, you could do something like below:

The below code is not tested and is incomplete. It is for conceptualizing only.

public class ControlAuthenticator
{
    Dictionary<string, ControlRule> ControlRules { get; set; } 
    public ControlAuthenticator()
    {
        ControlRules = new Dictionary<string, ControlRule>();
    }

    public bool UserCanRead(string controlName)
    {
        var user = MainViewModel.Current.CurrentUserPrincipal;

        return ControlRules[controlName].ReadPermission.Split(Convert.ToChar(","))
                                     .Intersect(user.GetGroups().Select(g => g.Name))
                                     .Any();
    }
}

public class ControlRule
{
    public string ControlName { get; set; }
    public string ReadPermission { get; set; }
    public string WritePermission { get; set; }
}

The idea is that on your ViewModel, you call the userCanRead (or write which I did not create) methods supplying the control name. You get back a boolean. The UserCanRead method checks to see if there are any entries in the ReadPermission property (which I took to likely be a comma separated string of authorized groups) that correlate with the groups that the current user belongs to. If there is any correlation, return true.

On your ViewModel, if true, display the value (or allow the edit) otherwise, display a different value, or disallow any edit.

CodeWarrior
  • 7,388
  • 7
  • 51
  • 78
  • Of course - so what I mean is that the controls are referenced in the database by their identifier and the role that is required to read and/or write. i.e. 3 columns: ControlName, ReadPermission, WritePermission. – BobTheBuilder Apr 22 '13 at 15:21