Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QNetwokrAccessManager: QNetworkReply::SslHandshakeFailedError



  • I want to read json data from a host with a predefined API with this code:

    #include "myarca.h"
    #include "ui_myarca.h"
    
    MyArca::MyArca(QWidget *parent)
        : QWidget(parent)
        , ui(new Ui::MyArca)
    {
        ui->setupUi(this);
    
        connect(ui->pushButtonGet, &QPushButton::clicked,
                this, &MyArca::on_clicked_PushButtonGet);
    
        connect(ui->pushButtonPost, &QPushButton::clicked,
                this, &MyArca::on_clicked_PushButtonPost);
    }
    
    MyArca::~MyArca()
    {
        delete ui;
    }
    
    void MyArca::on_clicked_PushButtonGet()
    {
        qDebug() << "Get";
        qDebug() << "openSSL Version:" << QSslSocket::sslLibraryBuildVersionString();
    
        QSslConfiguration sslConfiguration(QSslConfiguration::defaultConfiguration());
        sslConfiguration.setProtocol(QSsl::TlsV1_0);
    
    
        QUrl url;
        QUrl url = QUrl::.fromUserInput("https://192.20.2.101:11863/test-request/api/v1/users");
    
        QNetworkRequest request(url);
        request.setUrl(url);
        request.setRawHeader("Accept-Encoding", "gzip, deflate");
        request.setRawHeader("Content-Type", "application/json");
        request.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/json"));
    
        request.setSslConfiguration(sslConfiguration);
    
        reply = manager.get(request);
    
        connect(reply, QOverload<QNetworkReply::NetworkError>::of(&QNetworkReply::error),
            [=](QNetworkReply::NetworkError code) {
                qDebug() << "Error" << code << reply->errorString();
            }
        );
    
        connect(reply, &QNetworkReply::downloadProgress,
                this, &MyArca::on_downloadProgress);
    
        connect(reply, &QNetworkReply::readyRead,
                this, &MyArca::on_downloadReadyRead);
    
        connect(reply, &QNetworkReply::finished,
                this, &MyArca::on_downloadFinished);
    
    }
    
    void MyArca::on_clicked_PushButtonPost()
    {
        qDebug() << "Post";
    }
    
    void MyArca::on_downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
    {
        qDebug() << "bytes received" << bytesReceived;
        qDebug() << "bytes total   " << bytesTotal;
    }
    
    void MyArca::on_downloadReadyRead()
    {
        qDebug() << "ready read";
        qDebug() << reply->readAll();
    }
    
    void MyArca::on_downloadFinished()
    {
        qDebug() << "finished";
    }
    

    I get the following outputs:

    openSSL Version: "OpenSSL 1.1.1c  28 May 2019"
    Error QNetworkReply::SslHandshakeFailedError "Im Ablauf des SSL-Protokolls ist ein Fehler aufgetreten.
    bytes received 0
    bytes total    0
    finished
    

    How can I set the right protocol and which one do I have to chose from this list https://doc.qt.io/qt-5/qssl.html#SslProtocol-enum

    With this curl command I get the correct answer:

    curl -G -k -H 'Accept: application/json' https://192.20.2.101:11863/test-request/api/v1/users
    

    Or what am I doing wrong?

    Thanks for your help.


  • Lifetime Qt Champion

    Hi,

    You are missing the https in your url.

    What OS are you running ?
    What version of OpenSSL did you install ?



  • I'm running linux.
    OpenSSL 1.1.1c 28 May 2019



  • I found the solution now. I also had to add the certificate. my code looks like this now:

    void MyArca::on_clicked_PushButtonGet()
    {
        qDebug() << "Get";
        qDebug() << "openSSL Version:" << QSslSocket::sslLibraryBuildVersionString();
    
        QSslConfiguration sslConfiguration(QSslConfiguration::defaultConfiguration());
        const auto certs = QSslCertificate::fromPath("/tmp/arca.pem", QSsl::Pem, QRegExp::Wildcard);
        for (const QSslCertificate &cert : certs) {
            qDebug() << cert.issuerInfo(QSslCertificate::Organization);
        }
        sslConfiguration.setCaCertificates(certs);
        sslConfiguration.setProtocol(QSsl::AnyProtocol);
    
        QUrl url = QUrl::fromUserInput("https://192.20.2.101:11863/test-request/api/v1/users");
        qDebug() << "url" << url.toString();
    
        QNetworkRequest request(url);
        request.setSslConfiguration(sslConfiguration);
        request.setUrl(url);
        request.setRawHeader("Authorization", "Bearer <some token issued by a keycloak server>");
        request.setRawHeader("Accept-Encoding", "gzip, deflate");
        request.setRawHeader("Content-Type", "application/json");
        request.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/json"));
        request.setSslConfiguration(sslConfiguration);
    
        reply = manager.get(request);
    
        connect(reply, QOverload<QNetworkReply::NetworkError>::of(&QNetworkReply::error),
            [=](QNetworkReply::NetworkError code) {
                qDebug() << "Error" << code << reply->errorString();
            }
        );
    
        connect(reply, &QNetworkReply::downloadProgress,
                this, &MyArca::on_downloadProgress);
    
        connect(reply, &QNetworkReply::readyRead,
                this, &MyArca::on_downloadReadyRead);
    
        connect(reply, &QNetworkReply::finished,
                this, &MyArca::on_downloadFinished);
    
        connect(&manager, &QNetworkAccessManager::sslErrors, this, &MyArca::on_sslErrors);
        connect(&manager, &QNetworkAccessManager::authenticationRequired, this, &MyArca::on_authenticationRequired);
    }
    

    The server requires the Authorization Header to be set to a token.

    request.setRawHeader("Authorization", "Bearer <some keycloack token>");
    

    The token is issued by a keycloak server where the user has to login. After a successful login the keycloak server issues a token, which has to be set in the Authorization Header. With the setup I have now, I have to manually copy the token into request.setRawHeader("Authorization", "Bearer ..."); which is obviously not very convenient. Is there a way to obtain the token directly from the keycloak server? I searched around for many hours, but I couldn't find a solution. It would be great if somebody could point me in the right direction.


  • Lifetime Qt Champion

    One thing you can do is check if you have that token, if not, do the request you need to retrieve it and then continue.



  • Thanks for your help. It is working now.


Log in to reply