Search code examples
c++qtoauth-2.0google-oauth

Can't get OAuth 2.0 code in Qt app, but is seems to work in browser


I'm trying to configure communication with Google OAuth 2.0 in my Qt project. I was using this tutorial, although it seems to be a bit outdated. I configured everything in Google APIs site, used those data in Credentials/OAuth 2.0 Client IDs page:

enter image description here

Header file:

#ifndef GOOGLEAUTH_H
#define GOOGLEAUTH_H

#include <QObject>
#include <QOAuth2AuthorizationCodeFlow>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QUrl>
#include <QUrlQuery>
#include <QOAuthHttpServerReplyHandler>
#include <QDesktopServices>

class GoogleAuth : public QObject
{
    Q_OBJECT
public:
    explicit GoogleAuth(QObject *parent = nullptr);
    Q_INVOKABLE void click();    

private:
    QOAuth2AuthorizationCodeFlow google;
};

#endif // GOOGLEAUTH_H

Source file:

#include "GoogleAuthenticator.h"

GoogleAuth::GoogleAuth(QObject *parent) : QObject(parent)
{
    google.setScope("email");

    connect(&google, &QOAuth2AuthorizationCodeFlow::authorizeWithBrowser, [=](QUrl url) {
        QUrlQuery query(url);

        query.addQueryItem("prompt", "consent");      
        query.addQueryItem("access_type", "offline");
        query.addQueryItem("nonce", "123456");
        url.setQuery(query);
        QDesktopServices::openUrl(url);
    });    

    google.setAuthorizationUrl(QUrl("https://accounts.google.com/o/oauth2/auth"));
    google.setAccessTokenUrl(QUrl("https://oauth2.googleapis.com/token"));
    google.setClientIdentifier("<client_id>");
    google.setClientIdentifierSharedKey("<client_secret>");

    auto replyHandler = new QOAuthHttpServerReplyHandler(5476, this);
    google.setReplyHandler(replyHandler);

    connect(&google, &QOAuth2AuthorizationCodeFlow::granted, [=]() {
        qDebug() << "Access Granted!";
    });
}

void GoogleAuth::click()
{
    google.grant();
}

When I run click() method browser opens, I can log into Google account and then it redirects me to the page with following message:

Callback received. Feel free to close this page.

I can even see the code I need in the URL (at least I think it is that code?).

The problem is I don't get proper callback in Qt app. When above page with callback message is loaded, I just get this output in Qt Creator:

qt.networkauth.oauth2: Unexpected call
qt.networkauth.replyhandler: Error transferring https://oauth2.googleapis.com/token - server replied: Bad Request

Outside the app it seems to be working, I checked it on this page.

How to solve that propblem? Can I get more detailed info about that bad request?


Solution

  • I have tested the example and strangely it does not work for the "email" scope, after analyzing the http request I found that the problem is the encoding of the "code" received and that it is used to obtain the token. So my solution is to correct that parameter and that can be done override the requestAccessToken() method or use setModifyParametersFunction(), in this case use the latter:

    google.setModifyParametersFunction([](QAbstractOAuth::Stage stage,
                                       QVariantMap* parameters)
    {
        if(stage == QAbstractOAuth::Stage::RequestingAccessToken){
            QByteArray code = parameters->value("code").toByteArray();
            (*parameters)["code"] = QUrl::fromPercentEncoding(code);
        }
    });