tags:

views:

759

answers:

4

Hi, I have a WCF Web Service which is consuming by C# client application. I’m also having 4 groups stored in Active Directory. Client application is passing user credentials to connect this web service.

Web service exposing multiple APIs or Methods to be accessed by Client application as follows:

    [OperationContract]
    bool Read();


    [OperationContract]
    bool Write();

Read() method should be accessible for all clients

Write() method should be accessible by only users those belongs to specifc windows user group maintained by Active Directory.

Question: How can we filter or restrict an exposed interface or method by client based on it's user group maintain in AD?

Please help.

+1  A: 

I am not sure off the top of my head how to integrate AD credentials into the normal .NET security framework. However, it is possible (I'll see if I can find some links), and once you do, you should be able to use the standard security attribute to check for a "role", which would correspond to your AD group:

[OperationContract]
bool Read();

[PrincipalPermission(SecurityAction.Demand, Role = "Writers")]
[OperationContract]
bool Write();

To utilize AD groups, configure a service behavior:

<system.serviceModel>
  <behaviors>
    <serviceBehaviors>
      <adServiceBehavior>
        <serviceAuthorization principalPermissionMode="UseWindowsGroups" />
      </adServiceBehavior>
    </serviceBehaviors>
  </behaviors>
</system.serviceModel>

Had another thought. Sometimes the desire is to not even have the Write() method on the interface at all. With WCF, you can implement multiple service contract interfaces on a single service class. An ideal solution might be to create two service contract interfaces, one with Read() and Write(), one with just Read(). Depending on the user logged into the client, you could use the Read() interface for those who only have read access, and the Read()/Write() interface for those with access to both. This would also allow you to expose the safest service contract to clients that shouldn't have write access, while utilizing the read/write contract internally for administrative purposes. You never expose code that could be potentially exploited this way.

jrista
Thanks Marc, Please see my comments below
Lalit Sharma
+2  A: 

jrista is right - you can use the built-in Windows authorization services including the "PrincipalPermission" attribute to limit access.

BUT: before you can authorize, you need to authenticate. First you need to know who's knocking on your service's door before deciding whether to let him (or her) in or not.

In order to do that, you need to make sure to use Windows credentials on your message exchange, and client and server must be in the same domain (or in domains with a mutual trust relationship). Also, you'll need to use a binding like wsHttp or netTcp that allows and supports Windows credentials by default, and you need to make sure to use and configure a binding security configuration that transports the Windows credentials across from the client to the server.

You'll need to have something like:

<system.serviceModel>
  <bindings>
    <netTcpBinding>
      <binding name="Secured">
        <security mode="Transport">
          <transport clientCredentialType="Windows" />
        </security>
      </binding>
    </netTcpBinding>
  </bindings>
</system.serviceModel>

and then you'll need to reference that binding configuration from your client and server endpoints.

WsHttpBinding and NetTcpBinding both default to using Windows client credentials, so out of the box, unless you've turned security off completely, you should get Windows credentials support in those two bindings.

Marc

PS:
As jrista shows (and I did in a previous answer to almost the same question you had), you really only need to add that PrincipalPermission attribute to the methods you want to limit to users who belong to a certain group - no manual messing around with AD group memberships etc. needed.

If you really must get the groups the user calling your service belongs to, you can check out the ".Groups" property of the WindowsIdentity calling:

WindowsIdentity winCaller = ServiceSecurityContext.Current.WindowsIdentity;
foreach(var group in winCaller.Groups)
{
   Console.WriteLine(group.Value);
}

If you need the name of the user calling in, use winCaller.Name. If you need the SID for the user calling, use winCaller.User. It's all right there - no messing, no complicated code - just use it! :-)

marc_s
Thanks rista, Please see my comments below..
Lalit Sharma
A: 

jrista, Thanks for you reply.. I tried the same directives as PrincipalPermission as follows:

[PrincipalPermission(SecurityAction.Demand, Role = "Readers")] [OperationContract] bool Read();

[PrincipalPermission(SecurityAction.Demand, Role = "Writers")] [OperationContract] bool Write();

But it does not work. Read group user also able to call Writer() methined and Writer group user also able to call Write() method.

One thing, i want to tell you that, I'm using BasicHttpBind inmy web.config file as below:


Please suggest, Is that require to implement wsHttpBiding for this require functionality.If yes then How to implement wsHttpBinding in my Web Servive?

Please Help & Thanks

Lalit Sharma
I am not really sure what you mean by "Read group user also able to call Writer (0 methined and Writer group user also able to call Write() method.)" Could you please clarify that for me?
jrista
Let says, We have 2 windows Group named as "Readers" and another group is "Writers". Now Reader group should not allow to call Write() method and Writer Group should not call Read() methodBut as per my methids declaration above, Readers group is still able to call Write() method and Writers group is still able to call Read() method
Lalit Sharma
@Lalit: if you check the "WindowsIdentity" inside your service method - is it NULL, or did you get a WIndows credential delivered??
marc_s
I think marc_s is on to the problem. It does not sound like you are actually authenticating via windows authentication (in your case, against Active Directory). Make sure that you are following both marc's answer as well as my answer, and make sure that the WindowsIdentity is not null.
jrista
A: 

If you're hosting in IIS is the server set to allow anonymous?

Jarrod268
Lalit Sharma