From 1ef97d59a18a859dcbaca26db4c03f116880a37f Mon Sep 17 00:00:00 2001 From: Jesus Fernandez Date: Tue, 2 Aug 2016 16:14:55 +0200 Subject: [PATCH] Default UserAgent changed Moved QOAuth1Private private slots moved Added RFC references to the OAuth1 functions Removed return in _q_accessTokenRequestFinished Added copyright comment --- QtOAuth.pri | 3 +- QtOAuth/private/qabstractoauth2_p.h | 4 +- QtOAuth/private/qoauth1_p.h | 25 ++- QtOAuth/qabstractoauth2.cpp | 1 - QtOAuth/qoauth1.cpp | 154 +++++++++--------- QtOAuth/qoauth2authorizationcodeflow.cpp | 1 - QtOAuth/qoauth2implicitgrantflow.cpp | 3 +- examples/googlecalendar/main.cpp | 39 +++++ examples/redditclient/redditmodel.cpp | 3 +- examples/twittertimeline/main.cpp | 3 +- .../twittertimeline/twittertimelinemodel.cpp | 7 +- tests/qoauth/tst_qoauth.cpp | 25 ++- 12 files changed, 156 insertions(+), 112 deletions(-) diff --git a/QtOAuth.pri b/QtOAuth.pri index 1743fdf..b9a7f48 100644 --- a/QtOAuth.pri +++ b/QtOAuth.pri @@ -8,5 +8,6 @@ win32:CONFIG(release, debug|release): { } else:win32:CONFIG(debug, debug|release): { DESTDIR = $$OUT_PWD/../../debug LIBS += $$OUT_PWD/../../debug/QtOAuth.lib +} else:unix: { + LIBS += -L$$OUT_PWD/../../QtOAuth/ -lQtOAuth } -else:unix: LIBS += -L$$OUT_PWD/../../QtOAuth/ -lQtOAuth diff --git a/QtOAuth/private/qabstractoauth2_p.h b/QtOAuth/private/qabstractoauth2_p.h index 5fe4009..edcdd88 100644 --- a/QtOAuth/private/qabstractoauth2_p.h +++ b/QtOAuth/private/qabstractoauth2_p.h @@ -81,8 +81,8 @@ public: QString token; QString scope; QString state = generateRandomState(); - QString userAgent = "qoauth/0.1"; - const QString bearerFormat = QStringLiteral("Bearer %1"); + QString userAgent = "QtOAuth/1.0 (+https://www.qt.io)"; + const QString bearerFormat = QStringLiteral("Bearer %1"); // Case sensitive QDateTime expiresAt; QString refreshToken; diff --git a/QtOAuth/private/qoauth1_p.h b/QtOAuth/private/qoauth1_p.h index 8853f66..c1bd8d2 100644 --- a/QtOAuth/private/qoauth1_p.h +++ b/QtOAuth/private/qoauth1_p.h @@ -72,20 +72,6 @@ class OAUTH_EXPORT QOAuth1Private : public QAbstractOAuthPrivate public: QOAuth1Private(QNetworkAccessManager *networkAccessManager = nullptr); - QPair clientCredentials; - QPair tokenCredentials; - QString verifier; - QUrl temporaryCredentialsUrl; - QUrl tokenCredentialsUrl; - QOAuth1::SignatureMethod signatureMethod = QOAuth1::SignatureMethod::Hmac_Sha1; - const QString oauthVersion = QStringLiteral("1.0"); - - // private slots - void _q_onTokenRequestFinished(); - void _q_onTokenRequestError(QNetworkReply::NetworkError error); - void _q_requestAuthorizationGrantAnswer(); - void _q_tokensReceived(const QVariantMap &tokens); - void appendCommonHeaders(QVariantMap *headers); void appendSignature(QAbstractOAuth::Stage stage, QVariantMap *headers, @@ -101,6 +87,17 @@ public: QString signatureMethodString() const; static QString operationName(QNetworkAccessManager::Operation op); + void _q_onTokenRequestError(QNetworkReply::NetworkError error); + void _q_requestAuthorizationGrantAnswer(); + void _q_tokensReceived(const QVariantMap &tokens); + + QPair clientCredentials; + QPair tokenCredentials; + QString verifier; + QUrl temporaryCredentialsUrl; + QUrl tokenCredentialsUrl; + QOAuth1::SignatureMethod signatureMethod = QOAuth1::SignatureMethod::Hmac_Sha1; + const QString oauthVersion = QStringLiteral("1.0"); struct OAuth1KeyString { diff --git a/QtOAuth/qabstractoauth2.cpp b/QtOAuth/qabstractoauth2.cpp index c291ec7..0a86aae 100644 --- a/QtOAuth/qabstractoauth2.cpp +++ b/QtOAuth/qabstractoauth2.cpp @@ -72,7 +72,6 @@ const QString Key::scope = QStringLiteral("scope"); const QString Key::state = QStringLiteral("state"); const QString Key::tokenType = QStringLiteral("token_type"); - QAbstractOAuth2Private::QAbstractOAuth2Private(QNetworkAccessManager *manager) : QAbstractOAuthPrivate(manager) {} diff --git a/QtOAuth/qoauth1.cpp b/QtOAuth/qoauth1.cpp index 59660a6..43b08b2 100644 --- a/QtOAuth/qoauth1.cpp +++ b/QtOAuth/qoauth1.cpp @@ -80,77 +80,6 @@ QOAuth1Private::QOAuth1Private(QNetworkAccessManager *networkAccessManager) qRegisterMetaType("QNetworkReply::NetworkError"); } -void QOAuth1Private::_q_onTokenRequestError(QNetworkReply::NetworkError error) -{ - Q_Q(QOAuth1); - Q_UNUSED(error); - Q_EMIT q->requestFailed(QAbstractOAuth::Error::NetworkError); -} - -void QOAuth1Private::_q_requestAuthorizationGrantAnswer() -{ - Q_Q(QOAuth1); - typedef OAuth1KeyString Key; - - QNetworkReply *reply = static_cast(currentSender->sender); - if (reply->error() != QNetworkReply::NoError) { - qWarning("Reply error: %s: %s", qPrintable(reply->errorString()), - reply->readAll().data()); - Q_EMIT q->requestFailed(QAbstractOAuth::Error::NetworkError); - return; - } - - QByteArray data = reply->readAll(); - QMap response = q->parseResponse(data); - if (response.contains(Key::oauthToken) && response.contains(Key::oauthTokenSecret)) { - if (!response.isEmpty()) { - extraTokens.clear(); - for (auto it = response.begin(), end = response.end(); it != end; ++it) - extraTokens.insert(it.key(), it.value()); - const QString oauthToken = response.value(Key::oauthToken); - const QString oauthTokenSecret = response.value(Key::oauthTokenSecret); - q->setTokenCredentials(qMakePair(oauthToken, oauthTokenSecret)); - response.remove(Key::oauthToken); - response.remove(Key::oauthTokenSecret); - q->setStatus(QAbstractOAuth::Status::Granted); - Q_EMIT q->extraTokensChanged(extraTokens); - Q_EMIT q->granted(); - } - else { - q->setStatus(QAbstractOAuth::Status::NotAuthenticated); - q->setTokenCredentials(QPair()); - } - } else { - Q_EMIT q->requestFailed(QAbstractOAuth::Error::OAuthTokenNotFoundError); - } -} - -void QOAuth1Private::_q_tokensReceived(const QVariantMap &tokens) -{ - Q_Q(QOAuth1); - typedef OAuth1KeyString Key; - - QPair credential(tokens.value(Key::oauthToken).toString(), - tokens.value(Key::oauthTokenSecret).toString()); - switch (status) { - case QAbstractOAuth::Status::NotAuthenticated: - if (tokens.value(Key::oauthCallbackConfirmed, true).toBool()) { - q->setTokenCredentials(credential); - setStatus(QAbstractOAuth::Status::TemporaryTokenReceived); - } - else - Q_EMIT q->requestFailed(QAbstractOAuth::Error::OAuthCallbackNotVerified); - break; - case QAbstractOAuth::Status::TemporaryTokenReceived: - q->setTokenCredentials(credential); - setStatus(QAbstractOAuth::Status::Granted); - break; - case QAbstractOAuth::Status::Granted: - break; - } - -} - void QOAuth1Private::appendCommonHeaders(QVariantMap *headers) { typedef OAuth1KeyString Key; @@ -273,6 +202,77 @@ QString QOAuth1Private::operationName(QNetworkAccessManager::Operation op) return QString(); } +void QOAuth1Private::_q_onTokenRequestError(QNetworkReply::NetworkError error) +{ + Q_Q(QOAuth1); + Q_UNUSED(error); + Q_EMIT q->requestFailed(QAbstractOAuth::Error::NetworkError); +} + +void QOAuth1Private::_q_requestAuthorizationGrantAnswer() +{ + Q_Q(QOAuth1); + typedef OAuth1KeyString Key; + + QNetworkReply *reply = static_cast(currentSender->sender); + if (reply->error() != QNetworkReply::NoError) { + qWarning("Reply error: %s: %s", qPrintable(reply->errorString()), + reply->readAll().data()); + Q_EMIT q->requestFailed(QAbstractOAuth::Error::NetworkError); + return; + } + + QByteArray data = reply->readAll(); + QMap response = q->parseResponse(data); + if (response.contains(Key::oauthToken) && response.contains(Key::oauthTokenSecret)) { + if (!response.isEmpty()) { + extraTokens.clear(); + for (auto it = response.begin(), end = response.end(); it != end; ++it) + extraTokens.insert(it.key(), it.value()); + const QString oauthToken = response.value(Key::oauthToken); + const QString oauthTokenSecret = response.value(Key::oauthTokenSecret); + q->setTokenCredentials(qMakePair(oauthToken, oauthTokenSecret)); + response.remove(Key::oauthToken); + response.remove(Key::oauthTokenSecret); + q->setStatus(QAbstractOAuth::Status::Granted); + Q_EMIT q->extraTokensChanged(extraTokens); + Q_EMIT q->granted(); + } + else { + q->setStatus(QAbstractOAuth::Status::NotAuthenticated); + q->setTokenCredentials(QPair()); + } + } else { + Q_EMIT q->requestFailed(QAbstractOAuth::Error::OAuthTokenNotFoundError); + } +} + +void QOAuth1Private::_q_tokensReceived(const QVariantMap &tokens) +{ + Q_Q(QOAuth1); + typedef OAuth1KeyString Key; + + QPair credential(tokens.value(Key::oauthToken).toString(), + tokens.value(Key::oauthTokenSecret).toString()); + switch (status) { + case QAbstractOAuth::Status::NotAuthenticated: + if (tokens.value(Key::oauthCallbackConfirmed, true).toBool()) { + q->setTokenCredentials(credential); + setStatus(QAbstractOAuth::Status::TemporaryTokenReceived); + } + else + Q_EMIT q->requestFailed(QAbstractOAuth::Error::OAuthCallbackNotVerified); + break; + case QAbstractOAuth::Status::TemporaryTokenReceived: + q->setTokenCredentials(credential); + setStatus(QAbstractOAuth::Status::Granted); + break; + case QAbstractOAuth::Status::Granted: + break; + } + +} + QOAuth1::QOAuth1(QObject *parent) : QAbstractOAuth(*new QOAuth1Private, parent) {} @@ -503,12 +503,10 @@ QNetworkReply *QOAuth1::requestTemporaryCredentials(QNetworkAccessManager::Opera if (Q_UNLIKELY(!d->networkAccessManager())) { qCritical("QNetworkAccessManager not available"); return nullptr; - } - if (Q_UNLIKELY(url.isEmpty())) { + } else if (Q_UNLIKELY(url.isEmpty())) { qCritical() << "Request Url not set"; return nullptr; - } - if (Q_UNLIKELY(operation != QNetworkAccessManager::GetOperation && + } else if (Q_UNLIKELY(operation != QNetworkAccessManager::GetOperation && operation != QNetworkAccessManager::PostOperation)) { qCritical("Operation not supported"); return nullptr; @@ -639,6 +637,7 @@ QByteArray QOAuth1::parameterString(const QVariantMap ¶meters) QByteArray QOAuth1::nonce() { + // https://tools.ietf.org/html/rfc5849#section-3.3 QString u = QString::number(QDateTime::currentDateTimeUtc().toTime_t()); u.append(QString::number(qrand())); return u.toUtf8(); @@ -675,6 +674,7 @@ QByteArray QOAuth1::signature(const QVariantMap ¶meters, const QString &consumerSecret, const QString &tokenSecret) { + // https://tools.ietf.org/html/rfc5849#section-3.4 const QByteArray baseString = signatureBaseString(parameters, url, op); QByteArray secret; @@ -689,6 +689,8 @@ QByteArray QOAuth1::signature(const QVariantMap ¶meters, QByteArray QOAuth1::generateAuthorizationHeader(const QVariantMap &oauthParams) { + // https://tools.ietf.org/html/rfc5849#section-3.5.1 + // TODO Add realm parameter support bool first = true; QString ret(QStringLiteral("OAuth ")); QVariantMap headers(oauthParams); @@ -708,6 +710,7 @@ QByteArray QOAuth1::generateAuthorizationHeader(const QVariantMap &oauthParams) void QOAuth1::grant() { + // https://tools.ietf.org/html/rfc5849#section-2 Q_D(QOAuth1); typedef QOAuth1Private::OAuth1KeyString Key; @@ -762,6 +765,7 @@ void QOAuth1::grant() void QOAuth1::continueGrantWithVerifier(const QString &verifier) { + // https://tools.ietf.org/html/rfc5849#section-2.3 Q_D(QOAuth1); typedef QOAuth1Private::OAuth1KeyString Key; diff --git a/QtOAuth/qoauth2authorizationcodeflow.cpp b/QtOAuth/qoauth2authorizationcodeflow.cpp index a2f2d92..0bccad5 100644 --- a/QtOAuth/qoauth2authorizationcodeflow.cpp +++ b/QtOAuth/qoauth2authorizationcodeflow.cpp @@ -107,7 +107,6 @@ void QOAuth2AuthorizationCodeFlowPrivate::_q_accessTokenRequestFinished(QNetwork if (reply != currentReply) return; if (reply->error() == QNetworkReply::UnknownNetworkError) { - return; qWarning("QOAuth2AuthorizationCodeFlow: %s", qPrintable(reply->errorString())); setStatus(QAbstractOAuth::Status::NotAuthenticated); return; diff --git a/QtOAuth/qoauth2implicitgrantflow.cpp b/QtOAuth/qoauth2implicitgrantflow.cpp index a3eb9f0..2ab638f 100644 --- a/QtOAuth/qoauth2implicitgrantflow.cpp +++ b/QtOAuth/qoauth2implicitgrantflow.cpp @@ -66,8 +66,7 @@ QOAuth2ImplicitGrantFlow::QOAuth2ImplicitGrantFlow(QObject *parent) : QOAuth2ImplicitGrantFlow::QOAuth2ImplicitGrantFlow(QNetworkAccessManager *manager, QObject *parent) : QAbstractOAuth2(*new QOAuth2ImplicitGrantFlowPrivate(manager), parent) -{ -} +{} QOAuth2ImplicitGrantFlow::QOAuth2ImplicitGrantFlow(const QString &clientIdentifier, QNetworkAccessManager *manager, diff --git a/examples/googlecalendar/main.cpp b/examples/googlecalendar/main.cpp index 8ca4274..59f599a 100644 --- a/examples/googlecalendar/main.cpp +++ b/examples/googlecalendar/main.cpp @@ -1,3 +1,42 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtNetwork module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + #include #include #include diff --git a/examples/redditclient/redditmodel.cpp b/examples/redditclient/redditmodel.cpp index d5fc6e3..d96c266 100644 --- a/examples/redditclient/redditmodel.cpp +++ b/examples/redditclient/redditmodel.cpp @@ -44,8 +44,7 @@ RedditModel::RedditModel(QObject *parent) : QAbstractTableModel(parent) -{ -} +{} RedditModel::RedditModel(const QString &clientId, QObject *parent) : QAbstractTableModel(parent) diff --git a/examples/twittertimeline/main.cpp b/examples/twittertimeline/main.cpp index 7e64295..018f45b 100644 --- a/examples/twittertimeline/main.cpp +++ b/examples/twittertimeline/main.cpp @@ -100,8 +100,7 @@ int main(int argc, char **argv) if (parser.isSet(connect)) { if (parser.value(token).isEmpty() || parser.value(secret).isEmpty()) { parser.showHelp(); - } - else { + } else { authenticate(); twitterDialog.view->setFocus(); } diff --git a/examples/twittertimeline/twittertimelinemodel.cpp b/examples/twittertimeline/twittertimelinemodel.cpp index 3dee229..625af97 100644 --- a/examples/twittertimeline/twittertimelinemodel.cpp +++ b/examples/twittertimeline/twittertimelinemodel.cpp @@ -43,8 +43,7 @@ #include #include -TwitterTimelineModel::TwitterTimelineModel(QObject *parent) - : QAbstractTableModel(parent) +TwitterTimelineModel::TwitterTimelineModel(QObject *parent) : QAbstractTableModel(parent) { connect(&twitter, &Twitter::authenticated, this, &TwitterTimelineModel::authenticated); connect(&twitter, &Twitter::authenticated, this, &TwitterTimelineModel::updateTimeline); @@ -142,9 +141,7 @@ void TwitterTimelineModel::parseJson() qCritical() << "TwitterTimelineModel::parseJson. Error at:" << parseError.offset << parseError.errorString(); return; - } - - if (document.isObject()) { + } else if (document.isObject()) { // Error received :( const auto object = document.object(); const auto errorArray = object.value("errors").toArray(); diff --git a/tests/qoauth/tst_qoauth.cpp b/tests/qoauth/tst_qoauth.cpp index 0b93174..53fa850 100644 --- a/tests/qoauth/tst_qoauth.cpp +++ b/tests/qoauth/tst_qoauth.cpp @@ -40,7 +40,7 @@ Q_DECLARE_METATYPE(QAbstractOAuth::Error) typedef QSharedPointer QNetworkReplyPtr; -class tst_QOAuth: public QObject +class tst_QOAuth : public QObject { Q_OBJECT @@ -49,10 +49,21 @@ class tst_QOAuth: public QObject int returnCode; using QObject::connect; - static bool connect(const QNetworkReplyPtr &ptr, const char *signal, const QObject *receiver, const char *slot, Qt::ConnectionType ct = Qt::AutoConnection) - { return connect(ptr.data(), signal, receiver, slot, ct); } - bool connect(const QNetworkReplyPtr &ptr, const char *signal, const char *slot, Qt::ConnectionType ct = Qt::AutoConnection) - { return connect(ptr.data(), signal, slot, ct); } + static bool connect(const QNetworkReplyPtr &ptr, + const char *signal, + const QObject *receiver, + const char *slot, + Qt::ConnectionType ct = Qt::AutoConnection) + { + return connect(ptr.data(), signal, receiver, slot, ct); + } + bool connect(const QNetworkReplyPtr &ptr, + const char *signal, + const char *slot, + Qt::ConnectionType ct = Qt::AutoConnection) + { + return connect(ptr.data(), signal, slot, ct); + } public: int waitForFinish(QNetworkReplyPtr &reply); @@ -510,8 +521,8 @@ void tst_QOAuth::authenticatedCalls() QVERIFY(!reply.isNull()); QVERIFY(!reply->isFinished()); - connect(&networkAccessManager, &QNetworkAccessManager::finished, [&receivedData](QNetworkReply *reply) - { + connect(&networkAccessManager, &QNetworkAccessManager::finished, + [&receivedData](QNetworkReply *reply) { receivedData = QString::fromUtf8(reply->readAll()); }); QVERIFY(waitForFinish(reply) == Success); -- GitLab