Working with IIS Express Self-signed Certificate, ASP.NET Web API and HttpClient

We will see how to smoothly work with IIS Express Self-signed Certificate, ASP.NET Web API and HttpClient by placing the self-signed certificate in the Trusted Root CA store.
23 October 2012
4 minutes read

Related Posts

If you would like to only support HTTPS with your ASP.NET Web API application, you might also want expose your application through HTTPS during the development time. This is not a big problem if you are heavily integration-testing your Web API as you can pass anything you want as a host name but if you are building your HTTP API wrapper simultaneously, you want to sometimes do manual testing to see if it’s actually working. There are sevaral ways to sort this problem out and one of them is provided directly by Visual Studio. Visual Studio allows us to create HTTPS bindings to use with IIS Express during development time. Let’s see how that works.

Note: I am assuming everybody understands that I am talking about ASP.NET Web API web host scenario with ASP.NET here. This blog post is not about self-host scenarios.

First of all, I created an empty web application through visual studio. Then, I added one of my NuGet packages: WebAPIDoodle.Bootstrap.Sample.Complex. This package will get you all ASP.NET Web API stuff and a working sample with all CRUD operations.

I also created a message handler which is going to ensure that our API is only going to be exposed over HTTPS.

public class RequireHttpsMessageHandler : DelegatingHandler {

    protected override Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, 
        CancellationToken cancellationToken) {

        if (request.RequestUri.Scheme != Uri.UriSchemeHttps) {

            var forbiddenResponse = 
                request.CreateResponse(HttpStatusCode.Forbidden);

            forbiddenResponse.ReasonPhrase = "SSL Required";
            return Task.FromResult<HttpResponseMessage>(forbiddenResponse);
        }

        return base.SendAsync(request, cancellationToken);
    }
}

Then, I registered this message handler as you can see below:

protected void Application_Start(object sender, EventArgs e) {

    var config = GlobalConfiguration.Configuration;

    //...

    config.MessageHandlers.Add(new RequireHttpsMessageHandler());
}

To configure the HTTPS endpoint with IIS Express, I simply need to click on the web application project and press F4. This will bring up the project properties and there will be a option there called "SSL Enabled".

image

By default, this is set to False as you can see. If we change this and set it to True, Visual Studio will create the necessary binding for our application by assigning a new port number and attaching the pre-generated self-signed certificate for that endpoint.

image

Now, when we open up a browser and navigate to that HTTPS endpoint, we should face a scary looking error:

image

As our certificate is a self-signed certificate, the browser doesn’t trust that and gives this error. This error is not a blocking issue for us and we can just click the Proceed anyway button to suppress this error and everything will be work just fine.

Let’s close the browser and create a very simple and naïve .NET console client for our API as below:

class Program {

    static void Main(string[] args) {

        Console.WriteLine(GetStringAsync().Result);
        Console.ReadLine();
    }

    public static async Task<string> GetStringAsync() {

        using (HttpClient client = new HttpClient()) {

            return await client
               .GetStringAsync("https://localhost:44304/api/cars");
        }
    }
}

As I said, it is insanely simple Smile but will serve for our demo purposes. If we run this console application along with our Web API application, we should see an exception thrown as below:

image

This time the HttpClient is nagging at us because it didn’t trust the server certificate. If we open up the browser again and take a look at the certificate, we will see that it is also complaining that this self-signed certificate is not in the Trusted Root CA store.

image

One way to get rid of this problem is to place this self-signed certificate in the Trusted Root CA store and the error will go away. Let’s first open up a PowerShell Command window and see where this self-signed certificate lives.

image

As we now know where the certificate is, we can grab this certificate and place it in the Trusted Root CA store. There are several ways of doing this but I love PowerShell, so I am going to do this with PowerShell, too. To be able to perform the below operations, we need to open up an elevated PowerShell Command Prompt.

image

Let’s explain what we did above:

  • We retrieved our self-signed certificate and stuck it into a variable.
  • Then, we retrieved the Trusted Root CA store and stuck that into a variable, too.
  • Lastly, we opened up the store with Read and Write access and added the certificate there. As a final step, we closed the store.

After this change, if we take a look at the Trusted Root CA store, we will see our certificate there:

SNAGHTML1d009a0f

If we now run our console client application, we should see it working smoothly.

image

I hope this will help you as much as it helped me Smile