Search code examples
c#asp.net-coregraphqlhotchocolate

How to encrypt the body of a request with GraphQL and Hot Chocolate


I have to implement an API using GraphQL with C# and Hot Chocolate. One of the requirements is that the body of the request must be encrypted.

For instance, if I call my "Hello World" service with this body:

query{
  hello(name: "stackoverflow.com")
}

And the response of the service is this:

{
  "data": {
    "hello": "Hello, stackoverflow.com "
  }
}

I have to be able to send a body fully encrypted with some algorithm, lets say SHA256, like this:

//This is the query of graphql encrypted in SHA256
5777bb8378c6caf7f29e7b6aae9ddcb168cbba74ffd60dbe6ef21c2f70b16736

Then, decrypt the request and get the data to send as reponse.

My first aproach was to add an Interceptor Get the HttpRequest body, decrypt, and then continue with the normal flow.

 public class HttpRequestInterceptor : DefaultHttpRequestInterceptor
    {
        public override ValueTask OnCreateAsync(HttpContext context,
            IRequestExecutor requestExecutor,
            IQueryRequestBuilder requestBuilder,
            CancellationToken cancellationToken)
        {
            //Get the raw body of the request
            var rawBody = GetRequestBodyAsync(context.Request);
            //Decrypt the raw body and set the decrypted body into the HttpContext request body
            GetDecryptedBodyAsync(context, rawBody.Result);
            return base.OnCreateAsync(context, requestExecutor, requestBuilder, cancellationToken);
        }

        private async void GetDecryptedBodyAsync(HttpContext context, string rawBody)
        {
            var requestContent = new StringContent(rawBody, Encoding.UTF8, "application/json");
            context.Request.Body = await requestContent.ReadAsStreamAsync();
        }

    }

The problem is when I test this aproach, it doesn't work because the encrypted hash input as body is not valid:

{
  "errors": [
    {
      "message": "Unexpected token: Name.",
      "locations": [
        {
          "line": 1,
          "column": 1
        }
      ],
      "extensions": {
        "code": "HC0011"
      }
    }
  ]
}

Is there a way to do this?


Solution

  • So there is a difference between encryption and hashing. SHA256 is hashing, and has nothing to do with encryption. If you has your document, there is no way to retrieve the original document.

    If you do not want to send Queries over the wire then maybe you are looking for Persisted Queries:

    https://chillicream.com/docs/hotchocolate/v12/performance/persisted-queries or as a video: https://www.youtube.com/watch?v=ZZ5PF3_P_r4

    If this doesnt help you, and you want to do encryption, then you have to first define what you want to protect your data from. Maybe TLS is already enough of a encryption, then you just have to force the user to use HTTPS.

    If you end up using some kind of custom end to end encryption, then you will likely have to do this before the HotChocolate execution. So as a AspNet Core Middleware, rahter than a GraphQL component.