I hoped on back to the certificate management application project again this week, to do some cleanup, adding a bit of documentation and test its deployment using FastCGI as well. Fortunately, the application still works as expected when deployed as a FastCGI process. We tested it out with the entire flow for individual certificates, from buying a new subscription on the actual WooCommerce store, to downloading the PKCS#12 using the link provided in an email sent by the application.
We also tested out the renewal process as well.
One of our concerns when deploying this application using FastCGI was whether the server application could still receive the client certificate as chosen by the user from the browser prompt. The application assumes a renewal event if an existing valid certificate is presented. It is needed so that it could reuse the same private key to generate a new valid certificate. Then the application could return a PEM certificate instead with the application/x-x509-user-cert MIME type specified, in which only Mozilla Firefox would automatically import it to their certificate store if it could bind to an existing private key stored in there as well.
The server application still managed to receive the user’s existing certificate and return the PEM certificate (a .crt file) as expected. Except that, in the case of Firefox, it was supposed to be automatically imported into the browser. Instead, it keeps downloading the PEM certificate as a file without the automatic import. The last time we tried it out in Firefox, it worked like that. So what went wrong?
It turns out the problem lies in the Content-Disposition HTTP header. Wt allows you to suggest a filename to data returned from the server, if it’s to be downloaded as a file. It is specified in the HTTP header as:
Content-Disposition: attachment; filename="Gabriel_Tan.crt"
The attachment value above tells the browser to download the returned data as a file no matter what, using the specified filename. Wt does this by default, so that was the cause the of the problem. Another value that could be set is inline:
Content-Disposition: inline; filename="Gabriel_Tan.crt"
Which means to open the file within the browser. The browser is smart enough to know that it is receiving a PEM certificate, and imports it successfully if the corresponding private key already existed. At least, we now have one workflow that would be smooth for the users, if they use Firefox browser.
Now that another problem has been dealt with, all I have left for this project is to complete the documentation. Next week, I would need to set up another two of our projects for deployment as well. How exciting!