QUrl messageUrl = json["message_url"].toString();
if (reply->error() != QNetworkReply::NoError || jsonParseError.error != QJsonParseError::NoError
- || json.isEmpty() || refreshToken.isEmpty() || accessToken.isEmpty()
+ || jsonData.isEmpty() || json.isEmpty() || refreshToken.isEmpty() || accessToken.isEmpty()
|| json["token_type"].toString() != QLatin1String("Bearer")) {
QString errorReason;
QString errorFromJson = json["error"].toString();
} else if (reply->error() != QNetworkReply::NoError) {
errorReason = tr("There was an error accessing the 'token' endpoint: <br><em>%1</em>")
.arg(reply->errorString().toHtmlEscaped());
+ } else if (jsonData.isEmpty()) {
+ // Can happen if a funky load balancer strips away POST data, e.g. BigIP APM my.policy
+ errorReason = tr("Empty JSON from OAuth2 redirect");
+ // We explicitly have this as error case since the json qcWarning output below is misleading,
+ // it will show a fake json will null values that actually never was received like this as
+ // soon as you access json["whatever"] the debug output json will claim to have "whatever":null
} else if (jsonParseError.error != QJsonParseError::NoError) {
errorReason = tr("Could not parse the JSON returned from the server: <br><em>%1</em>")
.arg(jsonParseError.errorString());
public:
std::unique_ptr<QIODevice> payload;
bool aborted = false;
+ bool redirectToPolicy = false;
+ bool redirectToToken = false;
FakePostReply(QNetworkAccessManager::Operation op, const QNetworkRequest &request,
std::unique_ptr<QIODevice> payload_, QObject *parent)
emit metaDataChanged();
emit finished();
return;
+ } else if (redirectToPolicy) {
+ setHeader(QNetworkRequest::LocationHeader, "/my.policy");
+ setAttribute(QNetworkRequest::RedirectionTargetAttribute, "/my.policy");
+ setAttribute(QNetworkRequest::HttpStatusCodeAttribute, 302); // 302 might or might not lose POST data in rfc
+ setHeader(QNetworkRequest::ContentLengthHeader, 0);
+ emit metaDataChanged();
+ emit finished();
+ return;
+ } else if (redirectToToken) {
+ // Redirect to self
+ QVariant destination = QVariant(sOAuthTestServer.toString()+QLatin1String("/index.php/apps/oauth2/api/v1/token"));
+ setHeader(QNetworkRequest::LocationHeader, destination);
+ setAttribute(QNetworkRequest::RedirectionTargetAttribute, destination);
+ setAttribute(QNetworkRequest::HttpStatusCodeAttribute, 307); // 307 explicitly in rfc says to not lose POST data
+ setHeader(QNetworkRequest::ContentLengthHeader, 0);
+ emit metaDataChanged();
+ emit finished();
+ return;
}
setHeader(QNetworkRequest::ContentLengthHeader, payload->size());
setAttribute(QNetworkRequest::HttpStatusCodeAttribute, 200);
account->setUrl(sOAuthTestServer);
account->setCredentials(new FakeCredentials{fakeQnam});
fakeQnam->setParent(this);
- fakeQnam->setOverride([this](QNetworkAccessManager::Operation op, const QNetworkRequest &req, QIODevice *) {
+ fakeQnam->setOverride([this](QNetworkAccessManager::Operation op, const QNetworkRequest &req, QIODevice *device) {
+ ASSERT(device);
+ ASSERT(device->bytesAvailable()>0); // OAuth2 always sends around POST data.
return this->tokenReply(op, req);
});
} test;
test.test();
}
+
+ void testTokenUrlHasRedirect()
+ {
+ struct Test : OAuthTestCase {
+ int redirectsDone = 0;
+ QNetworkReply *tokenReply(QNetworkAccessManager::Operation op, const QNetworkRequest & request) override
+ {
+ ASSERT(browserReply);
+ // Kind of reproduces what we had in https://github.com/owncloud/enterprise/issues/2951 (not 1:1)
+ if (redirectsDone == 0) {
+ std::unique_ptr<QBuffer> payload(new QBuffer());
+ payload->setData("");
+ SlowFakePostReply *reply = new SlowFakePostReply(op, request, std::move(payload), this);
+ reply->redirectToPolicy = true;
+ redirectsDone++;
+ return reply;
+ } else if (redirectsDone == 1) {
+ std::unique_ptr<QBuffer> payload(new QBuffer());
+ payload->setData("");
+ SlowFakePostReply *reply = new SlowFakePostReply(op, request, std::move(payload), this);
+ reply->redirectToToken = true;
+ redirectsDone++;
+ return reply;
+ } else {
+ // ^^ This is with a custom reply and not actually HTTP, so we're testing the HTTP redirect code
+ // we have in AbstractNetworkJob::slotFinished()
+ redirectsDone++;
+ return OAuthTestCase::tokenReply(op, request);
+ }
+ }
+ } test;
+ test.test();
+ }
};
QTEST_GUILESS_MAIN(TestOAuth)