Guidance encryption/decryption of payload. Where? How?

Topics: Web Api
Nov 30, 2010 at 8:00 PM
Some of us may want to use decryption/encryption for xml payloads when making calls into open APIs on top of SSL (https). Similarly we may also want to use encrypting payload for any media type (for example, json format). Is this doable with current bits? If so, can some one provide a guidance on how to go about it?

 

Coordinator
Nov 30, 2010 at 8:24 PM

In the currents bits one way to implement this would be to author a custom processor. Processors sit in the middle of the request and the response making them an ideal place to do this sort of thing. In the future we will likley have other places where you can handle this translation.

If you look in the samples you will see a specific type of processor called the MediaTypeProcessor which is responsible for serialization / deserializtion. However, you can use processors any kind of translation. If you look in my blog post here for example I show taking the uri in the request and converting it into an object.

public class Location
{
    public double Latitude { get; set; }
    public double Longitude { get; set; }
}

public class LocationProcessor : Processor<string, string, Location>
{
    public LocationProcessor()
    {
        this.OutArguments[0].Name = "Location";
    }
    public override ProcessorResult<Location> OnExecute(string latitude, string longitude)
    {
        var lat = double.Parse(latitude);
        var lon = double.Parse(longitude);
        return new ProcessorResult<Location> { Output = new Location { Latitude = lat, Longitude = lon } };
    }
}

[ServiceContract]
public class MapResource {
  [UriTemplate="{latitude},{longitude}"]
  public Stream Get(Location location) {
    //return the map
  }
}

The above example takes in two strings latitude and longitude which are parsed out of the uri based on the parameters specified in the uri template. It then returns a location value which maps to the location parameter on the MapResource.Get method.

In your case what you will do is write a processor whose input type is HttpRequestMessage. The input param also needs a name, which you will set conventionally in the execute method. The output param won't be used but it's necessary due to the generic signature.

It will look something like this:

public class DecryptionProcessor : Processor<HttpRequestMessage, object> {
  public override ProcessorResult<object> OnExecute(HttpRequestMessage httpRequestMessage) 
  {
     //access httpRequestMessage.Content here to decrypt
    return new ProcessorResult<object>(); //necessary 
  }
}

Then in the execute method it will perform the decryption.

For the response / encryption you will create a separate processor which takes in HttpResponseMessage and returns object. It will do the encyption within the execute.

To register the processors you will override the methods in your configuration class. See my blog post for examples.

 

 

Dec 23, 2010 at 12:25 PM

Hi !

I react about this post. I try to do what Glen proposed, a response encrypter with a processor. So here is my processor :

public class ResponseEncrypter2 : Processor<HttpResponseMessage, object>
{
        public ResponseEncrypter2()
            : base()
        {
            this.InArguments[0].Name = "HttpResponseMessage";
        }

        public override ProcessorResult<object> OnExecute(HttpResponseMessage input)
        {
            // Make encryption
            //TODO
            return new ProcessorResult<object>()
            {
                Output = HttpContent.Create("Data encrypted")
            };
        }
}

Here I register the processor :

public override void RegisterResponseProcessorsForOperation(HttpOperationDescription operation, IList processors, MediaTypeProcessorMode mode)
{
// Encryption processor
processors.Add(new ResponseEncrypter2());
}

But when I execute a request, the output created by my processor (here "DataEncrypted") is always replaced by the "WriteToStream" method of the last MediaTypeProcessor executed...  Is it normal ??

 

Ben

Coordinator
Dec 23, 2010 at 10:06 PM

Actually what is happening is you are not setting your content to the actual response message. You are just returning content. instead set the content directly on the response that was passed in (input.content). as to the output value just new up a ProcessorResult<object> and don't set the output. The return value is not used in this case because the response message is a reference.

Glenn

Coordinator
Dec 23, 2010 at 10:08 PM

also just as a side note, you can set the name of the input parameter simply by modifying the names on the execute method rather than having to set the name in the ctor as we use the param names as a convention for the key. Thus rename input to httpResponseMessage and it should work.

Glenn

Dec 24, 2010 at 8:52 AM

Ok, it works but not like I'am expecting...

Imagine that I want to encrpyt the result of a MediaTypeProcessor (png for example). My "ResponseEncrypter2" Processor should be called after the "WriteToStream" method of the Png Processor (or any other MediaTypeProcessor).

But If I make my ResponseEncrypter processor as Glen said :

public class ResponseEncrypter2 : Processor<HttpResponseMessage, object>
    {
        public ResponseEncrypter2()
            : base()
        {
        }

        public override ProcessorResult<object> OnExecute(HttpResponseMessage HttpResponseMessage)
        {
            // Make encryption
            HttpResponseMessage.Content = HttpContent.Create("Data encrypted");
            return new ProcessorResult<object>();          
        }
    }

I register it and the png processor as follow :

public override void RegisterResponseProcessorsForOperation(HttpOperationDescription operation, IList<Processor> processors, MediaTypeProcessorMode mode)
        {          

            // Add media processors          
            processors.Add(new PngProcessor(operation, mode));
            processors.Add(new JpgProcessor(operation, mode));

            // Encryption processor
            processors.Add(new ResponseEncrypter2());
           
        }

 

With that configuration, "ResponseEncrypter2 OnExecuteMethod" is called but the "WriteToStreamMethod" of the PngProcessor is never called. So on real case, I could never encrpyt the result of the "writeToStream" method... What I will expect is that the "ResponseEncrypter" will be called at the end of all processors treatments (particulary, after the "writeToStream" method)...

Golbally, on my opinion, on this new Api, process orders management is not very clear...

 

Ben