QNetworkRequest always returning 401 over https



  • I'm doing an https get call using a QNetworkRequest. The connection uses basic authentication. I had gotten this working with Qt 5.3.0, however, we were having other issues so I updated to 5.3.1, fixing the other issues but breaking my connection.

    Now, when making a connection I always get a 401 reply and this message "Host requires authentication."

    @bool IIntegratorConnection::doRequest(
    QString const &username, QString const &password,
    QString const &url, QString const &api) {

    QNetworkRequest request;
    QString address(url);
    if (!url.endsWith("/"))
        address.append("/");
    request.setUrl(QUrl(address.append(api)));
    
    request.setRawHeader("Authorization", 
                         "Basic " + QByteArray(QString("%1:%2").arg(
                            username).arg(password)).toUtf8().toBase64());
    
    QNetworkReply *reply = _manager.get(request);//_manager is a member QNetworkAccessManager
    QObject::connect(reply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(slotProgress(qint64,qint64)));
    return true;
    

    }

    void IIntegratorConnection::receiveReply(QNetworkReply *reply) {
    int v = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); //v is 401 here
    if (reply->error() != QNetworkReply::NoError) {
    qDebug() << "Error: " << reply->errorString() << " For URL : " << reply->url().toString(); @

    I've played around with setting the password to base64 or not. It worked as base64 in 5.3.0. Anything I'm doing obviously wrong here?


  • Lifetime Qt Champion

    Hi,

    Did you just switch Qt version ? Compile them yourself ?



  • yes I compiled them myself. I was able to figure out a workaround by catching the authenticationRequired signal on the manager.

    @QObject::connect(&_manager, &QNetworkAccessManager::authenticationRequired, this, &MyClass::fixCredentials);@

    However, to do this I have to store the username/password in the object which I'd rather not do.

    I compiled on Windows with vs 2012.


  • Lifetime Qt Champion

    Did you compile both 5.3.1 and 5.3.0 ?

    If so, can you create a minimal compilable example that shows the behavior difference ?



  • I made a simple example to test this and of course now it's not working in 5.3.0 anymore either!

    header (gets mocced)

    @#include <QNetworkAccessManager>
    #include <QNetworkReply>
    #include <QAuthenticator>
    #include <QObject>

    struct Connection : public QObject {
    Q_OBJECT
    public:
    QNetworkAccessManager manager;
    QString _username, _password;
    Connection();
    signals:
    void finished();
    private slots:
    void receiveReply(QNetworkReply *);
    void fixCredentials(QNetworkReply *reply, QAuthenticator *authenticator);

    };@

    implementation

    @#include "Connection.h"
    #include "Connection.moc"
    #include <QApplication>
    #include <QJsonDocument>

    Connection::Connection() {
    QObject::connect(&manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(receiveReply(QNetworkReply*)));
    // QObject::connect(&manager, &QNetworkAccessManager::authenticationRequired, this, &Connection::fixCredentials);
    _username = "username";
    _password = "pass";
    QString address = "url";
    QString api = "v1/projects/";
    QNetworkRequest request;
    if (!address.endsWith("/"))
    address.append("/");
    request.setUrl(QUrl(address.append(api)));

    request.setRawHeader("Authorization", 
                         "Basic " + QByteArray(QString("%1:%2").arg(
                            _username).arg(_password).toUtf8().toBase64()));
    
    QNetworkReply *reply = manager.get(request);
    

    }

    void Connection::receiveReply(QNetworkReply *reply) {
    reply->deleteLater();
    int v = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
    if (reply->error() != QNetworkReply::NoError) {
    qDebug() << "Error: " << reply->errorString() << " For URL : " << reply->url().toString();
    } else {
    if (v >= 400 || v < 200) {
    qDebug() << "Error" << reply->error();
    emit finished();
    } else if (v >= 200 && v < 300) {
    //handle data
    QString text;
    text = reply->readAll();
    QJsonDocument jsonResponse = QJsonDocument::fromJson(text.toUtf8());
    qDebug() << jsonResponse;
    emit finished();
    } else {
    // Get the redirection url
    QUrl newUrl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
    // Because the redirection url can be relative,
    // we have to use the previous one to resolve it
    newUrl = reply->url().resolved(newUrl);

            QNetworkAccessManager *manager = reply->manager();
            QNetworkRequest redirection(newUrl);
            QNetworkReply *newReply = manager->get(redirection);
    
            return; // to keep the manager for the next request
        }
    }
    

    }

    void Connection::fixCredentials(QNetworkReply *reply, QAuthenticator *authenticator) {
    authenticator->setUser(_username);
    authenticator->setPassword(_password);
    }

    int main(int argc, char **argv) {
    QApplication app(argc, argv);
    Connection connect;
    QObject::connect(&connect, &Connection::finished, &app, &QCoreApplication::quit);

    return app.exec();
    

    }@

    It runs ok if i make use of my fixCredentials method.

    We're building Qt by following the instructions "here":https://github.com/MiraGeoscience/developmentCycle/wiki/Build-Qt (based on the instructions in the qt wiki for building from git).



  • I recently added the -no-accessibility option to our Qt build. I'm wondering if I had it working on 5.3.0 before rebuilding without that option... I'll have to build again to test.


  • Lifetime Qt Champion

    Also, check whether the server changed it's authentication scheme



  • The devs claim nothing's changed...are they trustworthy? Doubtful ;)


  • Lifetime Qt Champion

    You can verify this with e.g. chrome's Postman application :-)


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.