Commit 1ef97d59 authored by Jesus Fernandez's avatar Jesus Fernandez

Default UserAgent changed

Moved QOAuth1Private private slots moved
Added RFC references to the OAuth1 functions
Removed return in _q_accessTokenRequestFinished
Added copyright comment
parent 41dd2c12
...@@ -8,5 +8,6 @@ win32:CONFIG(release, debug|release): { ...@@ -8,5 +8,6 @@ win32:CONFIG(release, debug|release): {
} else:win32:CONFIG(debug, debug|release): { } else:win32:CONFIG(debug, debug|release): {
DESTDIR = $$OUT_PWD/../../debug DESTDIR = $$OUT_PWD/../../debug
LIBS += $$OUT_PWD/../../debug/QtOAuth.lib LIBS += $$OUT_PWD/../../debug/QtOAuth.lib
} else:unix: {
LIBS += -L$$OUT_PWD/../../QtOAuth/ -lQtOAuth
} }
else:unix: LIBS += -L$$OUT_PWD/../../QtOAuth/ -lQtOAuth
...@@ -81,8 +81,8 @@ public: ...@@ -81,8 +81,8 @@ public:
QString token; QString token;
QString scope; QString scope;
QString state = generateRandomState(); QString state = generateRandomState();
QString userAgent = "qoauth/0.1"; QString userAgent = "QtOAuth/1.0 (+https://www.qt.io)";
const QString bearerFormat = QStringLiteral("Bearer %1"); const QString bearerFormat = QStringLiteral("Bearer %1"); // Case sensitive
QDateTime expiresAt; QDateTime expiresAt;
QString refreshToken; QString refreshToken;
......
...@@ -72,20 +72,6 @@ class OAUTH_EXPORT QOAuth1Private : public QAbstractOAuthPrivate ...@@ -72,20 +72,6 @@ class OAUTH_EXPORT QOAuth1Private : public QAbstractOAuthPrivate
public: public:
QOAuth1Private(QNetworkAccessManager *networkAccessManager = nullptr); QOAuth1Private(QNetworkAccessManager *networkAccessManager = nullptr);
QPair<QString, QString> clientCredentials;
QPair<QString, QString> 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 appendCommonHeaders(QVariantMap *headers);
void appendSignature(QAbstractOAuth::Stage stage, void appendSignature(QAbstractOAuth::Stage stage,
QVariantMap *headers, QVariantMap *headers,
...@@ -101,6 +87,17 @@ public: ...@@ -101,6 +87,17 @@ public:
QString signatureMethodString() const; QString signatureMethodString() const;
static QString operationName(QNetworkAccessManager::Operation op); static QString operationName(QNetworkAccessManager::Operation op);
void _q_onTokenRequestError(QNetworkReply::NetworkError error);
void _q_requestAuthorizationGrantAnswer();
void _q_tokensReceived(const QVariantMap &tokens);
QPair<QString, QString> clientCredentials;
QPair<QString, QString> tokenCredentials;
QString verifier;
QUrl temporaryCredentialsUrl;
QUrl tokenCredentialsUrl;
QOAuth1::SignatureMethod signatureMethod = QOAuth1::SignatureMethod::Hmac_Sha1;
const QString oauthVersion = QStringLiteral("1.0");
struct OAuth1KeyString struct OAuth1KeyString
{ {
......
...@@ -72,7 +72,6 @@ const QString Key::scope = QStringLiteral("scope"); ...@@ -72,7 +72,6 @@ const QString Key::scope = QStringLiteral("scope");
const QString Key::state = QStringLiteral("state"); const QString Key::state = QStringLiteral("state");
const QString Key::tokenType = QStringLiteral("token_type"); const QString Key::tokenType = QStringLiteral("token_type");
QAbstractOAuth2Private::QAbstractOAuth2Private(QNetworkAccessManager *manager) : QAbstractOAuth2Private::QAbstractOAuth2Private(QNetworkAccessManager *manager) :
QAbstractOAuthPrivate(manager) QAbstractOAuthPrivate(manager)
{} {}
......
...@@ -80,77 +80,6 @@ QOAuth1Private::QOAuth1Private(QNetworkAccessManager *networkAccessManager) ...@@ -80,77 +80,6 @@ QOAuth1Private::QOAuth1Private(QNetworkAccessManager *networkAccessManager)
qRegisterMetaType<QNetworkReply::NetworkError>("QNetworkReply::NetworkError"); qRegisterMetaType<QNetworkReply::NetworkError>("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<QNetworkReply *>(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<QString, QString> 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<QString, QString>());
}
} else {
Q_EMIT q->requestFailed(QAbstractOAuth::Error::OAuthTokenNotFoundError);
}
}
void QOAuth1Private::_q_tokensReceived(const QVariantMap &tokens)
{
Q_Q(QOAuth1);
typedef OAuth1KeyString Key;
QPair<QString, QString> 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) void QOAuth1Private::appendCommonHeaders(QVariantMap *headers)
{ {
typedef OAuth1KeyString Key; typedef OAuth1KeyString Key;
...@@ -273,6 +202,77 @@ QString QOAuth1Private::operationName(QNetworkAccessManager::Operation op) ...@@ -273,6 +202,77 @@ QString QOAuth1Private::operationName(QNetworkAccessManager::Operation op)
return QString(); 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<QNetworkReply *>(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<QString, QString> 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<QString, QString>());
}
} else {
Q_EMIT q->requestFailed(QAbstractOAuth::Error::OAuthTokenNotFoundError);
}
}
void QOAuth1Private::_q_tokensReceived(const QVariantMap &tokens)
{
Q_Q(QOAuth1);
typedef OAuth1KeyString Key;
QPair<QString, QString> 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) QOAuth1::QOAuth1(QObject *parent)
: QAbstractOAuth(*new QOAuth1Private, parent) : QAbstractOAuth(*new QOAuth1Private, parent)
{} {}
...@@ -503,12 +503,10 @@ QNetworkReply *QOAuth1::requestTemporaryCredentials(QNetworkAccessManager::Opera ...@@ -503,12 +503,10 @@ QNetworkReply *QOAuth1::requestTemporaryCredentials(QNetworkAccessManager::Opera
if (Q_UNLIKELY(!d->networkAccessManager())) { if (Q_UNLIKELY(!d->networkAccessManager())) {
qCritical("QNetworkAccessManager not available"); qCritical("QNetworkAccessManager not available");
return nullptr; return nullptr;
} } else if (Q_UNLIKELY(url.isEmpty())) {
if (Q_UNLIKELY(url.isEmpty())) {
qCritical() << "Request Url not set"; qCritical() << "Request Url not set";
return nullptr; return nullptr;
} } else if (Q_UNLIKELY(operation != QNetworkAccessManager::GetOperation &&
if (Q_UNLIKELY(operation != QNetworkAccessManager::GetOperation &&
operation != QNetworkAccessManager::PostOperation)) { operation != QNetworkAccessManager::PostOperation)) {
qCritical("Operation not supported"); qCritical("Operation not supported");
return nullptr; return nullptr;
...@@ -639,6 +637,7 @@ QByteArray QOAuth1::parameterString(const QVariantMap &parameters) ...@@ -639,6 +637,7 @@ QByteArray QOAuth1::parameterString(const QVariantMap &parameters)
QByteArray QOAuth1::nonce() QByteArray QOAuth1::nonce()
{ {
// https://tools.ietf.org/html/rfc5849#section-3.3
QString u = QString::number(QDateTime::currentDateTimeUtc().toTime_t()); QString u = QString::number(QDateTime::currentDateTimeUtc().toTime_t());
u.append(QString::number(qrand())); u.append(QString::number(qrand()));
return u.toUtf8(); return u.toUtf8();
...@@ -675,6 +674,7 @@ QByteArray QOAuth1::signature(const QVariantMap &parameters, ...@@ -675,6 +674,7 @@ QByteArray QOAuth1::signature(const QVariantMap &parameters,
const QString &consumerSecret, const QString &consumerSecret,
const QString &tokenSecret) const QString &tokenSecret)
{ {
// https://tools.ietf.org/html/rfc5849#section-3.4
const QByteArray baseString = signatureBaseString(parameters, url, op); const QByteArray baseString = signatureBaseString(parameters, url, op);
QByteArray secret; QByteArray secret;
...@@ -689,6 +689,8 @@ QByteArray QOAuth1::signature(const QVariantMap &parameters, ...@@ -689,6 +689,8 @@ QByteArray QOAuth1::signature(const QVariantMap &parameters,
QByteArray QOAuth1::generateAuthorizationHeader(const QVariantMap &oauthParams) QByteArray QOAuth1::generateAuthorizationHeader(const QVariantMap &oauthParams)
{ {
// https://tools.ietf.org/html/rfc5849#section-3.5.1
// TODO Add realm parameter support
bool first = true; bool first = true;
QString ret(QStringLiteral("OAuth ")); QString ret(QStringLiteral("OAuth "));
QVariantMap headers(oauthParams); QVariantMap headers(oauthParams);
...@@ -708,6 +710,7 @@ QByteArray QOAuth1::generateAuthorizationHeader(const QVariantMap &oauthParams) ...@@ -708,6 +710,7 @@ QByteArray QOAuth1::generateAuthorizationHeader(const QVariantMap &oauthParams)
void QOAuth1::grant() void QOAuth1::grant()
{ {
// https://tools.ietf.org/html/rfc5849#section-2
Q_D(QOAuth1); Q_D(QOAuth1);
typedef QOAuth1Private::OAuth1KeyString Key; typedef QOAuth1Private::OAuth1KeyString Key;
...@@ -762,6 +765,7 @@ void QOAuth1::grant() ...@@ -762,6 +765,7 @@ void QOAuth1::grant()
void QOAuth1::continueGrantWithVerifier(const QString &verifier) void QOAuth1::continueGrantWithVerifier(const QString &verifier)
{ {
// https://tools.ietf.org/html/rfc5849#section-2.3
Q_D(QOAuth1); Q_D(QOAuth1);
typedef QOAuth1Private::OAuth1KeyString Key; typedef QOAuth1Private::OAuth1KeyString Key;
......
...@@ -107,7 +107,6 @@ void QOAuth2AuthorizationCodeFlowPrivate::_q_accessTokenRequestFinished(QNetwork ...@@ -107,7 +107,6 @@ void QOAuth2AuthorizationCodeFlowPrivate::_q_accessTokenRequestFinished(QNetwork
if (reply != currentReply) if (reply != currentReply)
return; return;
if (reply->error() == QNetworkReply::UnknownNetworkError) { if (reply->error() == QNetworkReply::UnknownNetworkError) {
return;
qWarning("QOAuth2AuthorizationCodeFlow: %s", qPrintable(reply->errorString())); qWarning("QOAuth2AuthorizationCodeFlow: %s", qPrintable(reply->errorString()));
setStatus(QAbstractOAuth::Status::NotAuthenticated); setStatus(QAbstractOAuth::Status::NotAuthenticated);
return; return;
......
...@@ -66,8 +66,7 @@ QOAuth2ImplicitGrantFlow::QOAuth2ImplicitGrantFlow(QObject *parent) : ...@@ -66,8 +66,7 @@ QOAuth2ImplicitGrantFlow::QOAuth2ImplicitGrantFlow(QObject *parent) :
QOAuth2ImplicitGrantFlow::QOAuth2ImplicitGrantFlow(QNetworkAccessManager *manager, QOAuth2ImplicitGrantFlow::QOAuth2ImplicitGrantFlow(QNetworkAccessManager *manager,
QObject *parent) : QObject *parent) :
QAbstractOAuth2(*new QOAuth2ImplicitGrantFlowPrivate(manager), parent) QAbstractOAuth2(*new QOAuth2ImplicitGrantFlowPrivate(manager), parent)
{ {}
}
QOAuth2ImplicitGrantFlow::QOAuth2ImplicitGrantFlow(const QString &clientIdentifier, QOAuth2ImplicitGrantFlow::QOAuth2ImplicitGrantFlow(const QString &clientIdentifier,
QNetworkAccessManager *manager, QNetworkAccessManager *manager,
......
/****************************************************************************
**
** 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 <QtCore> #include <QtCore>
#include <QtGui> #include <QtGui>
#include <QtQml> #include <QtQml>
......
...@@ -44,8 +44,7 @@ ...@@ -44,8 +44,7 @@
RedditModel::RedditModel(QObject *parent) RedditModel::RedditModel(QObject *parent)
: QAbstractTableModel(parent) : QAbstractTableModel(parent)
{ {}
}
RedditModel::RedditModel(const QString &clientId, QObject *parent) RedditModel::RedditModel(const QString &clientId, QObject *parent)
: QAbstractTableModel(parent) : QAbstractTableModel(parent)
......
...@@ -100,8 +100,7 @@ int main(int argc, char **argv) ...@@ -100,8 +100,7 @@ int main(int argc, char **argv)
if (parser.isSet(connect)) { if (parser.isSet(connect)) {
if (parser.value(token).isEmpty() || parser.value(secret).isEmpty()) { if (parser.value(token).isEmpty() || parser.value(secret).isEmpty()) {
parser.showHelp(); parser.showHelp();
} } else {
else {
authenticate(); authenticate();
twitterDialog.view->setFocus(); twitterDialog.view->setFocus();
} }
......
...@@ -43,8 +43,7 @@ ...@@ -43,8 +43,7 @@
#include <QtCore> #include <QtCore>
#include <QtWidgets> #include <QtWidgets>
TwitterTimelineModel::TwitterTimelineModel(QObject *parent) TwitterTimelineModel::TwitterTimelineModel(QObject *parent) : QAbstractTableModel(parent)
: QAbstractTableModel(parent)
{ {
connect(&twitter, &Twitter::authenticated, this, &TwitterTimelineModel::authenticated); connect(&twitter, &Twitter::authenticated, this, &TwitterTimelineModel::authenticated);
connect(&twitter, &Twitter::authenticated, this, &TwitterTimelineModel::updateTimeline); connect(&twitter, &Twitter::authenticated, this, &TwitterTimelineModel::updateTimeline);
...@@ -142,9 +141,7 @@ void TwitterTimelineModel::parseJson() ...@@ -142,9 +141,7 @@ void TwitterTimelineModel::parseJson()
qCritical() << "TwitterTimelineModel::parseJson. Error at:" << parseError.offset qCritical() << "TwitterTimelineModel::parseJson. Error at:" << parseError.offset
<< parseError.errorString(); << parseError.errorString();
return; return;
} } else if (document.isObject()) {
if (document.isObject()) {
// Error received :( // Error received :(
const auto object = document.object(); const auto object = document.object();
const auto errorArray = object.value("errors").toArray(); const auto errorArray = object.value("errors").toArray();
......
...@@ -40,7 +40,7 @@ Q_DECLARE_METATYPE(QAbstractOAuth::Error) ...@@ -40,7 +40,7 @@ Q_DECLARE_METATYPE(QAbstractOAuth::Error)
typedef QSharedPointer<QNetworkReply> QNetworkReplyPtr; typedef QSharedPointer<QNetworkReply> QNetworkReplyPtr;
class tst_QOAuth: public QObject class tst_QOAuth : public QObject
{ {
Q_OBJECT Q_OBJECT
...@@ -49,10 +49,21 @@ class tst_QOAuth: public QObject ...@@ -49,10 +49,21 @@ class tst_QOAuth: public QObject
int returnCode; int returnCode;
using QObject::connect; using QObject::connect;
static bool connect(const QNetworkReplyPtr &ptr, const char *signal, const QObject *receiver, const char *slot, Qt::ConnectionType ct = Qt::AutoConnection) static bool connect(const QNetworkReplyPtr &ptr,
{ return connect(ptr.data(), signal, receiver, slot, ct); } const char *signal,
bool connect(const QNetworkReplyPtr &ptr, const char *signal, const char *slot, Qt::ConnectionType ct = Qt::AutoConnection) const QObject *receiver,
{ return connect(ptr.data(), signal, slot, ct); } 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: public:
int waitForFinish(QNetworkReplyPtr &reply); int waitForFinish(QNetworkReplyPtr &reply);
...@@ -510,8 +521,8 @@ void tst_QOAuth::authenticatedCalls() ...@@ -510,8 +521,8 @@ void tst_QOAuth::authenticatedCalls()
QVERIFY(!reply.isNull()); QVERIFY(!reply.isNull());
QVERIFY(!reply->isFinished()); QVERIFY(!reply->isFinished());
connect(&networkAccessManager, &QNetworkAccessManager::finished, [&receivedData](QNetworkReply *reply) connect(&networkAccessManager, &QNetworkAccessManager::finished,
{ [&receivedData](QNetworkReply *reply) {
receivedData = QString::fromUtf8(reply->readAll()); receivedData = QString::fromUtf8(reply->readAll());
}); });
QVERIFY(waitForFinish(reply) == Success); QVERIFY(waitForFinish(reply) == Success);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment