HTTPS with QT?



  • Hi,

    I am trying to build an application for the Spark Core https://www.spark.io/

    In order to do so, I need to acquire an access key and token as shown here:

    http://docs.spark.io/api/#authentication-generate-a-new-access-token

    I can figure out how to send an HTTP POST using QT, but I am not sure how to handle sending an HTTPS POST because I'm pretty sure it uses SSL, and when I searched online for examples on how to do this, I became very confused, the code seems long and is very hard to understand. I am not even sure which class(es) I need:

    QHttp
    QHttpPart
    QUrl
    QNetworkAccessManager
    QNetworkReply
    QSslSocket
    QTcp . ...
    etc.

    I appreciate any help anyone could give me in how to set up this simple https post!
    Thank you guys :)


  • Moderators

    Hi @John9570,

    HTTPS POST is done exactly the same way as HTTP POST, using QNetworkAccessManager::post(). QNetworkAccessmanager takes care of the SSL layer for you.

    You simply need to include the access token in your POST data. (You might need QNetworkCookieJar for storing and retrieving cookies)



  • Thanks @JKSH !

    I tried that just not but after a few hours of searching and tinkering I'm running into an unforgiving and very non specific issue.

    Below is my code:

          manager = new QNetworkAccessManager(this);
    
         connect(manager, SIGNAL(finished(QNetworkReply*)),
                this, SLOT(replyFinished(QNetworkReply*)));
    
         connect(manager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)),
                SLOT(provideAuthenication(QNetworkReply*,QAuthenticator*)));
    
         QByteArray postData;
    
    
         postData.append("grant_type=password");
         postData.append("username=MYEMAIL");
         postData.append("password=MYPASS");
    
         manager->post(QNetworkRequest(QUrl("https://api.spark.io/oauth/token")), postData);
    
    void clientGUI::provideAuthenication(QNetworkReply *reply, QAuthenticator *ator){
        qDebug() << "INSIDE AUTH";
        qDebug() << reply->readAll(); // this is just to see what we received
        ator->setUser(QString("spark"));
        ator->setPassword(QString("spark"));
    }
    
    void clientGUI::replyFinished(QNetworkReply *reply){
        if(reply->error())
        {
            qDebug() << "ERROR!";
            qDebug() << reply->errorString();
        }
        else {
         //i print out some stuff pertaining to the message
       }
    
        reply->deleteLater();
    }
    
    
    

    On the terminal when I run this with my credentials in the code (I am planning to remove them later and extract them from a GUI) this is what I see:

    content-type missing in HTTP POST, defaulting to application/x-www-form-urlencoded. Use QNetworkRequest::setHeader() to fix this problem.
    ERROR! 
    "Error downloading https://api.spark.io/oauth/token - server replied: Bad Request" 
    

    So I never get to the Authentication part of the code.

    Basically I am trying to convert this curl https post statement to one that is equivalent in QT code:

     curl https://api.spark.io/oauth/token -u spark:spark \
     -d grant_type=password -d username=joe@example.com -d password=SuperSecret
    

    And I guess the part I'm missing is the -u spark:spark which is how curl sets a username and password for authentication.

    Thanks again for the help! And sorry for the long post, I just wanted to make sure you could see everything to help me debug this.

    EDIT: The output from the terminal saying "content-type missing ... defaulting to application/x-www-form-urlencoded. " is exactly the type I want. So why it defaults to is perfectly fine.


  • Moderators

    Hi @John9570,

    I don't have experience with the curl -u option so I don't know how it works. This might help: http://stackoverflow.com/questions/20737031/curlss-option-u

         postData.append("grant_type=password");
         postData.append("username=MYEMAIL");
         postData.append("password=MYPASS");
    

    That's the same as postData.append("grant_type=passwordusername=MYEMAILpassword=MYPASS");. I believe you need an ampersand between each parameter



  • Thanks for all the help! :D

    You were right about the ampersands, they are necessary.

    I was able to figure out how to do the -u option with the link you provided. Incase anyone else is curious, my solution looks like this:

          QString concatenated = "spark:spark";
         QByteArray data = concatenated.toLocal8Bit().toBase64();
         QString headerData = "Basic " + data;
    
    
         QNetworkRequest request;
         request.setUrl(QUrl("https://api.spark.io/oauth/token"));
    
         request.setRawHeader("Authorization", headerData.toLocal8Bit());
    

    If you look at the link, there is an " Authorization: " field, and then after that field the value is "Basic: blah blah blah", by using the code above you can set the username:password that would be set with the -u option in code, and the server will recognize it as thus. You dont need to use QAuthentication.

    ^.^


  • Lifetime Qt Champion

    Hi,

    Since it's username/password your original clientGUI::provideAuthenication should have worked however I would not have read the content of the reply just called setUser and setPassword



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