summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorFelix Barz <barz.felix@web.de>2018-10-16 18:44:09 +0200
committerFelix Barz <barz.felix@web.de>2019-01-28 15:14:05 +0000
commit297e842a7fcbe0def4223625b8daa3e46afe057f (patch)
tree7db5c3a24462ceab60459740a435228141722158 /tests
parent94640eb27c054baffddf44fcaebf26f800a6415e (diff)
Add method to prepare network requests
Sending authenticated requests is limited to the APIs the QAbstractOAuth class provides. With the newly added prepareRequest and sendCustomRequest methods, one can set the correct headers etc. on any custom created network request, including the verb that is used to the request as well the body to be sent. This includes a modifcation to the QOAuth1Signature class to make it possible to sign requests with a custom method. [ChangeLog][QOAuth1Signature] Added customMethodString and setCustomMethodString methods to support signing requests with custom methods. [ChangeLog][QAbstractOAuth] Added prepareRequest and sendCustomRequest methods to authenticate any custom request, including custom verbs and bodies. Change-Id: I86459844ee919e8c9d60d349257b57afbc3fa07a Reviewed-by: MÃ¥rten Nordheim <marten.nordheim@qt.io>
Diffstat (limited to 'tests')
-rw-r--r--tests/auto/abstractoauth/tst_abstractoauth.cpp11
-rw-r--r--tests/auto/oauth1/BLACKLIST2
-rw-r--r--tests/auto/oauth1/tst_oauth1.cpp269
-rw-r--r--tests/auto/oauth1signature/tst_oauth1signature.cpp35
-rw-r--r--tests/auto/oauth2/tst_oauth2.cpp11
5 files changed, 327 insertions, 1 deletions
diff --git a/tests/auto/abstractoauth/tst_abstractoauth.cpp b/tests/auto/abstractoauth/tst_abstractoauth.cpp
index b422dc9..775f930 100644
--- a/tests/auto/abstractoauth/tst_abstractoauth.cpp
+++ b/tests/auto/abstractoauth/tst_abstractoauth.cpp
@@ -39,8 +39,17 @@ class tst_AbstractOAuth : public QObject
Q_OBJECT
private:
+ struct AbstractOAuthPrivate : public QAbstractOAuthPrivate {
+ AbstractOAuthPrivate() : QAbstractOAuthPrivate("", QUrl(), QString(), nullptr)
+ {}
+
+ void prepareRequestImpl(QNetworkRequest *,
+ const QByteArray &,
+ const QByteArray &) override {}
+ };
+
struct AbstractOAuth : QAbstractOAuth {
- AbstractOAuth() : QAbstractOAuth(*new QAbstractOAuthPrivate("", QUrl(), QString(), nullptr),
+ AbstractOAuth() : QAbstractOAuth(*new AbstractOAuthPrivate(),
nullptr)
{}
diff --git a/tests/auto/oauth1/BLACKLIST b/tests/auto/oauth1/BLACKLIST
index 44de921..3f74a03 100644
--- a/tests/auto/oauth1/BLACKLIST
+++ b/tests/auto/oauth1/BLACKLIST
@@ -15,3 +15,5 @@ windows
*
[authenticatedCalls]
*
+[prepareRequestCalls]
+*
diff --git a/tests/auto/oauth1/tst_oauth1.cpp b/tests/auto/oauth1/tst_oauth1.cpp
index dbc793c..eb13420 100644
--- a/tests/auto/oauth1/tst_oauth1.cpp
+++ b/tests/auto/oauth1/tst_oauth1.cpp
@@ -155,15 +155,29 @@ private Q_SLOTS:
void getToken_data();
void getToken();
+ void prepareRequestSignature_data();
+ void prepareRequestSignature();
+
void grant_data();
void grant();
void authenticatedCalls_data();
void authenticatedCalls();
+ void prepareRequestCalls_data();
+ void prepareRequestCalls();
+
void secondTemporaryToken();
};
+const auto oauthVersion = QStringLiteral("oauth_version");
+const auto oauthConsumerKey = QStringLiteral("oauth_consumer_key");
+const auto oauthNonce = QStringLiteral("oauth_nonce");
+const auto oauthSignatureMethod = QStringLiteral("oauth_signature_method");
+const auto oauthTimestamp = QStringLiteral("oauth_timestamp");
+const auto oauthToken = QStringLiteral("oauth_token");
+const auto oauthSignature = QStringLiteral("oauth_signature");
+
bool hostReachable(const QLatin1String &host)
{
// check host exists
@@ -476,6 +490,118 @@ void tst_OAuth1::getToken()
QCOMPARE(oauthHeaders["oauth_signature"], expectedSignature);
}
+void tst_OAuth1::prepareRequestSignature_data()
+{
+ QTest::addColumn<QString>("consumerKey");
+ QTest::addColumn<QString>("consumerSecret");
+ QTest::addColumn<QString>("accessKey");
+ QTest::addColumn<QString>("accessKeySecret");
+ QTest::addColumn<QNetworkRequest>("request");
+ QTest::addColumn<QByteArray>("operation");
+ QTest::addColumn<QByteArray>("body");
+ QTest::addColumn<QVariantMap>("extraParams");
+
+ QTest::newRow("get_simple")
+ << "key"
+ << "secret"
+ << "accesskey"
+ << "accesssecret"
+ << QNetworkRequest(QUrl("http://term.ie/oauth/example/echo_api.php"))
+ << QByteArray("GET")
+ << QByteArray()
+ << QVariantMap();
+
+ QTest::newRow("get_params")
+ << "key"
+ << "secret"
+ << "accesskey"
+ << "accesssecret"
+ << QNetworkRequest(QUrl("http://term.ie/oauth/example/echo_api.php?"
+ "first=first&second=second"))
+ << QByteArray("GET")
+ << QByteArray()
+ << QVariantMap();
+
+ QNetworkRequest postRequest(QUrl("http://term.ie/oauth/example/echo_api.php"));
+ postRequest.setHeader(QNetworkRequest::ContentTypeHeader,
+ QByteArray("application/x-www-form-urlencoded"));
+ QTest::newRow("post_params")
+ << "key"
+ << "secret"
+ << "accesskey"
+ << "accesssecret"
+ << postRequest
+ << QByteArray("POST")
+ << QByteArray("first=first&second=second")
+ << QVariantMap({
+ {"first", "first"},
+ {"second", "second"}
+ });
+
+ QTest::newRow("patch_param")
+ << "key"
+ << "secret"
+ << "accesskey"
+ << "accesssecret"
+ << QNetworkRequest(QUrl("http://term.ie/oauth/example/echo_api.php?"
+ "first=first&second=second"))
+ << QByteArray("PATCH")
+ << QByteArray()
+ << QVariantMap();
+}
+
+void tst_OAuth1::prepareRequestSignature()
+{
+ QFETCH(QString, consumerKey);
+ QFETCH(QString, consumerSecret);
+ QFETCH(QString, accessKey);
+ QFETCH(QString, accessKeySecret);
+ QFETCH(QNetworkRequest, request);
+ QFETCH(QByteArray, operation);
+ QFETCH(QByteArray, body);
+ QFETCH(QVariantMap, extraParams);
+
+ QOAuth1 o1;
+ o1.setClientCredentials(consumerKey, consumerSecret);
+ o1.setTokenCredentials(accessKey, accessKeySecret);
+
+ o1.prepareRequest(&request, operation, body);
+
+ // extract oauth parameters from the headers
+ QVariantMap authArgs;
+ const auto authHeader = request.rawHeader("Authorization");
+ QCOMPARE(authHeader.mid(0, 6), "OAuth ");
+ const auto values = authHeader.mid(6).split(',');
+ for (const auto &pair : values) {
+ const auto argPair = pair.split('=');
+ QCOMPARE(argPair.size(), 2);
+ QCOMPARE(argPair[1].front(), '\"');
+ QCOMPARE(argPair[1].back(), '\"');
+ authArgs.insert(argPair[0], argPair[1].mid(1, argPair[1].size() - 2));
+ }
+
+ //compare known parameters
+ QCOMPARE(authArgs.value(oauthConsumerKey).toByteArray(), consumerKey);
+ QCOMPARE(authArgs.value(oauthToken).toByteArray(), accessKey);
+ QCOMPARE(authArgs.value(oauthSignatureMethod).toByteArray(), QByteArray("HMAC-SHA1"));
+ QCOMPARE(authArgs.value(oauthVersion).toByteArray(), QByteArray("1.0"));
+ QVERIFY(authArgs.contains(oauthNonce));
+ QVERIFY(authArgs.contains(oauthTimestamp));
+ QVERIFY(authArgs.contains(oauthSignature));
+
+ // verify the signature
+ const auto sigString = QUrl::fromPercentEncoding(authArgs.take(oauthSignature)
+ .toByteArray()).toUtf8();
+ QOAuth1Signature signature(request.url(),
+ consumerSecret,
+ accessKeySecret,
+ QOAuth1Signature::HttpRequestMethod::Custom,
+ authArgs.unite(extraParams));
+ signature.setCustomMethodString(operation);
+ const auto signatureData = signature.hmacSha1();
+ QCOMPARE(signatureData.toBase64(), sigString);
+}
+
void tst_OAuth1::grant_data()
{
QTest::addColumn<QString>("consumerKey");
@@ -713,6 +839,149 @@ void tst_OAuth1::authenticatedCalls()
reply.clear();
}
+void tst_OAuth1::prepareRequestCalls_data()
+{
+ QTest::addColumn<QString>("consumerKey");
+ QTest::addColumn<QString>("consumerSecret");
+ QTest::addColumn<QString>("accessKey");
+ QTest::addColumn<QString>("accessKeySecret");
+ QTest::addColumn<QUrl>("url");
+ QTest::addColumn<QVariantMap>("parameters");
+ QTest::addColumn<QByteArray>("operation");
+
+ const QVariantMap parameters { { QStringLiteral("first"), QStringLiteral("first") },
+ { QStringLiteral("second"), QStringLiteral("second") },
+ { QStringLiteral("third"), QStringLiteral("third") },
+ { QStringLiteral("c2&a3"), QStringLiteral("2=%$&@q") }
+ };
+
+ if (hostReachable(QLatin1String("term.ie"))) {
+ QTest::newRow("term.ie_get") << "key"
+ << "secret"
+ << "accesskey"
+ << "accesssecret"
+ << QUrl("http://term.ie/oauth/example/echo_api.php")
+ << parameters
+ << QByteArray("GET");
+ QTest::newRow("term.ie_post") << "key"
+ << "secret"
+ << "accesskey"
+ << "accesssecret"
+ << QUrl("http://term.ie/oauth/example/echo_api.php")
+ << parameters
+ << QByteArray("POST");
+ QTest::newRow("term.ie_percent_encoded_query")
+ << "key"
+ << "secret"
+ << "accesskey"
+ << "accesssecret"
+ << QUrl("http://term.ie/oauth/example/echo_api.php?key=%40value+1%2B2=3")
+ << parameters
+ << QByteArray("GET");
+ }
+ if (hostReachable(QLatin1String("oauthbin.com"))) {
+ QTest::newRow("oauthbin.com_get") << "key"
+ << "secret"
+ << "accesskey"
+ << "accesssecret"
+ << QUrl("http://oauthbin.com/v1/echo")
+ << parameters
+ << QByteArray("GET");
+ QTest::newRow("oauthbin.com_post") << "key"
+ << "secret"
+ << "accesskey"
+ << "accesssecret"
+ << QUrl("http://oauthbin.com/v1/echo")
+ << parameters
+ << QByteArray("POST");
+ QTest::newRow("oauthbin.com_percent_encoded_query")
+ << "key"
+ << "secret"
+ << "accesskey"
+ << "accesssecret"
+ << QUrl("http://oauthbin.com/v1/echo?key=%40value+1%2B2=3")
+ << parameters
+ << QByteArray("GET");
+ QTest::newRow("oauthbin.com_patch") << "key"
+ << "secret"
+ << "accesskey"
+ << "accesssecret"
+ << QUrl("http://oauthbin.com/v1/echo")
+ << parameters
+ << QByteArray("PATCH");
+ }
+}
+
+void tst_OAuth1::prepareRequestCalls()
+{
+ QFETCH(QString, consumerKey);
+ QFETCH(QString, consumerSecret);
+ QFETCH(QString, accessKey);
+ QFETCH(QString, accessKeySecret);
+ QFETCH(QUrl, url);
+ QFETCH(QVariantMap, parameters);
+ QFETCH(QByteArray, operation);
+
+ QNetworkAccessManager networkAccessManager;
+ QNetworkReplyPtr reply;
+ QString receivedData;
+ QString parametersString;
+ {
+ if (url.hasQuery()) {
+ parametersString = url.query(QUrl::FullyDecoded);
+ if (!parameters.empty())
+ parametersString.append(QLatin1Char('&'));
+ }
+ bool first = true;
+ for (auto it = parameters.begin(), end = parameters.end(); it != end; ++it) {
+ if (first)
+ first = false;
+ else
+ parametersString += QLatin1Char('&');
+ parametersString += it.key() + QLatin1Char('=') + it.value().toString();
+ }
+ }
+
+ QOAuth1 o1(&networkAccessManager);
+ o1.setClientCredentials(consumerKey, consumerSecret);
+ o1.setTokenCredentials(accessKey, accessKeySecret);
+
+ if (operation != "POST") {
+ QUrlQuery query(url.query());
+ for (auto it = parameters.begin(), end = parameters.end(); it != end; ++it)
+ query.addQueryItem(it.key(), it.value().toString());
+ url.setQuery(query);
+ }
+ QNetworkRequest request(url);
+ QByteArray body;
+ if (operation == "POST") {
+ QUrlQuery query(url.query());
+ for (auto it = parameters.begin(), end = parameters.end(); it != end; ++it)
+ query.addQueryItem(it.key(), it.value().toString());
+ body = query.toString().toUtf8();
+ request.setHeader(QNetworkRequest::ContentTypeHeader,
+ QByteArray("application/x-www-form-urlencoded"));
+ }
+
+ o1.prepareRequest(&request, operation, body);
+ if (body.isEmpty())
+ reply.reset(o1.networkAccessManager()->sendCustomRequest(request, operation));
+ else
+ reply.reset(o1.networkAccessManager()->sendCustomRequest(request, operation, body));
+ QVERIFY(!reply.isNull());
+ QVERIFY(!reply->isFinished());
+
+ connect(&networkAccessManager, &QNetworkAccessManager::finished,
+ [&](QNetworkReply *reply) {
+ QByteArray data = reply->readAll();
+ QUrlQuery query(QString::fromUtf8(data));
+ receivedData = query.toString(QUrl::FullyDecoded);
+ });
+ QVERIFY(waitForFinish(reply) == Success);
+ QCOMPARE(receivedData, parametersString);
+ reply.clear();
+}
+
void tst_OAuth1::secondTemporaryToken()
{
QNetworkAccessManager networkAccessManager;
diff --git a/tests/auto/oauth1signature/tst_oauth1signature.cpp b/tests/auto/oauth1signature/tst_oauth1signature.cpp
index 616578e..912aa44 100644
--- a/tests/auto/oauth1signature/tst_oauth1signature.cpp
+++ b/tests/auto/oauth1signature/tst_oauth1signature.cpp
@@ -101,6 +101,7 @@ void tst_OAuth1Signature::signatures_data()
{
QTest::addColumn<QUrl>("url");
QTest::addColumn<QOAuth1Signature::HttpRequestMethod>("method");
+ QTest::addColumn<QByteArray>("customVerb");
QTest::addColumn<QString>("version");
QTest::addColumn<QString>("consumerKey");
QTest::addColumn<QString>("consumerSecret");
@@ -113,6 +114,7 @@ void tst_OAuth1Signature::signatures_data()
QTest::newRow("standard") << QUrl("http://example.net")
<< QOAuth1Signature::HttpRequestMethod::Get
+ << QByteArray()
<< "1.0"
<< "key"
<< "secret"
@@ -124,6 +126,7 @@ void tst_OAuth1Signature::signatures_data()
<< "mQaARxv7pqJyViuwNGtUfm6QSIQ=";
QTest::newRow("post") << QUrl("http://example.net")
<< QOAuth1Signature::HttpRequestMethod::Post
+ << QByteArray()
<< "1.0"
<< "key"
<< "secret"
@@ -135,6 +138,7 @@ void tst_OAuth1Signature::signatures_data()
<< "L4blJKqYMTSNUEt32rCgDLhxQxM=";
QTest::newRow("put") << QUrl("http://example.net")
<< QOAuth1Signature::HttpRequestMethod::Put
+ << QByteArray()
<< "1.0"
<< "key"
<< "secret"
@@ -146,6 +150,7 @@ void tst_OAuth1Signature::signatures_data()
<< "+eiZ+phNoYnETf6SqI+XSE43JSY=";
QTest::newRow("delete") << QUrl("http://example.net")
<< QOAuth1Signature::HttpRequestMethod::Delete
+ << QByteArray()
<< "1.0"
<< "key"
<< "secret"
@@ -157,6 +162,7 @@ void tst_OAuth1Signature::signatures_data()
<< "enbOVNG7/vGliie2/L44NdccMaw=";
QTest::newRow("head") << QUrl("http://example.net")
<< QOAuth1Signature::HttpRequestMethod::Head
+ << QByteArray()
<< "1.0"
<< "key"
<< "secret"
@@ -168,6 +174,7 @@ void tst_OAuth1Signature::signatures_data()
<< "6v74w0rRsVibJsJ796Nj8cJPqEU=";
QTest::newRow("no-hmac-key") << QUrl("http://example.net")
<< QOAuth1Signature::HttpRequestMethod::Get
+ << QByteArray()
<< "1.0"
<< "key"
<< QString()
@@ -179,6 +186,7 @@ void tst_OAuth1Signature::signatures_data()
<< "N2qP+LJdLbjalZq71M7oxPdeUjc=";
QTest::newRow("custom-values") << QUrl("http://example.net")
<< QOAuth1Signature::HttpRequestMethod::Get
+ << QByteArray()
<< "1.0"
<< "key"
<< "secret"
@@ -191,6 +199,30 @@ void tst_OAuth1Signature::signatures_data()
{ "secondKey", "secondValue" }
}
<< "xNXgQaO0LrQMbJZGSfKFUmWwGDw=";
+ QTest::newRow("custom-verb-get") << QUrl("http://example.net")
+ << QOAuth1Signature::HttpRequestMethod::Custom
+ << QByteArray("GET")
+ << "1.0"
+ << "key"
+ << "secret"
+ << "accesskey"
+ << "accesssecret"
+ << "468167367"
+ << "1494852816"
+ << QVariantMap()
+ << "mQaARxv7pqJyViuwNGtUfm6QSIQ=";
+ QTest::newRow("custom-verb-patch") << QUrl("http://example.net")
+ << QOAuth1Signature::HttpRequestMethod::Custom
+ << QByteArray("PATCH")
+ << "1.0"
+ << "key"
+ << "secret"
+ << "accesskey"
+ << "accesssecret"
+ << "468167367"
+ << "1494852816"
+ << QVariantMap()
+ << "kcRO68D7IBQWlQvUR/jkhuF8AKM=";
}
void tst_OAuth1Signature::signatures()
@@ -200,6 +232,7 @@ void tst_OAuth1Signature::signatures()
QFETCH(QUrl, url);
QFETCH(QOAuth1Signature::HttpRequestMethod, method);
+ QFETCH(QByteArray, customVerb);
QFETCH(QString, version);
QFETCH(QString, consumerKey);
QFETCH(QString, consumerSecret);
@@ -218,6 +251,8 @@ void tst_OAuth1Signature::signatures()
parameters.insert(oauthToken, token);
QOAuth1Signature signature(url, consumerSecret, tokenSecret, method, parameters);
+ if (method == QOAuth1Signature::HttpRequestMethod::Custom)
+ signature.setCustomMethodString(customVerb);
const auto signatureData = signature.hmacSha1();
QCOMPARE(signatureData.toBase64(), result);
}
diff --git a/tests/auto/oauth2/tst_oauth2.cpp b/tests/auto/oauth2/tst_oauth2.cpp
index f3a30a9..a82ad82 100644
--- a/tests/auto/oauth2/tst_oauth2.cpp
+++ b/tests/auto/oauth2/tst_oauth2.cpp
@@ -41,6 +41,7 @@ private Q_SLOTS:
void getToken();
void refreshToken();
void getAndRefreshToken();
+ void prepareRequest();
};
struct ReplyHandler : QAbstractOAuthReplyHandler
@@ -165,5 +166,15 @@ void tst_OAuth2::getAndRefreshToken()
QCOMPARE(oauth2.token(), QLatin1String("refresh_token"));
}
+void tst_OAuth2::prepareRequest()
+{
+ QOAuth2AuthorizationCodeFlow oauth2;
+ oauth2.setToken(QStringLiteral("access_token"));
+
+ QNetworkRequest request(QUrl("http://localhost"));
+ oauth2.prepareRequest(&request, QByteArray());
+ QCOMPARE(request.rawHeader("Authorization"), QByteArray("Bearer access_token"));
+}
+
QTEST_MAIN(tst_OAuth2)
#include "tst_oauth2.moc"