SSL/TLS
SSL/TLS (https) is increasingly required for security (e.g. it's mandatory for OAuth2).
SSL 3.0 (from 1996) is insecure. Most servers and clients (and IE 7+) use TLS 1.1 or later.
"POODLE" hacks work by downgrading from TLS to insecure SSL. If you don't support IE6, the server can disable SSL.
RequireHttps
MVC has a [RequireHttps] attribute, which automatically redirects GET requests from http:// to https://. (Not POSTS, which would invoke dreaded "do you want to re-submit" dialogs).
WebAPI doesn't have RequireHttps, so here's a simple implementation:
using System;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;
namespace Mvc5Auth.Infrastructure
{
public class WebApiRequireHttpsAttribute : AuthorizationFilterAttribute
{
public override void OnAuthorization(HttpActionContext actionContext)
{
var request = actionContext.Request;
if (request.RequestUri.Scheme == Uri.UriSchemeHttps) return;
//it's http
HttpResponseMessage response;
if (!request.Method.Equals(HttpMethod.Get))
{
//post etc
response = request.CreateResponse(HttpStatusCode.NotFound);
response.ReasonPhrase = "Must use https";
}
else //GET
{
//create a copy of the uri with https
var uri = new UriBuilder(request.RequestUri) { Scheme = Uri.UriSchemeHttps, Port = 443 };
//build a redirect with the header location and helpful html
response = request.CreateResponse(HttpStatusCode.Redirect);
response.Headers.Location = uri.Uri;
var body = string.Format("<p>Resource available at <a href=\"{0}\">{0}</a>.</p>",
uri.Uri.AbsoluteUri);
response.Content = new StringContent(body, Encoding.UTF8, "text/html");
}
actionContext.Response = response;
}
}
}
Either use it directly on the controller/method with [WebApiRequireHttps] or apply it in App_Start/WebApiConfig (with a little config switch for local debugging)
if (string.Equals(ConfigurationManager.AppSettings["RequireHttps"], "true", StringComparison.OrdinalIgnoreCase))
{
config.Filters.Add(new WebApiRequireHttpsAttribute());
}
- Visual Studio https: in project Properties Window (F4), Development Server / SSL Enabled.
- The https URL is a different port. RequireHttps cannot redirect. Copy and paste it from the F4 properties.
- Th browser will complain the localhost certificate isn't trusted!
- In Visual Studio 2013, project Properties (Alt-Enter) - "Web" page - Debuggers (near bottom), uncheck "Edit and Continue" so IISExpress runs continuously.
SSL from Certificate Authority
- A basic certificate is for a specific domain name; a wildcard certificate allows www. and subdomains. A Subject Alternative Name (SAN) cert allows specific alternative names (known subdomains).
- Create a certificate request (for the correct domain name!) with IIS, certreq.exe or OpenSSL (NB: the OID for an SSL cert is 1.3.6.1.5.5.7.3.1).
- Submit the .csr (or paste in text), and get a .cer file. When you accept the .cer file, it is placed in the windows certificate store.
- You probably have to get intermediate (chain) certificates from the CA. Install those.
- Export the certificate from the Personal store with the private key, Personal Information Exchange - PKCS #12 (.pfx), Include all certificates in the certificate chain.
Local SSL certificates
- An SSL certificate contains the server/machine name.
- You can create a generic root certificate (company name) which is installed to Trusted Root on each machine (share the root .cer file) then...
- Each application has a host name with an SSL certificate. The host name is created in IIS and System32/drivers/etc/hosts. The SSL certificate is signed with the root certificate, and the .pfx file is shared. Because the root certificate is trusted, the SSL certificate is implicitly trusted.
IIS
For development, you can create a certificate with IIS (IIS section, Server certificates icon, actions "Create Self-Signed Certificate", which puts it in the Personal certificates) or use makecert.
Certificates mmc
Open the Certificates mmc (MMC/ File - Add/Remove Snap-In / pick "Certificates" and "Add" / "Computer Account" / "Local Computer"
The certificate store you need is "Trusted Root Certification Authorities"
MakeCert
Makecert is available using the Visual Studio command prompt (Common7\Tools\VsDevCmd.bat), usually in C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin
makecert.exe generates an X509 (.cer) certificate and a private key file (.pvk).
This version (from the Pluralsight course WebAPi2 Security) creates a "certification authority" type cert and converts the pvk and cert files to a more portable pfx. NB dates are mm/dd/yyyy
makecert.exe -r -n "CN=DevRoot" -pe -sv DevRoot.pvk -a sha1 -len 2048 -b 01/31/2010 -e 01/31/2030 -cy authority DevRoot.cer pvk2pfx.exe -pvk DevRoot.pvk -spc DevRoot.cer -pfx DevRoot.pfx
Import the .cer into Trusted Root Certification Authorities using MMC (NB: just the public key)
Then make an SSL certificate (the obscure -eku OID) using the root certificate.
makecert.exe -iv DevRoot.pvk -ic DevRoot.cer -n "CN=%1" -pe -sv %1.pvk -a sha1 -len 2048 -b 01/31/2010 -e 01/31/2020 -sky exchange %1.cer -eku 1.3.6.1.5.5.7.3.1 pvk2pfx.exe -pvk %1.pvk -spc %1.cer -pfx %1.pfx
Import the .pfx (NB: NOT .cer as you need the private key) into Personal using MMC. Because it was signed with the Trusted Root certificate, the chain is trusted.
In IIS manager, go to Edit Site/Bindings and add an https binding with the SSL certificate.
If you add a new site, ensure IIS_IUSERS has access to the site folder, and add the binding, host name and (in IIS8/Windows Server 2012) Require Server Name Indication (allows multiple host names to use the same server/port)
Finally, in System32/drivers/etc edit hosts to add the alias to the 127.0.0.1
You can also create client SSL certificates, if you can distribute them and configure IIS to accept client certificates (system.webServer/security/access sslFlags="Ssl, SslNegotiateCert" )
OpenSSL
OpenSSL includes a set of command lines tools for converting different file formats.
If you update a certificate, you'll get a .crt and .p7b (without private keys). To create a .pfx, you can use OpenSSL.
To extract the private key from original .pfx if you don't have the private key (normally a .key or .pem extension, internally it's .pem)
openssl pkcs12 -in certname.pfx -nocerts -out key.pem -nodes
To create a .pfx from a private key and a .crt/.cer file:
openssl pkcs12 -export -out certname.pfx -in certname.crt -inkey key.pem