From 62f46375df1659e0b91eb9b6ff7a12592e6882d7 Mon Sep 17 00:00:00 2001 From: Camila Ayres Date: Mon, 31 Mar 2025 20:29:40 +0200 Subject: [PATCH 1/8] chore(Flow2Auth): modernize fetchNewToken. Signed-off-by: Camila Ayres --- src/gui/creds/flow2auth.cpp | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/src/gui/creds/flow2auth.cpp b/src/gui/creds/flow2auth.cpp index b3cc7c937ac41..75b35dcf6c0eb 100644 --- a/src/gui/creds/flow2auth.cpp +++ b/src/gui/creds/flow2auth.cpp @@ -67,8 +67,9 @@ void Flow2Auth::copyLinkToClipboard() void Flow2Auth::fetchNewToken(const TokenAction action) { - if(_isBusy) + if(_isBusy) { return; + } _isBusy = true; _hasToken = false; @@ -76,21 +77,21 @@ void Flow2Auth::fetchNewToken(const TokenAction action) emit statusChanged(PollStatus::statusFetchToken, 0); // Step 1: Initiate a login, do an anonymous POST request - QUrl url = Utility::concatUrlPath(_account->url().toString(), QLatin1String("/index.php/login/v2")); - _enforceHttps = url.scheme() == QStringLiteral("https"); + const auto loginV2url = Utility::concatUrlPath(_account->url().toString(), QLatin1String("/index.php/login/v2")); + _enforceHttps = loginV2url.scheme() == QStringLiteral("https"); // add 'Content-Length: 0' header (see https://github.com/nextcloud/desktop/issues/1473) - QNetworkRequest req; - req.setHeader(QNetworkRequest::ContentLengthHeader, "0"); - req.setHeader(QNetworkRequest::UserAgentHeader, Utility::friendlyUserAgentString()); + QNetworkRequest request; + request.setHeader(QNetworkRequest::ContentLengthHeader, "0"); + request.setHeader(QNetworkRequest::UserAgentHeader, Utility::friendlyUserAgentString()); - auto job = _account->sendRequest("POST", url, req); + auto job = _account->sendRequest("POST", loginV2url, request); job->setTimeout(qMin(30 * 1000ll, job->timeoutMsec())); QObject::connect(job, &SimpleNetworkJob::finishedSignal, this, [this, action](QNetworkReply *reply) { - auto jsonData = reply->readAll(); + const auto jsonData = reply->readAll(); QJsonParseError jsonParseError{}; - QJsonObject json = QJsonDocument::fromJson(jsonData, &jsonParseError).object(); + const auto json = QJsonDocument::fromJson(jsonData, &jsonParseError).object(); QString pollToken, pollEndpoint, loginUrl; if (reply->error() == QNetworkReply::NoError && jsonParseError.error == QJsonParseError::NoError @@ -108,8 +109,8 @@ void Flow2Auth::fetchNewToken(const TokenAction action) if (reply->error() != QNetworkReply::NoError || jsonParseError.error != QJsonParseError::NoError || json.isEmpty() || pollToken.isEmpty() || pollEndpoint.isEmpty() || loginUrl.isEmpty()) { QString errorReason; - QString errorFromJson = json["error"].toString(); - if (!errorFromJson.isEmpty()) { + if (const auto errorFromJson = json["error"].toString(); + !errorFromJson.isEmpty()) { errorReason = tr("Error returned from the server: %1") .arg(errorFromJson.toHtmlEscaped()); } else if (reply->error() != QNetworkReply::NoError) { @@ -128,12 +129,11 @@ void Flow2Auth::fetchNewToken(const TokenAction action) return; } - _loginUrl = loginUrl; if (_account->isUsernamePrefillSupported()) { - const auto userName = Utility::getCurrentUserName(); - if (!userName.isEmpty()) { + if (const auto userName = Utility::getCurrentUserName(); + !userName.isEmpty()) { auto query = QUrlQuery(_loginUrl); query.addQueryItem(QStringLiteral("user"), userName); _loginUrl.setQuery(query); @@ -143,22 +143,19 @@ void Flow2Auth::fetchNewToken(const TokenAction action) _pollToken = pollToken; _pollEndpoint = pollEndpoint; - // Start polling - ConfigFile cfg; - std::chrono::milliseconds polltime = cfg.remotePollInterval(); + std::chrono::milliseconds polltime = ConfigFile().remotePollInterval(); qCInfo(lcFlow2auth) << "setting remote poll timer interval to" << polltime.count() << "msec"; _secondsInterval = (polltime.count() / 1000); _secondsLeft = _secondsInterval; emit statusChanged(PollStatus::statusPollCountdown, _secondsLeft); - if(!_pollTimer.isActive()) { + if (!_pollTimer.isActive()) { _pollTimer.start(); } - switch(action) - { + switch(action) { case actionOpenBrowser: // Try to open Browser if (!Utility::openBrowser(authorisationLink())) { From 75243fc20be9bb4aa2bf9b244b893f7a93f0dc22 Mon Sep 17 00:00:00 2001 From: Camila Ayres Date: Mon, 31 Mar 2025 20:51:59 +0200 Subject: [PATCH 2/8] chore(Flow2Auth): modernize slotPollTimerTimeout. Signed-off-by: Camila Ayres --- src/gui/creds/flow2auth.cpp | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/gui/creds/flow2auth.cpp b/src/gui/creds/flow2auth.cpp index 75b35dcf6c0eb..a8d35b4fd7d76 100644 --- a/src/gui/creds/flow2auth.cpp +++ b/src/gui/creds/flow2auth.cpp @@ -177,8 +177,9 @@ void Flow2Auth::fetchNewToken(const TokenAction action) void Flow2Auth::slotPollTimerTimeout() { - if(_isBusy || !_hasToken) + if(_isBusy || !_hasToken) { return; + } _isBusy = true; @@ -191,20 +192,20 @@ void Flow2Auth::slotPollTimerTimeout() emit statusChanged(PollStatus::statusPollNow, 0); // Step 2: Poll - QNetworkRequest req; - req.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded"); + QNetworkRequest request; + request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded"); auto requestBody = new QBuffer; QUrlQuery arguments(QStringLiteral("token=%1").arg(_pollToken)); requestBody->setData(arguments.query(QUrl::FullyEncoded).toLatin1()); - auto job = _account->sendRequest("POST", _pollEndpoint, req, requestBody); + auto job = _account->sendRequest("POST", _pollEndpoint, request, requestBody); job->setTimeout(qMin(30 * 1000ll, job->timeoutMsec())); QObject::connect(job, &SimpleNetworkJob::finishedSignal, this, [this](QNetworkReply *reply) { - auto jsonData = reply->readAll(); + const auto jsonData = reply->readAll(); QJsonParseError jsonParseError{}; - QJsonObject json = QJsonDocument::fromJson(jsonData, &jsonParseError).object(); + const QJsonObject json = QJsonDocument::fromJson(jsonData, &jsonParseError).object(); QUrl serverUrl; QString loginName, appPassword; @@ -223,8 +224,8 @@ void Flow2Auth::slotPollTimerTimeout() if (reply->error() != QNetworkReply::NoError || jsonParseError.error != QJsonParseError::NoError || json.isEmpty() || serverUrl.isEmpty() || loginName.isEmpty() || appPassword.isEmpty()) { QString errorReason; - QString errorFromJson = json["error"].toString(); - if (!errorFromJson.isEmpty()) { + if (const QString errorFromJson = json["error"].toString(); + !errorFromJson.isEmpty()) { errorReason = tr("Error returned from the server: %1") .arg(errorFromJson.toHtmlEscaped()); } else if (reply->error() != QNetworkReply::NoError) { @@ -239,8 +240,9 @@ void Flow2Auth::slotPollTimerTimeout() qCDebug(lcFlow2auth) << "Error when polling for the appPassword" << json << errorReason; // We get a 404 until authentication is done, so don't show this error in the GUI. - if(reply->error() != QNetworkReply::ContentNotFoundError) + if (reply->error() != QNetworkReply::ContentNotFoundError) { emit result(Error, errorReason); + } // Forget sensitive data appPassword.clear(); From 66b3c5fdd8f8ff4056932188e43270dfff6eaa7d Mon Sep 17 00:00:00 2001 From: Camila Ayres Date: Mon, 31 Mar 2025 21:25:12 +0200 Subject: [PATCH 3/8] chore(Flow2Auth): modernize slotPollNow. Signed-off-by: Camila Ayres --- src/gui/creds/flow2auth.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gui/creds/flow2auth.cpp b/src/gui/creds/flow2auth.cpp index a8d35b4fd7d76..3c7e68b12353f 100644 --- a/src/gui/creds/flow2auth.cpp +++ b/src/gui/creds/flow2auth.cpp @@ -279,8 +279,9 @@ void Flow2Auth::slotPollTimerTimeout() void Flow2Auth::slotPollNow() { // poll now if we're not already doing so - if(_isBusy || !_hasToken) + if(_isBusy || !_hasToken) { return; + } _secondsLeft = 1; slotPollTimerTimeout(); From e98ab1a2dd14c408d6d95cc125471a7a97c13bd0 Mon Sep 17 00:00:00 2001 From: Camila Ayres Date: Tue, 1 Apr 2025 19:21:42 +0200 Subject: [PATCH 4/8] chore(Flow2Auth): modernize slotPollTimerTimeout. Move part of the server repsonse logic to another function. Signed-off-by: Camila Ayres --- src/gui/creds/flow2auth.cpp | 88 ++++++++++++++++++++++--------------- src/gui/creds/flow2auth.h | 3 ++ 2 files changed, 55 insertions(+), 36 deletions(-) diff --git a/src/gui/creds/flow2auth.cpp b/src/gui/creds/flow2auth.cpp index 3c7e68b12353f..d5c906d9946aa 100644 --- a/src/gui/creds/flow2auth.cpp +++ b/src/gui/creds/flow2auth.cpp @@ -67,7 +67,7 @@ void Flow2Auth::copyLinkToClipboard() void Flow2Auth::fetchNewToken(const TokenAction action) { - if(_isBusy) { + if (_isBusy) { return; } @@ -177,7 +177,7 @@ void Flow2Auth::fetchNewToken(const TokenAction action) void Flow2Auth::slotPollTimerTimeout() { - if(_isBusy || !_hasToken) { + if (_isBusy || !_hasToken) { return; } @@ -203,47 +203,17 @@ void Flow2Auth::slotPollTimerTimeout() job->setTimeout(qMin(30 * 1000ll, job->timeoutMsec())); QObject::connect(job, &SimpleNetworkJob::finishedSignal, this, [this](QNetworkReply *reply) { - const auto jsonData = reply->readAll(); - QJsonParseError jsonParseError{}; - const QJsonObject json = QJsonDocument::fromJson(jsonData, &jsonParseError).object(); + const QJsonObject json = handleRequest(reply); QUrl serverUrl; QString loginName, appPassword; - if (reply->error() == QNetworkReply::NoError && jsonParseError.error == QJsonParseError::NoError - && !json.isEmpty()) { + if (!json.isEmpty()) { serverUrl = json["server"].toString(); - if (_enforceHttps && serverUrl.scheme() != QStringLiteral("https")) { - qCWarning(lcFlow2auth) << "Returned server url" << serverUrl << "does not start with https"; - emit result(Error, tr("The returned server URL does not start with HTTPS despite the login URL started with HTTPS. Login will not be possible because this might be a security issue. Please contact your administrator.")); - return; - } loginName = json["loginName"].toString(); appPassword = json["appPassword"].toString(); } - if (reply->error() != QNetworkReply::NoError || jsonParseError.error != QJsonParseError::NoError - || json.isEmpty() || serverUrl.isEmpty() || loginName.isEmpty() || appPassword.isEmpty()) { - QString errorReason; - if (const QString errorFromJson = json["error"].toString(); - !errorFromJson.isEmpty()) { - errorReason = tr("Error returned from the server: %1") - .arg(errorFromJson.toHtmlEscaped()); - } else if (reply->error() != QNetworkReply::NoError) { - errorReason = tr("There was an error accessing the \"token\" endpoint:
%1") - .arg(reply->errorString().toHtmlEscaped()); - } else if (jsonParseError.error != QJsonParseError::NoError) { - errorReason = tr("Could not parse the JSON returned from the server:
%1") - .arg(jsonParseError.errorString()); - } else { - errorReason = tr("The reply from the server did not contain all expected fields"); - } - qCDebug(lcFlow2auth) << "Error when polling for the appPassword" << json << errorReason; - - // We get a 404 until authentication is done, so don't show this error in the GUI. - if (reply->error() != QNetworkReply::ContentNotFoundError) { - emit result(Error, errorReason); - } - + if (json.isEmpty() || serverUrl.isEmpty() || loginName.isEmpty() || appPassword.isEmpty()) { // Forget sensitive data appPassword.clear(); loginName.clear(); @@ -276,10 +246,56 @@ void Flow2Auth::slotPollTimerTimeout() }); } +QJsonObject Flow2Auth::handleRequest(QNetworkReply *reply) +{ + const auto jsonData = reply->readAll(); + QJsonParseError jsonParseError{}; + const auto json = QJsonDocument::fromJson(jsonData, &jsonParseError).object(); + + if (reply->error() == QNetworkReply::NoError && jsonParseError.error == QJsonParseError::NoError + && !json.isEmpty()) { + const QUrl serverUrl = json["server"].toString(); + if (_enforceHttps && serverUrl.scheme() != QStringLiteral("https")) { + qCWarning(lcFlow2auth) << "Returned server url" << serverUrl << "does not start with https"; + emit result(Error, tr("The returned server URL does not start with HTTPS despite the login URL started with HTTPS. Login will not be possible because this might be a security issue. Please contact your administrator.")); + return {}; + } + } + + if (reply->error() != QNetworkReply::NoError || jsonParseError.error != QJsonParseError::NoError) { + QString errorReason; + if (const QString errorFromJson = json["error"].toString(); + !errorFromJson.isEmpty()) { + errorReason = tr("Error returned from the server: %1") + .arg(errorFromJson.toHtmlEscaped()); + } else if (reply->error() != QNetworkReply::NoError) { + errorReason = tr("There was an error accessing the \"token\" endpoint:
%1") + .arg(reply->errorString().toHtmlEscaped()); + } else if (jsonParseError.error != QJsonParseError::NoError) { + errorReason = tr("Could not parse the JSON returned from the server:
%1") + .arg(jsonParseError.errorString()); + } else if (json.isEmpty()) { + errorReason = tr("The reply from the server did not contain all expected fields") + .arg(jsonParseError.errorString()); + } + + qCDebug(lcFlow2auth) << "Error when requesting:" << reply->url() << "- json returned:" << json << "- error:" << errorReason; + + // We get a 404 until authentication is done, so don't show this error in the GUI. + if (reply->error() != QNetworkReply::ContentNotFoundError) { + emit result(Error, errorReason); + } + + return {}; + } + + return json; +} + void Flow2Auth::slotPollNow() { // poll now if we're not already doing so - if(_isBusy || !_hasToken) { + if (_isBusy || !_hasToken) { return; } diff --git a/src/gui/creds/flow2auth.h b/src/gui/creds/flow2auth.h index adac4d39bb1ad..4d4c05a012a9f 100644 --- a/src/gui/creds/flow2auth.h +++ b/src/gui/creds/flow2auth.h @@ -19,6 +19,8 @@ #include #include "accountfwd.h" +class QNetworkReply; + namespace OCC { /** @@ -71,6 +73,7 @@ private slots: private: void fetchNewToken(const TokenAction action); + [[nodiscard]] QJsonObject handleRequest(QNetworkReply *reply); Account *_account; QUrl _loginUrl; From b94bb91a44b2265970678586d4578756ae399209 Mon Sep 17 00:00:00 2001 From: Camila Ayres Date: Tue, 1 Apr 2025 19:27:29 +0200 Subject: [PATCH 5/8] chore(Flow2Auth): modernize fetchNewToken. Move part of the server repsonse logic to another function. Signed-off-by: Camila Ayres --- src/gui/creds/flow2auth.cpp | 34 ++++------------------------------ 1 file changed, 4 insertions(+), 30 deletions(-) diff --git a/src/gui/creds/flow2auth.cpp b/src/gui/creds/flow2auth.cpp index d5c906d9946aa..4bef0d3199fa9 100644 --- a/src/gui/creds/flow2auth.cpp +++ b/src/gui/creds/flow2auth.cpp @@ -89,41 +89,16 @@ void Flow2Auth::fetchNewToken(const TokenAction action) job->setTimeout(qMin(30 * 1000ll, job->timeoutMsec())); QObject::connect(job, &SimpleNetworkJob::finishedSignal, this, [this, action](QNetworkReply *reply) { - const auto jsonData = reply->readAll(); - QJsonParseError jsonParseError{}; - const auto json = QJsonDocument::fromJson(jsonData, &jsonParseError).object(); + const auto json = handleRequest(reply); QString pollToken, pollEndpoint, loginUrl; - if (reply->error() == QNetworkReply::NoError && jsonParseError.error == QJsonParseError::NoError - && !json.isEmpty()) { + if (!json.isEmpty()) { pollToken = json.value("poll").toObject().value("token").toString(); pollEndpoint = json.value("poll").toObject().value("endpoint").toString(); - if (_enforceHttps && QUrl(pollEndpoint).scheme() != QStringLiteral("https")) { - qCWarning(lcFlow2auth) << "Can not poll endpoint because the returned url" << pollEndpoint << "does not start with https"; - emit result(Error, tr("The polling URL does not start with HTTPS despite the login URL started with HTTPS. Login will not be possible because this might be a security issue. Please contact your administrator.")); - return; - } loginUrl = json["login"].toString(); } - if (reply->error() != QNetworkReply::NoError || jsonParseError.error != QJsonParseError::NoError - || json.isEmpty() || pollToken.isEmpty() || pollEndpoint.isEmpty() || loginUrl.isEmpty()) { - QString errorReason; - if (const auto errorFromJson = json["error"].toString(); - !errorFromJson.isEmpty()) { - errorReason = tr("Error returned from the server: %1") - .arg(errorFromJson.toHtmlEscaped()); - } else if (reply->error() != QNetworkReply::NoError) { - errorReason = tr("There was an error accessing the \"token\" endpoint:
%1") - .arg(reply->errorString().toHtmlEscaped()); - } else if (jsonParseError.error != QJsonParseError::NoError) { - errorReason = tr("Could not parse the JSON returned from the server:
%1") - .arg(jsonParseError.errorString()); - } else { - errorReason = tr("The reply from the server did not contain all expected fields"); - } - qCWarning(lcFlow2auth) << "Error when getting the loginUrl" << json << errorReason; - emit result(Error, errorReason); + if (json.isEmpty() || pollToken.isEmpty() || pollEndpoint.isEmpty() || loginUrl.isEmpty()) { _pollTimer.stop(); _isBusy = false; return; @@ -154,8 +129,7 @@ void Flow2Auth::fetchNewToken(const TokenAction action) _pollTimer.start(); } - - switch(action) { + switch (action) { case actionOpenBrowser: // Try to open Browser if (!Utility::openBrowser(authorisationLink())) { From 245258329cc8704ae1c89c1cd6edc0909d52f854 Mon Sep 17 00:00:00 2001 From: Camila Ayres Date: Thu, 10 Apr 2025 17:49:25 +0200 Subject: [PATCH 6/8] chore: rename handleRequest to handleResponse. Signed-off-by: Camila Ayres --- src/gui/creds/flow2auth.cpp | 6 +++--- src/gui/creds/flow2auth.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/gui/creds/flow2auth.cpp b/src/gui/creds/flow2auth.cpp index 4bef0d3199fa9..59acc23849f13 100644 --- a/src/gui/creds/flow2auth.cpp +++ b/src/gui/creds/flow2auth.cpp @@ -89,7 +89,7 @@ void Flow2Auth::fetchNewToken(const TokenAction action) job->setTimeout(qMin(30 * 1000ll, job->timeoutMsec())); QObject::connect(job, &SimpleNetworkJob::finishedSignal, this, [this, action](QNetworkReply *reply) { - const auto json = handleRequest(reply); + const auto json = handleResponse(reply); QString pollToken, pollEndpoint, loginUrl; if (!json.isEmpty()) { @@ -177,7 +177,7 @@ void Flow2Auth::slotPollTimerTimeout() job->setTimeout(qMin(30 * 1000ll, job->timeoutMsec())); QObject::connect(job, &SimpleNetworkJob::finishedSignal, this, [this](QNetworkReply *reply) { - const QJsonObject json = handleRequest(reply); + const QJsonObject json = handleResponse(reply); QUrl serverUrl; QString loginName, appPassword; @@ -220,7 +220,7 @@ void Flow2Auth::slotPollTimerTimeout() }); } -QJsonObject Flow2Auth::handleRequest(QNetworkReply *reply) +QJsonObject Flow2Auth::handleResponse(QNetworkReply *reply) { const auto jsonData = reply->readAll(); QJsonParseError jsonParseError{}; diff --git a/src/gui/creds/flow2auth.h b/src/gui/creds/flow2auth.h index 4d4c05a012a9f..01e87511c8db3 100644 --- a/src/gui/creds/flow2auth.h +++ b/src/gui/creds/flow2auth.h @@ -73,7 +73,7 @@ private slots: private: void fetchNewToken(const TokenAction action); - [[nodiscard]] QJsonObject handleRequest(QNetworkReply *reply); + [[nodiscard]] QJsonObject handleResponse(QNetworkReply *reply); Account *_account; QUrl _loginUrl; From 0cc6b0e788484e615d4335f3ffa5136ddf8aad76 Mon Sep 17 00:00:00 2001 From: Camila Ayres Date: Thu, 10 Apr 2025 17:51:39 +0200 Subject: [PATCH 7/8] fix: add parameter to string. Signed-off-by: Camila Ayres --- src/gui/creds/flow2auth.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/creds/flow2auth.cpp b/src/gui/creds/flow2auth.cpp index 59acc23849f13..f3d9e09c0333f 100644 --- a/src/gui/creds/flow2auth.cpp +++ b/src/gui/creds/flow2auth.cpp @@ -249,7 +249,7 @@ QJsonObject Flow2Auth::handleResponse(QNetworkReply *reply) errorReason = tr("Could not parse the JSON returned from the server:
%1") .arg(jsonParseError.errorString()); } else if (json.isEmpty()) { - errorReason = tr("The reply from the server did not contain all expected fields") + errorReason = tr("The reply from the server did not contain all expected fields:
%1") .arg(jsonParseError.errorString()); } From d2720745453455075bce27ddac4c5350331b4319 Mon Sep 17 00:00:00 2001 From: Camila Ayres Date: Thu, 10 Apr 2025 19:13:12 +0200 Subject: [PATCH 8/8] fix: handleResponse logic on handling valid https url. Signed-off-by: Camila Ayres --- src/gui/creds/flow2auth.cpp | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src/gui/creds/flow2auth.cpp b/src/gui/creds/flow2auth.cpp index f3d9e09c0333f..2b45b3bc68184 100644 --- a/src/gui/creds/flow2auth.cpp +++ b/src/gui/creds/flow2auth.cpp @@ -225,13 +225,29 @@ QJsonObject Flow2Auth::handleResponse(QNetworkReply *reply) const auto jsonData = reply->readAll(); QJsonParseError jsonParseError{}; const auto json = QJsonDocument::fromJson(jsonData, &jsonParseError).object(); - if (reply->error() == QNetworkReply::NoError && jsonParseError.error == QJsonParseError::NoError && !json.isEmpty()) { - const QUrl serverUrl = json["server"].toString(); - if (_enforceHttps && serverUrl.scheme() != QStringLiteral("https")) { - qCWarning(lcFlow2auth) << "Returned server url" << serverUrl << "does not start with https"; - emit result(Error, tr("The returned server URL does not start with HTTPS despite the login URL started with HTTPS. Login will not be possible because this might be a security issue. Please contact your administrator.")); + const auto isHttps = [&]() { + const auto endpoint = json["server"].toString().isEmpty() + ? json.value("poll").toObject().value("endpoint").toString() //from login/v2 endpoint + : json["server"].toString(); //from login/v2/poll endpoint + + if (endpoint.isEmpty()) { + return false; + } + + qCDebug(lcFlow2auth) << "Server url returned is" << endpoint; + if (QUrl(endpoint).scheme() != QStringLiteral("https")) { + return false; + } + + return true; + }; + + if (_enforceHttps && !isHttps()) { + qCWarning(lcFlow2auth) << "Returned server url | poll endpoint does not start with https"; + emit result(Error, tr("The returned server URL does not start with HTTPS despite the login URL started with HTTPS. " + "Login will not be possible because this might be a security issue. Please contact your administrator.")); return {}; } }