Adam J Wolf

Syntax is my UI

WCF Dynamic IP Filtering

Have you ever had a client that wanted to do dynamic time of day IP filtering of a WCF service? No! What do you live under, a rock?

Well, I have and this is how I solved it. First, we look for better options like not writing code and use IIS IP Filtering. After that’s rejected by the client, I fire up my IDE; it takes so loooong.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public class IPFilteringAuthorizationManager : ServiceAuthorizationManager
{
  private const string ServiceActionAttempedBy = "{0} Service Action {1} attemped by {2}.";
  private const string NoAuthorizedIPAddress = "{0} is not an authorized IP address for {1}.";
  private const string AuthorizationManagerFailure = "ARTServiceAuthorizationManager failure.";

  protected override bool CheckAccessCore(OperationContext operationContext)
  {
      var callerIsAuthorized = false;

      var callersIP = ((RemoteEndpointMessageProperty)operationContext
          .IncomingMessageProperties[RemoteEndpointMessageProperty.Name]).Address;
      var mesageTo = operationContext.RequestContext.RequestMessage.Headers.To.Segments.Last();
      var messageAction = operationContext.RequestContext.RequestMessage.Headers.Action;

      try
      {
          callerIsAuthorized = GetAuthorizedIPAddresses(mesageTo).Contains(callersIP);

          if (!callerIsAuthorized)
          {
              _log.Info(String.Format(NoAuthorizedIPAddress, callersIP, mesageTo));
          }
      }
      catch (Exception ex)
      {
          _log.Error(ex);
      }
      finally
      {
          _log.Info(String.Format(ServiceActionAttempedBy, mesageTo, messageAction, callersIP));
      }

      return callerIsAuthorized;
  }
}

I am a big fan of how WCF can be composed so I used a ServiceAuthorizationManager and added it to the services behaviors through the config.

1
2
3
4
5
6
7
8
9
10
11
12
<serviceBehaviors>
  <behavior name="IPFilteringBehavior">
      <serviceMetadata httpGetEnabled="true"/>
      <serviceDebug includeExceptionDetailInFaults="false"/>
      <serviceAuthorization
          serviceAuthorizationManagerType="AdamJWolf.IPFilteringAuthorizationManager, 
              AdamJWolf.Core, 
              Version=1.0.0.0, 
              Culture=neutral, 
              PublicKeyToken=null" />
  </behavior>
</serviceBehaviors>

I left out the boring part about which IP addresses are allowed and at what time, but I think you get the point. These dynamic rules for access to a WCF service can get a little sticky but WCF has some great extensibility points that allow you to solve your client’s problems. I have also used the same type of dynamic service authorization for use with Active Directory Groups.