Working with SSL in Web API
by Mike Wasson
Several common authentication schemes are not secure over plain HTTP. In particular, Basic authentication and forms authentication send unencrypted credentials. To be secure, these authentication schemes must use SSL. In addition, SSL client certificates can be used to authenticate clients.
Enabling SSL on the Server
To set up SSL in IIS 7 or later:
- Create or get a certificate. For testing, you can create a self-signed certificate.
- Add an HTTPS binding.
For details, see How to Set Up SSL on IIS 7.
For local testing, you can enable SSL in IIS Express from Visual Studio. In the Properties window, set SSL Enabled to True. Note the value of SSL URL; use this URL for testing HTTPS connections.
Enforcing SSL in a Web API Controller
If you have both an HTTPS and an HTTP binding, clients can still use HTTP to access the site. You might allow some resources to be available through HTTP, while other resources require SSL. In that case, use an action filter to require SSL for the protected resources. The following code shows a Web API authentication filter that checks for SSL:
[!code-csharpMain]
1: public class RequireHttpsAttribute : AuthorizationFilterAttribute
2: {
3: public override void OnAuthorization(HttpActionContext actionContext)
4: {
5: if (actionContext.Request.RequestUri.Scheme != Uri.UriSchemeHttps)
6: {
7: actionContext.Response = new HttpResponseMessage(System.Net.HttpStatusCode.Forbidden)
8: {
9: ReasonPhrase = "HTTPS Required"
10: };
11: }
12: else
13: {
14: base.OnAuthorization(actionContext);
15: }
16: }
17: }
Add this filter to any Web API actions that require SSL:
[!code-csharpMain]
1: public class ValuesController : ApiController
2: {
3: [RequireHttps]
4: public HttpResponseMessage Get() { ... }
5: }
SSL Client Certificates
SSL provides authentication by using Public Key Infrastructure certificates. The server must provide a certificate that authenticates the server to the client. It is less common for the client to provide a certificate to the server, but this is one option for authenticating clients. To use client certificates with SSL, you need a way to distribute signed certificates to your users. For many application types, this will not be a good user experience, but in some environments (for example, enterprise) it may be feasible.
Advantages | Disadvantages |
---|---|
- Certificate credentials are stronger than username/password. - SSL provides a complete secure channel, with authentication, message integrity, and message encryption. | - You must obtain and manage PKI certificates. - The client platform must support SSL client certificates. |
To configure IIS to accept client certificates, open IIS Manager and perform the following steps:
- Click the site node in the tree view.
- Double-click the SSL Settings feature in the middle pane.
Under Client Certificates, select one of these options:
- Accept: IIS will accept a certificate from the client, but does not require one.
- Require: Require a client certificate. (To enable this option, you must also select “Require SSL”)
You can also set these options in the ApplicationHost.config file:
[!code-xmlMain]
1: <system.webServer>
2: <security>
3: <access sslFlags="Ssl, SslNegotiateCert" />
4: <!-- To require a client cert: -->
5: <!-- <access sslFlags="Ssl, SslRequireCert" /> -->
6: </security>
7: </system.webServer>
The SslNegotiateCert flag means IIS will accept a certificate from the client, but does not require one (equivalent to the “Accept” option in IIS Manager). To require a certificate, set the SslRequireCert flag. For testing, you can also set these options in IIS Express, in the local applicationhost.Config file, located in “Documents”.
Creating a Client Certificate for Testing
For testing purposes, you can use MakeCert.exe to create a client certificate. First, create a test root authority:
[!code-consoleMain]
1: makecert.exe -n "CN=Development CA" -r -sv TempCA.pvk TempCA.cer
Makecert will prompt you to enter a password for the private key.
Next, add the certificate to the test server’s “Trusted Root Certification Authorities” store, as follows:
- Open MMC.
- Under File, select Add/Remove Snap-In.
- Select Computer Account.
- Select Local computer and complete the wizard.
- Under the navigation pane, expand the “Trusted Root Certification Authorities” node.
- On the Action menu, point to All Tasks, and then click Import to start the Certificate Import Wizard.
- Browse to the certificate file, TempCA.cer.
- Click Open, then click Next and complete the wizard. (You will be prompted to re-enter the password.)
Now create a client certificate that is signed by the first certificate:
[!code-consoleMain]
1: makecert.exe -pe -ss My -sr CurrentUser -a sha1 -sky exchange -n "CN=name"
2: -eku 1.3.6.1.5.5.7.3.2 -sk SignedByCA -ic TempCA.cer -iv TempCA.pvk
Using Client Certificates in Web API
On the server side, you can get the client certificate by calling GetClientCertificate on the request message. The method returns null if there is no client certificate. Otherwise, it returns an X509Certificate2 instance. Use this object to get information from the certificate, such as the issuer and subject. Then you can use this information for authentication and/or authorization.
[!code-csharpMain]
1: X509Certificate2 cert = Request.GetClientCertificate();
2: string issuer = cert.Issuer;
3: string subject = cert.Subject;
|