Sunday, May 13, 2012

Enable HTTPS in a Window Azure website

Just enabled HTTPS for our social CRM site.  Following is the steps:

Step 1. Obtain a SSL certificate in .pfx file (Azure takes .pfx cert only)
a. Create a Certificate Signing Request (CSR)
    In IIS Manager, click root in the left pane, double click Server Certificate in the middle pane, click Create Certificate Request in the right pane. Go through the wizard and save the certificate request in a .txt file.

b. Purchase, generate and download a SSL certificate from a Certificate Authority (CA), e.g. VeriSign, GoDaddy.  You need to copy & paste the CSR generated in 1a to generate the certificate.  
(In Godaddy's case, the downloaded certificate package contains two files: <domain name>.crt and gd_iis_intermediates.p7b.)

c. Go back to IIS Manager, click Complete Certificate Request in the right pane
d. Navigate to the location where your certificate file is saved. You may need to change the file extension filter to show your cerf file (in my case, I select <domain name>.crt).
e. Right click the imported cert, Export, give .pfx file name and type password, hit OK.  Now you have the right cert ready to be uploaded to Azure.

Step 2. Upload the cert file (.pfx) to Windows Azure management portal.
a. Log in to Windows Azure management portal (http://windows.azure.com), click Hosted Service, Storage Accounts & CDN on the left, Production Deployments on the right.  
b. Navigate to where the exported .pfx file is located, type in the password, hit OK
c. Select the uploaded cert, copy the Thumbprint from the Properties pane on the right

Step 3. Enable SSL in your Windows Azure web project.
a. Enable it in Azure configuration.
In your ServiceConfiguration.Cloud.cscfg file, add
    <Certificates>
      <Certificate name="<your cert name>" thumbprint="<your thumbprint>" thumbprintAlgorithm="sha1" />
    </Certificates>

In your ServiceDefinition.csdef file, add
    <Sites>
      <Site name="Web">
        <Bindings>
          <Binding name="Endpoint1" endpointName="HTTP" />
          <Binding name="Endpoint1" endpointName="HTTPS" />
        </Bindings>
      </Site>
    </Sites>
    <Endpoints>
      <InputEndpoint name="HTTP" protocol="http" port="80" />
      <InputEndpoint name="HTTPS" protocol="https" port="443" certificate="<your cert name>" />
    </Endpoints>
    <Certificates>
      <Certificate name="<your cert name>" storeLocation="LocalMachine" storeName="CA" />
    </Certificates>

Obviously you need to replace <your cert name> with your own cert name and <your thumbprint> with the thumbprint you copied from 2c.

b. Enable in your code: I have a MVC site.  So I decorated certain controllers and actions with RequireHttps attribute.  

    [RequireHttps]
    public class ContactController : BaseController
    { 
        ...
    public class AccountController : Controller
    {
        [RequireHttps]
        public ViewResult Index()
        {
        ...

Step 4. Deploy your web project to Azure.
When you try to navigate to a secure page using HTTP, the website should automatically redirect you to HTTPS.

Asp.Net Dev Server and HTTPS
After HTTPS is enabled, you can no longer debug with Asp.Net Dev Server which simply doesn't support HTTPS.  Fortunately, there are a couple of easy workarounds in this helpful StackOverflow post.  Both worked well.  I chose second one as I'd like to disable HTTPS when running locally regardless debug or release build,  but
  • Enable HTTPS on release build only by using conditional compiling: 
#if !DEBUG
[RequireHttps] //apply to all actions in controller
#endif
  • Derive from RequireHttpsAttribute and stop HTTPS if the request is local.
    public class CustomequireHttpsAttribute : RequireHttpsAttribute
    {
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            if (filterContext == null)
            {
                throw new ArgumentNullException("filterContext");
            }

            if (filterContext.HttpContext != null && filterContext.HttpContext.Request.IsLocal)
            {
                return;
            }

            base.OnAuthorization(filterContext);
        }
    }


No comments:

Post a Comment