Previously, there were some issues in the transmission of the bitstream to the board’s server, but with a touch of Dr Shawn’s magic, he managed to somehow solve the issue on the board side. With that, I was able to send the bitstream successfully and get a proper response from the server in the board after a few seconds. At the moment, the board’s server does not do anything with the bitstream, and therefore the MD5 calculation which is done on HEAD request is not implemented yet. But the fact it could give a response means that it has received the bitstream successfully. Until then, a new intern would be responsible for properly implementing the required procedures. So it’s time for me to move on to the next phase.
For the application I’m developing now, it is decided that the user authentication method would be done through client certificates as opposed to the Basic Authentication method of username and password. This is great because the users are not required to remember any passwords. They would just have to acquire a certificate from a web store that would be set up to sell different kinds of client certificates that we generate on our end. Furthermore, all user related information is stored in that certificate, thus we do not need to have a separate table in the application’s database just to store user’s meta data.
To test things out first, I would need to enable HTTPS for the server application. This is done by first creating a self-signed Certificate Authority (CA) certificate. In brief, the CA is a trusted entity for issuing certificates. Requesting for one from the CA requires payment and takes time, therefore we generate our own cert for testing purposes.
Here is an example of creating a self signed certificate with OpenSSL:
# CA’s private key
openssl genrsa -out ca.key 4096
# self-signed certificate for CA
openssl req -new -x509 -set_serial 01 -days 365 -key ca.key -out ca.key
The first command generates a 4096 bit RSA private key, and then it is used to generate a self-signed certificate that is valid for 365 days. When executing the second command, the user would be prompted to specify the distinguished name (DN) attributes, i.e
- C – Country Name
- ST – State Name
- L – Locality Name
- O – Organisation Name
- OU – Organisational Unit Name
- CN – Common Name
Each attributes are important for the unique identification of a certificate. As for the server and client certificates, they would also need to generate their own RSA private keys and use it to generate a Certificate Signing Request (CSR), containing their corresponding public key as well as the DN attributes specified by the user like before, so that they could receive a certificate that is signed by a trusted CA. This can be easily done with OpenSSL too:
# Generate private key and Certificate Signing Request (CSR) for server
openssl req -newkey rsa:4096 -keyout server.key -out server.csr -nodes
The same command is used for client as well. Now, the CA needs to generate the certificate according to the CSR and have it signed with their own signature, like so:
# Generate server’s public certificate, signed by our CA
openssl x509 -req -set_serial 02 -days 365 -in server.csr -CA ca.crt -CAkey ca.key -out server.crt
The client certificate would be signed by our CA as well. To import the client certificate into the browser, it needs to be in PKCS#12 file format, where the file contains both the certificate as well as the private key encrypted in it:
# Bundle client cert and key in PKCS#12 format
openssl pkcs12 -export -clcerts -in client.crt -inkey client.key -out client.p12
The OpenSSL is a great command line utility for this purposes. Alternatively, you can use a GUI software to generate keys and certs as well, like XCA as shown by Dr Shawn to me.
After doing all of that, it was time to test. So having the server application running a separate port for HTTPS connections, with the browser I basically issue a GET request to a designated auth endpoint, which is responsible for extracting the information from the given client certificate. At the moment, the information I’m looking for is the name of the user and his or her email address. By giving a valid certificate to the server, i.e signed by our own CA certificate, the server application was able to parse certificate and get the values of the DN attributes but the email address from the certificate was nowhere to be found. According to the Wt documentation, it is only limited to a set of DN attributes, which is not including the email address. But I still asked Dr Shawn for help.
The first thing he pointed out to me was that I only had specified the CN attribute in the client certificate, but now I learned that it is important for the other DN attributes to be specified as well. Secondly, he showed me that the email address is actually within the CN, although it seem like a separate attribute especially during the CSR prompt. Despite getting to know all that, the email address was still not there when parsing the attributes in Wt. He then suggested to get the PEM textual format of the cert and pass it to Poco’s x509 API in hopes that the email address could be obtained. However, going through all that trouble just for a single email address seems unnecessary. We wanted to use the email address solely for the Gravatar service, but is that just it? So at the moment I’ll just get the user’s name from the CN attribute.
Otherwise, if no certificate was given or is invalid, then the user would be redirected to the web store to buy a certificate or renew their existing certificate. That is it for this blog post.