3.2.2016
The usual approach to log in to a web applications is to request username and password. This approach is risky when using unsecured HTTP protocol. Anyone listing to your network traffic can easily read your password using application like tcpdump or wireshark.
This is not good. Of course you do not want to give access to your bank account to unknown attacker. We do not produce bank applications but unpleasant may be event just the fact that someone change settings of your home wifi. Therefore, it is good practice to encrypt sensitive network traffic.
Read earlier article about HTTP SSL server for C++ and Qt
SSL support in HTTP server for C++ and Qt
To encrypt the connection the SSL is commonly used. But it can offer you more then just encryption. If you are relying solely on encryption, you were in the same situation as without encryption at all. Attacker's situation becomes little complicated because he cannot use simple tcpdump or wireshark now but against a computer bandit established in the middle of your internet connection you were still powerless. For such a bandit it would be very easy to impersonate your bank. Instead of talking to bank you were talking to intruder, in fact. Your password to you hard-earned money could be compromised on en encrypted channel, too. To avoid such a situation, you need to be sure that you are talking to real bank. In the real world, is's easy - bank is available at its usual location and you can easily recognize bank clerk from masked robber. On the internet you have no such security, but you can secure the connection in another way.
If you want to be sure you are talking to bank, you have to ensure two things:
The role of id cards in computer world play SSL certificates and keys. Validity of the id card (know how the id card looks like) ensures certification authorities.
The situation is reversible - the same procedure, thus checking ID card, the bank can verify that you are really you.
It you have verified bank's id and the bank verified your id, it is needless to require passwords. And that's another thing the SSL offers to you. It is possible to log in to the internet application without password.
Server has few parameters which configure encryption:
[http] useSSL = true sslKey = /etc/ssl/private/mysite.bravenec.eu.key.pem sslCrt = /etc/ssl/private/mysite.bravenec.eu.crt.pem sslCaCrt = /etc/ssl/private/hobrasoft.crt.pem
Parameter sslKey and sslCrt are sufficient to create encrypted connection. Next parameter sslCaCrt is the certificate which should be used to sign client's certificate to be considered credible.
In the application using Hobrasoft httpd server call method HttpConnection::verified() to ensure that the client's certificate was issued by known certification authority. Class HttpConnection has also other methods to access client's certificate:
There are a lot of browsers. This is the procedure for Chrome:
The server application should identify you using your certificate. If you have written the server's controller properly, no username and password should be required.
Curl is a small utility for accessing HTTP sites from the command line.
Curl requires key and certificate in PEM format:
curl \ --cacert hobrasoft.crt.pem \ --cert bravenec.crt.pem \ --key bravenec.key.pem \ -v -X GET https://weblight.bravenec.eu:8099/
Qt applications use class QNetworkAccessManger to access http server. The class works asynchronously, each request needs separated instance of QNetworkRequest. The class requires SSL configuration in QSslConfiguration instance:
QNetworkAccesManager *manager = new QNetworkAccessManager() // ... manager setting - connections to slots... // Default configuration QSslConfiguration configuration = QSslConfiguration::defaultConfiguration(); // CA certificates are replaced with own certificate QListcaCertificates; QFile fileca("hobrasoft.crt.pem"); filecea.open(QIODevice::ReadOnly); caCertificates << QSslCertificate(fileca); configuration.setCaCertificates(caCertificates); // Client's private key QFile filekey("bravenec.key.pem"); filekey.open(QIODevice::ReadOnly); QSslKey key = QSslKey(filekey); configuration.setPrivateKey(key); // Client's certificate QFile filecrt("bravenec.crt.pem"); filecrt.open(QIODevice::ReadOnly); QSslCertificate crt = QSslCertificate(filecrt); configuration.setLocalCertificate(crt); // Create request and attach ssl configuration to it QNetworkRequest request(QUrl("https://weblight.bravenec.eu:8099")); request.setSslConfiguration(configuration); // Pass the request to QNetworkAccessManager QNetworkReply *reply = manager->get(request);
There is only idicated how to use QNetworkAccessManager. Real use is something more complex.
This procedure will only work if everything is properly set up, certificates are valid and the server exactly matches the name in the certificate.
If you try to connect to http server with different name then set in certificate, then the authentication fail on the client's side. Then you have to suppress the server verification in your code:
configuration.setPeerVerifyMode(QSslSocket::VerifyMone);
You should always catch signal QNetworkAccessManager::sslErrors(QNetworkReply *, QList<QSslError>). Error can be ignored calling QNetworkReply::ignoreSslErrors() in the connecte slot. Please, consider carefully which errors to ignore and ask the user. Ignoring SSL errors can lead to serious security issues.
Authentication by certificate is not common practice in usual web application. I real world the authentication is used for example to access time stamp certification authorities. This case usually requires specialized application.
You can use authentication in situations where various devices are communicating and it is appropriate to avoid user and password management.