diff --git a/src/gui/creds/flow2auth.cpp b/src/gui/creds/flow2auth.cpp
index b3cc7c937ac41..2b45b3bc68184 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,64 +77,38 @@ 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();
- QJsonParseError jsonParseError{};
- QJsonObject json = QJsonDocument::fromJson(jsonData, &jsonParseError).object();
+ const auto json = handleResponse(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;
- QString errorFromJson = json["error"].toString();
- if (!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;
}
-
_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 +118,18 @@ 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())) {
@@ -180,8 +151,9 @@ void Flow2Auth::fetchNewToken(const TokenAction action)
void Flow2Auth::slotPollTimerTimeout()
{
- if(_isBusy || !_hasToken)
+ if (_isBusy || !_hasToken) {
return;
+ }
_isBusy = true;
@@ -194,57 +166,28 @@ 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();
- QJsonParseError jsonParseError{};
- QJsonObject json = QJsonDocument::fromJson(jsonData, &jsonParseError).object();
+ const QJsonObject json = handleResponse(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;
- QString errorFromJson = json["error"].toString();
- if (!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();
@@ -277,11 +220,74 @@ void Flow2Auth::slotPollTimerTimeout()
});
}
+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 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 {};
+ }
+ }
+
+ 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:
%1")
+ .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;
+ }
_secondsLeft = 1;
slotPollTimerTimeout();
diff --git a/src/gui/creds/flow2auth.h b/src/gui/creds/flow2auth.h
index adac4d39bb1ad..01e87511c8db3 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 handleResponse(QNetworkReply *reply);
Account *_account;
QUrl _loginUrl;