Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-133905

QOAuth2AuthorizationCodeFlow does not open web server listening when app is backgrounded (which always is)

    XMLWordPrintable

Details

    • Bug
    • Resolution: Out of scope
    • P2: Important
    • None
    • 6.8.2
    • None
    • Android, iOS/tvOS/watchOS
    • Foundation Sprint 125, Foundation Sprint 126

    Description

      Hello,

       

      I am porting old (only fe months, I think that time was 6.5 or 6.6) code to new app and its not working anymore.

      Problem is, that once i run Workflow, browser properly opens for google auth website, i enter email, pass, and then its loading forever for my redirect url... however as soon as I get the app to foreground, the browser properly pickup the redirect url and opens it...

       

      Code is:

      Cmake:

      ..
      find_package(Qt6 REQUIRED COMPONENTS Network)
      find_package(Qt6 REQUIRED COMPONENTS NetworkAuth)
      ..
      target_link_libraries(${TARGET_NAME} PRIVATE Qt6::Network)
      target_link_libraries(${TARGET_NAME} PRIVATE Qt6::NetworkAuth)
      ..
      

       

       

      main.cpp:

      ..
      #include <auth.h>
       
      int main(int argc, char *argv[])
      {
        ...
        QQmlApplicationEngine engine;
        GoogleSSO googleAuth;
        engine.rootContext()->setContextProperty("GoogleSSO", &googleAuth);
        ...
        engine.load(url);
        return app.exec();
      }
      

       

       

      auth.h:

      #ifndef AUTH_H
      #define AUTH_H
      #include <QObject>
      #include <QOAuth2AuthorizationCodeFlow>
      #include <QNetworkAccessManager>
      #include <QNetworkReply>
      #include <QNetworkRequest>
      #include <QUrl>
      #include <QUrlQuery>
      #include <QOAuthHttpServerReplyHandler>
      #include <QDesktopServices>
      #include <QString>
      #include <QByteArray>
      #include <QTime>
      #include <QFile>
      #include <QDir>
      #include <QAbstractOAuth>
      #include <QJsonDocument>
      #include <QJsonObject>
      #include <QJsonArray>
      
      class GoogleSSO : public QObject
      {
        Q_OBJECT
      public:
        explicit GoogleSSO(QObject *parent = nullptr);
        virtual ~GoogleSSO();
      
      public slots:
        Q_INVOKABLE void authenticate();
      
      private:
        QOAuth2AuthorizationCodeFlow *google;
        QString generateRandomString() { return "xxxxxx"; }
        QString replyMessage = "<html>you were properly logged in, you can close the browser and return to the application</b>,<br>unfortunately i can not close this browser myself, you must do it and navigate back to your app</html>";
      };
      #endif // AUTH_H

       
       
      auth_google.cpp:

      #include "auth.h"
      
      GoogleSSO::GoogleSSO(QObject *parent) : QObject(parent)
      {
        this->google = new QOAuth2AuthorizationCodeFlow(this);
        this->google->setScope("https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile");
      
        // Connect to Browser Listener
        QObject::connect(this->google, &QOAuth2AuthorizationCodeFlow::authorizeWithBrowser, &QDesktopServices::openUrl);
      
        this->google->setClientIdentifier("93________66-i0ik1q__________a5oks84alinuaujp.apps.googleusercontent.com");
      
        const QUrl redirectUri("http://127.0.0.1:5476/");
        const auto port = static_cast<quint16>(redirectUri.port());
      
        this->google->setState(generateRandomString());
        this->google->responseType() = "code";
        this->google->setAuthorizationUrl(QUrl("https://accounts.google.com/o/oauth2/v2/auth"));
        this->google->setAccessTokenUrl(QUrl("https://oauth2.googleapis.com/token"));
        this->google->setClientIdentifierSharedKey("MCZ__________kArIQdkZC6q");
      
        QOAuthHttpServerReplyHandler* replyHandler = new QOAuthHttpServerReplyHandler(port, this);
        replyHandler->setCallbackText(replyMessage);
        this->google->setReplyHandler(replyHandler);
      
        this->google->setModifyParametersFunction([redirectUri](QAbstractOAuth::Stage stage, QMultiMap<QString, QVariant>* parameters) {
      
          //qDebug() << "modifyParametersFunction stage=" << static_cast<int>(stage);
          if (stage == QAbstractOAuth::Stage::RequestingAuthorization) {
      
            // The only way to get refresh_token from Google Cloud
            parameters->insert("access_type", "offline"); // Needed for Refresh Token (as AccessToken expires shortly)
            parameters->insert("prompt", "consent"); // Param required to get data everytime
            //parameters->replace("redirect_uri", redirectUri);        // not working... initaly intended to change redirect uri from https (which is needed for facebook, apple, etc) to http
          }
          else if (stage == QAbstractOAuth::Stage::RequestingAccessToken) {
            // Percent-decode the "code" parameter so Google can match it
            QByteArray code = parameters->value("code").toByteArray();
            parameters->replace("code", QUrl::fromPercentEncoding(code)); // need to fix the URL syntaxt to manage spaces
          }
        });
      
        QObject::connect(this->google, &QOAuth2AuthorizationCodeFlow::granted, [=](){
          //qDebug() << __FUNCTION__ << __LINE__ << "Access Granted!";
      
          // send the token to receive needed info
          QNetworkRequest req; req.setUrl(QUrl("https://people.googleapis.com/v1/people/me?personFields=emailAddresses,photos,names&access_token=" + this->google->token()));
          QNetworkAccessManager* manager = new QNetworkAccessManager();
          QNetworkReply* rep = manager->get(req);
          QObject::connect(manager, &QNetworkAccessManager::finished, [this](QNetworkReply* reply) {
            QByteArray serverReply = reply->readAll();
            //qDebug() << "result:" << serverReply;
            reply->deleteLater();
          });
        });
      }
      
      GoogleSSO::~GoogleSSO() { delete this->google; }
      
      // Invoked externally to initiate
      void GoogleSSO::authenticate() { this->google->grant(); }

       
       

      from QML i call it via:

      GoogleSSO.authenticate();

       

      so again... what it does, opens the browser, to google oatuh webside, i enter email, password to authenticate... and at the point it shall redirect me to redirecturl (which is "http://127.0.0.1:5476/") but it doesnt... google webside redirects me there, but the browser loads it forever, and as soon as i go back to the app wich is backgrounded, then it properly finishes the process and browser redirects to that 127.0.0.1:5476 url

       

      eventualy i will have the error like:

       

      if I compile for windows, it works properly because app is noe being backgrounded when browser is opened.

       

      Android api i u se still same 34, so no change in android version permission

      Attachments

        Issue Links

          No reviews matched the request. Check your Options in the drop-down menu of this sections header.

          Activity

            People

              vuokko Juha Vuolle
              shokarta Jiri Zaloudek
              Vladimir Minenko Vladimir Minenko
              Alex Blasche Alex Blasche
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Gerrit Reviews

                  There are no open Gerrit changes